how to get controller method name in Spring Interceptor preHandle method - spring-mvc

In my application based on spring mvc and spring security I am using #Controller annotation to configure controller.
I have configured Spring Handler Interceptor and in preHandle() method , I want to get method name which is going to be call by interceptor.
I want to get custom annotation defined on controller method in preHandle() method of HandlerInterceptor so that I can manage by logging activity for that particular method.
Please have a look at my application requirement and code
#Controller
public class ConsoleUserManagementController{
#RequestMapping(value = CONSOLE_NAMESPACE + "/account/changePassword.do", method = RequestMethod.GET)
#doLog(true)
public ModelAndView showChangePasswordPage() {
String returnView = USERMANAGEMENT_NAMESPACE + "/account/ChangePassword";
ModelAndView mavChangePassword = new ModelAndView(returnView);
LogUtils.logInfo("Getting Change Password service prerequisit attributes");
mavChangePassword.getModelMap().put("passwordModel", new PasswordModel());
return mavChangePassword;
}
}
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// here I want the controller method name(i.e showChangePasswordPage()
// for /account/changePassword.do url ) to be called and that method annotation
// (i.e doLog() ) so that by viewing annotation , I can manage whether for that
// particular controller method, whether to enable logging or not.
}
I am using SPRING 3.0 in my application

Don't know about the Handler interceptor, but you could try to use Aspects and create a general interceptor for all your controller methods.
Using aspects, it would be easy to access your joinpoint method name.
You can inject the request object inside your aspect or use:
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
To retrieve it from your advice method.
For instance:
#Around("execution (* com.yourpackages.controllers.*.*(..)) && #annotation(org.springframework.web.bind.annotation.RequestMapping)")
public Object doSomething(ProceedingJoinPoint pjp){
pjp.getSignature().getDeclaringType().getName();
}

Related

get or pass values from jsp to spring mvc controller with #RequestParam("VIEW") annotation

