Spring-webflux, how to get the request as parameter in #ExceptionHandler - spring

With spring webflux and the #RestController model, I have a #RestControllerAdvice with some #ExceptionHandler methods.
I would like to get the original request as parameter because I want to log it and use it in my response.
However I have tried all the possible types for an handler method in the classic MVC model but none of them was accepted (HttpServletRequest, WebRequest and ServerRequest).
What type can I use to access the original request in a webflux annotated handler method ?

You should use org.springframework.http.server.reactive.ServerHttpRequest, because:
HttpServletRequest and WebRequest are Servlet/Spring MVC specific
ServerRequest belongs to Spring WebFlux, but the functional variant

Related

Do SpringBoot annotations like GetMapping use Spring AOP internally?

A maybe dumb question from a Spring Boot beginner.
I'm reading materials about AOP, and feel like the processing of a lot of annotations (including GetMapping and PostMapping) fits natually with AOP - we have a common concern (say, all functions annotated with GetMapping be treated as HTTP GET method) that is distributed over many different classes.
So does Spring internally use AOP to implement its handlers for stuff like GetMapping?
No, Spring does not use AOP in order to find the correct handler for the requested URI.
That's essentially the job of the DispatcherServlet.
#GetMapping, #PostMapping, #PutMapping, #PatchMapping, #DeleteMapping are all shortcuts for their respectives #RequestMapping annotations.
The DispatcherServlet is a front controller that handles the incoming requests and delegates them to the correct handler.
When a request arrives, the DispatcherServlet uses HandlerMappings and HandlerAdapters from the WebApplicationContext to delegate the request to the appropriate handler. Of course it's a lot more complicated then just that and there's a lot of engineering going on.
The DispatcherServlet doesn't invoke the handler method directly, instead, the HandlerAdapter interface is used. Specifically, in the case of #RequestMapping annotations and it's shortcuts, the RequestMappingHandlerAdapter is used together with the RequestMappingHandlerMapping.
The RequestMappingHandlerMapping is used by the DispatcherServlet to obtain the handler object (when using #RequestMapping in a class instead of a method) and the handler method (when using #RequestMapping and it's shortcuts in a method). This class is responsible for creating the RequestMappingInfo for each #RequestMapping annotated class or method, so, basically, it maps the corresponding handlers to it's paths.
The RequestMappingHandlerAdapter is used to invoke the handler method through the RequestMappingHandlerAdapter#invokeHandlerMethod (see here)
So no, Spring doesn't use AOP in this case. It's a lot of intelligent mapping going on.

How control advice catches exception

I am trying to understand how ControllerAdvice is working in SpringBoot. It is suggested that for per application there should be one ControllerAdvice. But my question is how this ControllerAdvice is tied to Controllers and catching the exceptions. So basically what is the underhood?
Spring AOP works with proxies.
That is when you annotate a class with any of AOP annotation spring will create a proxy class by extending your annotated class and all the methods will be overridden there in the proxy class.
Thus here after when you call a method in your class spring will call the proxy object method first then your actual method. This is Spring AOP knows whether the method has been called or thrown some exception or returned successfully etc etc.
This is the reason why when you call a private method with in the class AOP cannot intercept that method call.

Why Spring Boot throws different exceptions for Controller method argument validations?

While validating a primitive type or their equivalent (Integer, Boolean) using constraints validation annotations (#Min, #NotNull, ...) Spring Boot throws ConstraintViolationException. But when validating a parameter using the #Valid annotation then MethodArgumentNotValidException is thrown.
I have a class annotated with #ControllerAdvice to handle the exceptions from the Controllers.
The problem is that depending on the spring-boot-starter-parent version, the results are pretty much different.
While using the version 2.0.5.RELEASE I just needed to include a handler for the ConstraintViolationException class.
But there are some others versions that MethodArgumentNotValidException is thrown too.
It already was mentioned on a GitHub issue, but no useful answer...
I'll use the lukasniemeier-zalando's example here. For more detail click on the link above.
#Validated // needed to actually trigger validation
#RestController
class MyController {
#RequestMapping
Response serve(
#RequestParam #Min(2) Integer parameter, // throws ConstraintViolationException
#RequestBody #Valid BodyModel body // throws MethodArgumentNotValidException
) {
return new Response();
}
}
I would expect that both validations throws the same exception, no matter which of them, just to be consistent.
Apearently there's no reason to this to be like it is, at least it was what I understood from this other GitHub issue.
Then I just want a answer why Spring Boot throws 2 types of exception to represent the same problem (argument validation).
Note: as mentioned before, using the version 2.0.5.RELEASE of the spring-boot-starter-parent it doesn't happens.
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
But as reported by the last GitHub issue that I linked, the version 2.0.0.M4 has this behavior, and I also experienced it with the 2.2.0.M3 version.
They are handled by different validation mechanisms. The #Validated on the class is handled by the MethodValidationInterceptor which is a generic purpose validation mechanism for classes. Due to this it throws a ConstraintViolationException. The #Validated is used here simply because the #Valid annotation isn't allowed on types. Hence the only way to enable/trigger the MethodValidationInterceptor is by using the #Validation annotation.
The #Valid on the method argument in a controller is handled by the ModelAttributeMethodProcessor internally and leads to a web specific binding exception, the MethodArgumentNotValidException. The ModelAttributeMethodProcessor is called (indirectly) from the RequestMappingHandlerAdapter when preparing the method invocation. Instead of #Valid you could also use the #Validated annotation on the method argument. Spring MVC supports both (it actually supported #Validated before #Valid even existed!).
The solution/workaround is to create your own exception-handler which handles the ConstraintViolationException the same as a MethodArgumentNotValidException. Which is also suggested in the GitHub issue you link to.

Spring: Inject initialized RestTemplates

Currently I have several services making requests to other services.
In order to build the requests I'm using Spring RestTemplates.
Is there anyway to inject a RestTemplate initialized with some headers...?
I was thinking about Factory injectors.
Any ideas?
I think you are approaching the problem incorrectly.
Instead of injecting a RestTemplate,
consider injecting an HttpEntity<?>.
Setup the HttpEntity<?> bean in your configuration #Bean method.
Then use which ever RestTemplate.exchange() method is appropriate to send your desired request.
Edits
The exchange method sends an HTTP message and returns the response.
Here is the RestTemplate JavaDoc Page

What does context annotation do in Spring?

In Rest API design, I am wondering what the exact purpose of the context annotation is?
private HttpServletRequest request;
#Context
public void setRequest(final HttpServletRequest req) {
request = req;
}
The purpose is to indicate that the request property should be set from the context.
#Context is used to inject various HTTP-ish contextual data, from here:
In general #Context can be used to obtain contextual Java types related to the request or response.
API docs (Not horribly useful IMO. Or, perhaps more accurately, horribly-useful.)
This annotation is used to inject information into a class field, bean property or method parameter.
JAX-RS #Context to get the ServletContext, and WebApplicationContextUtils to get the Spring application context, with this Spring application context, you are able to access and get beans from Spring container

Resources