what is the difference between posthandle and aftercompletion in handlerinterceptor in SpringMVC - model-view-controller

To learn more about the difference between posthandle and aftercompletion, I feel that they have the same function. How to choose posthandle or aftercompletion in actual business? thank you

Related

Spring Interceptor and AuthenticationFilter Order of Execution

I have a LoginHandler and an Interceptor. I want the Interceptor to execute before the AuthenticationFilter. Is there a way to specify the order of execution?
UPDATED:
The title mentioned LoginHandler. I changed it to AuthenticationFilter.
A HandlerInterceptor from Spring will never execute before a filter.
The javax.servlet.Filter is part of the Java Servlet API and requests always first pass through Filter instances, before reaching a Servlet.
HandlerInterceptor instances are executed as part of the request handling inside the DispatcherServlet (which implements javax.servlet.Servlet). As mentioned the flow is Filter -> Servlet the result is that a HandlerInterceptor will always execute after a Filter.
So is what you want possible, no it isn't. No matter how much ordering you add to the HandlerInterceptor.

Good idea using ControllerAdvice to perform REST authentication of a request?

In my current Spring Boot application i seem to hit a wall when trying to implement a REST request filter. My goal with the request filter was to read the header and body part and validate the incoming data and check if it meets the HMAC construction we are using.
So the request filter seemed not to work an alternative solutions is to use #ControllerAdvice.
Then the request validation can be implemented very easy. But i am not sure if it normally seen as an incorrect usage of the #ControllerAdvice annotation.
#ControllerAdvice
public class GenericWebControllerAdvice {
#ModelAttribute
public void authenticationFilter(#RequestHeader(value = "Authorization") String authHeader, #RequestBody String payload) {
// process authentication based on header info and body content
// calculate the hash and check if meets the security settings
// if the hash fails throw an exception that returns a http status code
}
}
Any comments on the solution or alternatives that are better?
No you should do the validation in the controller (ie method with #RequestMapping).
Spring supports JSR 303/349 bean validation. Thus if your request body is a POJO and you have the correct annotation Spring will automatically do the validation for you. There is a tutorial of that here:
http://www.leveluplunch.com/java/tutorials/017-validate-spring-rest-webservice-request/
As for request parameter validation (ie not bean validation) I have had to make my own transfer objects and exception handling. How you do global exception handling is covered in the Spring Reference guide but generally you extend and/or register a org.springframework.web.servlet.handler.SimpleMappingExceptionResolver. Ironically #ControllerAdvice can be used for exception handling but I find it better to extend and register an Exception Resolver. More info can be found here:
https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-exceptionhandlers
Edit based on OP comments and edits:
If your doing authentication or some other request based validation/authorization its probably best to use an Interceptor. Reference doc. #ControllerAdvice will probably not work as the request handling is too far a long. That is you want something before databinding happens.

ControllerAdvice ExceptionHandler not called from PropertyEditorSupport

I'm using Spring 3.2.1 and have a PropertyEditorSupport to force a parameter I'd like autoconverted to an enum to uppercase so it converts wrong-cased parameters. An IllegalArgumentException can be thrown if the parameter String can't be converted to the enum. My problem is that the status code is returned as 500 when it ought to be 400. I created a ResponseEntityExceptionHandler annotated with #ControllerAdvice and with a method annotated #ExceptionHandler (IllegalArgumentException.class), intending to set the status code there, but the method is never called when the exception is thrown. Why not? Is it the same problem as discussed here, MaxUploadSizeExceededException doesn't invoke the exception handling method in Spring ? i.e.
"...the exception is thrown before the request has reached the
dispatcher servlet. Therefore your exceptionhandler isn't called
because at the point the exception is thrown the target controller has
yet to be determined."
If so how can I return the proper status code?
Short version:
Put #ExceptionHandler(Exception) annotated method in #Controller class.
Longer version:
I noticed that the #ExceptionHandler(XxxException.class) annotated method in #ControllerAdvice class will only be called if XxxException happens "after" entering the method with matching #RequestMapping.
Conditions like MaxUploadSizeExceededException and MethodArgumentNotValidException will cause SpringMVC to NOT enter the #RequestMapping method, so advice is not applied.
My solution was to sadly place #ExceptionHandler(XxxException.class) annotated method in the actual controller class. Not nice but works.
Hope this helps. If someone knows of a better solution (when using #ControllerAdvice), do share.

Spring WebMVC: interceptor which has access to the method definition and the HttpServletRequest

I'm trying to intercept Spring Controller calls which are annotated, similar to:
#RequestMapping("/my/page")
#AccessRestriction(module = Module.Audit, action = AuditActions.Log)
public ModelAndView myPage() {
// pls type teh codez
}
At this point I want to access both the values of the #AccessRestriction method, the HttpServletRequest object to check if the values match the restrictions and the HttpServletResponse object in order to send a redirect , if applicable. Being able to throw an exception might be suitable as well.
I've looked into Interceptors but they don't offer access to the method, just the handler. What are my options of achieving this?
My suggestion would be to decouple the two concerns, one to check the annotation and throw an exception, another to catch that exception and translate it into a redirect.
The first concern could be done using the Auto-proxy facility, which would apply an AOP-style interceptor to any invocations on your controller objects. They would check for the annotation, validate the invocation, and throw a custom RuntimeException is the conditions are violated.
You could then have a custom HandlerInterceptor which checked for this exception in the afterCompletion method, sending a redirect via the response object if it's present.

Calling #Controller methods once per request

Is there a nice way to have Spring's #Controller classes to call a specific method once per request?
Right now I'm using a method annotated with #InitBinder for this purpose, but this is suboptimal as #InitBinder methods get called several times per request. I just want to do some initialization / update stuff to use in my controllers.
What I'm looking for is something like Rails' before_filter, but as far as I can tell there's no functionality like that in Spring.
Sounds like you need a request-scoped controller bean. Spring will create a new instance of the controller for each request, and will initialize the bean each time using the standard mechanisms like #PostConstruct.

Resources