Hi everyone I'm trying to get or pass the values from my JSP to my controller because I want to write a method whose main function will be to save a new user in the database but I got an error like this:
(((java.lang.IllegalStateException: Mode mappings conflict between method and type level: [/myPath] versus [VIEW])))
I guess this two annotations, first in the class declaration #RequestMapping("VIEW") and the second in the method declaration for save the new user
#RequestMapping(value="/saveUser", method = RequestMethod.POST)
are in conflict by the use of the same annotation in tow times at the same controller but I have to say that I´ve been tried to remove the #RequestMapping annotation in the class declaration and after that, I get a different error like this:
(((java.lang.IllegalStateException: No portlet mode mappings specified - neither at type nor at method level)))
I don't know if I can use as many necessary controllers for differents operations as I will need, if I can, I will be happy to know the correct way to implement with this technique
Here is my controller:
#Controller
#RequestMapping("VIEW")
public class UsersController {
User currentUser = null;
#RenderMapping
public ModelAndView view(RenderRequest request, RenderResponse response)throws Exception {
ModelAndView modelView = new ModelAndView();
UserDTO usuarioAdd = new UserDTO();
//blah, blah, blah...
return modelView;
}
#RequestMapping(value="/saveUser", method=RequestMethod.POST)
public void saveUser(HttpServletRequest request) {
logger.info("***SAVE USER***);
System.out.println("***SAVE USER***);
}
}

Why is Spring exception handler not working as expected

When I use #ExceptionHandler within Controller, it's not working as expected.
Here is my code:
#Controller
public class PageController {
#RequestMapping("/page")
public ModelAndView index(ModelAndView modelAndView){
String mess = null;
mess.split(",");
modelAndView.setViewName("index");
return modelAndView;
}
#ExceptionHandler({Exception.class})
#ResponseStatus(value = HttpStatus.BAD_REQUEST, reason = "Bad Request")
public ModelAndView handleException(Exception ex, HttpServletRequest request, HttpServletResponse response){
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("message", ex.getMessage());
modelAndView.addObject("url", request.getRequestURL());
modelAndView.addObject("code", response.getStatus());
modelAndView.setViewName("exception");
return modelAndView;
}
}
After the application starts with debug mode, I visit http://localhost:8080/page, and handleException is running, but the view is below other than the expected excepction view. Why?
The problem is with the #ResponseStatus annotation. Have a look at the following article: http://blog.sizovs.net/spring-rest-exception-handler/. In the mid of this article the author says following:
Warning: when using this annotation on an exception class, or when setting the reason attribute of this annotation, the HttpServletResponse.sendError method will be used.
With HttpServletResponse.sendError, the response is considered complete and should not be written to any further. Furthermore, the Servlet container will typically write an HTML error page therefore making the use of a reason unsuitable for REST APIs. For such cases it is preferable to use a org.springframework.http.ResponseEntity as a return type and avoid the use of #ResponseStatus altogether.
According to a Spring article: https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc, Spring MVC chains the following three resolvers in the order below:
ExceptionHandlerExceptionResolver matches uncaught exceptions against for suitable #ExceptionHandler methods on both the handler (controller) and on any controller-advices.
ResponseStatusExceptionResolver looks for uncaught exceptions annotated by #ResponseStatus (as described in Section 1)
DefaultHandlerExceptionResolver converts standard Spring exceptions and converts them
to HTTP Status Codes (I have not mentioned this above as it is internal to Spring MVC).
So the ResponseStatusExceptionResolver is triggered after the ExceptionHanlderExceptionResolver and uses the default and will display Spring's error page.
For a quick fix try to remove #ResponseStatus and you should see your custom error page in your browser.

Spring log request payload

I want to log every incoming request data and payload(body). How to configure that in Spring Boot? And how to hide sensitive data like password in logs?
Is it possible to log the original 'raw' request body (e.g. JSON)?
You could use AOP (Aspect Oriented programming) and intercept all the requests and log the info you need. Also you can filter which kind of requests need to log. An example with Spring-Boot could be this code
If you want to skip some methods from the logging in the aspect you can add this:
Create an annotation
#Retention(RetentionPolicy.RUNTIME)
public #interface NoLogging {}
#Aspect
#Component
public class LogsAspect {
private static final Logger LOGGER = LoggerFactory.getLogger(EventAspect.class);
#Before("execution(* com.your.controller..*Controller.*(..)) && !#annotation(NoLogging)")
public void beforeController(JoinPoint joinPoint){
String packageName = joinPoint.getSignature().getDeclaringTypeName();
String params = getArguments(joinPoint);
String methodName = joinPoint.getSignature().getName();
//Log here your message as you prefer
}
}
And in any method from your Controllers, if you want to avoid the logging by aspects add the annotation
#RequestMapping(value = "/login", method = RequestMethod.GET)
#NoLogging
public ModelAndView loginUser(){
//actions
}
IMO, to log any incoming request should place at webserver level instead of application level.
For example, you could turn on/off access_log at Nginx.

Intercept #RequestBody after serialization but before controller

My request body objects all implement a interface call Auditable, where the username and lastUpdate timestamp could be set. I would like to intercept calls to controller functions after serialization but before it hits controller so can I can these values in a single place.
I looked at HandlerInterceptor.prehandle but this method executes before serialization. Any suggestion on how I can make this happen?
You can use ControllerAdvice and it can help in these scenarios. It intercepts all controller requests and you can access the serialized domain object in the method. It can pretty much all args that a requestMapping method takes. Hope this helps.
#ControllerAdvice
public class ControllerAdvisor {
#ModelAttribute
public void addAttributes(HttpServletRequest request, HttpServletResponse response,Model model, #RequestBody DomainObject domain) {
domain.setUserName("test");
// set other items that you want to do.
}
}

Spring Controller - Fill DTO from Servlet Request manually

In Spring controller, I want to invoke same method for different HTML - Forms submission
So, taking HttpServletRequest as a RequestBody
#RequestMapping(value = "/Search")
public String doSearch(HttpServletRequest httpServletRequest, ModelMap map) {
// Now, looking for something like this...
if(req.getType.equals("x")
//X x = SOME_SPRING_UTIL.convert(httpServletRequest,X.class)
else
// Y y = SOME_SPRING_UTIL.convert(httpServletRequest,Y.class)
}
I want to convert request parameters to bean through Spring, As it converts while I take Bean as method argument
Use the params attribute of the #RequestMapping annotation to differentiate the request mapping mapping.
#RequestMapping(value="/search", params={"actionId=Actionx"})
public String searchMethod1(X search) {}
#RequestMapping(value="/search", params={"actionId=ActionY"})
public String searchMethod2(Y search) {}
This way you can create methods for each different action and let spring do all the heavy lifting for you.

Resources