Spring Boot - Pass Exception object from ResponseEntityExceptionHandler to HandlerInterceptor? - spring

I am working on Spring Boot Example and implemented GlobalExceptionHandler and trying to print all error messages in JSON - it's my custom method.
Also, I have ExceptionHandler there I am catching all the Exception. But is there any way to pass the exception object from ResponseEntityExceptionHandler to HandlerInterceptor?
HandlerInterceptor:
#Slf4j
public class GlobalExceptionHandler implements HandlerInterceptor {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
............
.............
..............
return true;
}
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
ServletRequestAttributes attributes = (ServletRequestAttributes) request.getAttribute(REQUEST_ATTRIBUTES);
ServletRequestAttributes threadAttributes = (ServletRequestAttributes) RequestContextHolder
.getRequestAttributes();
............
.............
..............
}
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
if(ex != null) {
printJsonReq(request, response);
}
}
}
ExceptionHandler:
#ControllerAdvice
#Slf4j
public class ExceptionHandler extends ResponseEntityExceptionHandler{
#ExceptionHandler({ResponseStatusException.class})
protected ResponseEntity<Object> handleResStatusException(Exception e, WebRequest request, HttpServletRequest httpRequest) {
ResponseStatusException be = (ResponseStatusException) e;
ErrorResource error = ErrorResource.builder().code(AppConst.BAD_REQUEST)
.message(ExceptionUtils.getDetails(e.getCause())).build();
return handleExceptionInternal(e, error, getHeaders(), HttpStatus.BAD_REQUEST, request);
}
.........
..........
.........
}

You can set it as a request attribute in ExceptionHandler class (if you need it just to be sure you are going print log then instead of passing Exception object you can pass boolean param to not load your request object)
request.setAttribute("exception", e);
And use it in your HandlerInterceptor as
if(ex != null || request.getAttribute("exception") != null) {
printJsonReq(request, response);
}

You can configure the interceptors using WebMvcConfigurerAdapter
17.15.3 Configuring Interceptors
You can configure HandlerInterceptors or WebRequestInterceptors to be applied to all incoming requests or restricted to specific URL path patterns.
An example of registering interceptors in Java:
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new GlobalExceptionHandler());
}
}

Related

How do I get the rest path in a HandlerInterceptorAdapter without resolved path variables

I have a problem with my RestController interceptor.
My goal is to get the RestController path in a HandlerInterceptorAdapter and then use it to create metrics.
Via the interface HttpServletRequest I have access to the path, but it is resolved there.
Example of what I would like to get in my interceptor:
GET: object/123 // wrong
GET object/{id} // right
Is there any way to get the path without resolved variables?
Here is my implementation:
RestController:
#RestController
public class ObjectController
{
#GetMapping("object/{id}")
public String getObjectById(#PathVariable String id)
{
return id;
}
}
Config:
#Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter
{
#Override
public void addInterceptors(InterceptorRegistry registry)
{
registry.addInterceptor(new RequestInterceptor());
}
}
Interceptor:
public class RequestInterceptor extends HandlerInterceptorAdapter
{
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception
{
System.out.println(request.getRequestURI());
return true;
}
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
#Nullable ModelAndView modelAndView) throws Exception
{
System.out.println(request.getRequestURI());
}
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
#Nullable Exception ex) throws Exception
{
System.out.println(request.getRequestURI());
}
}

i am trying to add interceptors to spring project,my prehandle method is not getting called

I want my prehandle method to be called.On debugging i see the control going inside ProductServiceInterceptor class but none of the methods inside are getting called
#EnableWebMvc
#Configuration
public class ProductServiceInterceptorAppConfig extends WebMvcConfigurerAdapter {
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new productServiceInterceptor()).addPathPatterns("/home/*"));
}
}
#Component
public class ProductServiceInterceptor implements HandlerInterceptor {
#Override
public boolean preHandle(
HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
#Override
public void postHandle(
HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {}
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception exception) throws Exception {}
}

Avoid logging Swagger Endpoints when you implement HandlerInterceptor?

I have implemented Spring Boot + springfox-swagger-ui and HandlerInterceptor to log the request for my application. When I start my application following all swagger related endpoint are getting called and all those endpoint are logging into request shown below.
/webjars/springfox-swagger-ui/fonts/source-code-pro-v7-latin-300.woff2
/webjars/springfox-swagger-ui/fonts/open-sans-v15-latin-700.woff2
/webjars/springfox-swagger-ui/fonts/source-code-pro-v7-latin-300.woff2
/webjars/springfox-swagger-ui/fonts/open-sans-v15-latin-700.woff2
.....
.....
LogRequestInterceptor.java
#Slf4j
public class LogRequestInterceptor implements HandlerInterceptor {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
ServletRequestAttributes attributes = new ServletRequestAttributes(request);
.................
.................
.................
return true;
}
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
printJsonReq(request, userIdentityService.getUserName(), response.getStatus(), getTime(request), handler);
}
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
printJsonReq(request, userIdentityService.getUserName(), response.getStatus(), getTime(request), handler);
}
}
How Can I prevent logging those requests in HandlerInterceptors preHandle and postHandle and afterCompletion methods ?
In the following link you can view an example: https://www.baeldung.com/spring-http-logging
I think that is usefull for your problem

Why does the spring boot controller not invoked after calling request.getReader in preHandle

I am implementing an interceptor for logging purposes. I know once i called the getReader method on HttpServletRequest will loose the body data, but i was experimenting. So i ran the below code, and realized the controller is never invoked (Debug point is not activated) and there was no errors.
#Component
public class IncomingRequestInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
String requestPayload = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
System.out.println(requestPayload);
return super.preHandle(request, response, handler);
}
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
super.afterCompletion(request, response, handler, ex);
}
}
And the controller
#PostMapping("/test")
public String test(#Valid #RequestBody CredentialsVo credentials) {
credentials.getUsername();
.............
return "test";
}
Filter Registration
#Configuration
public class MyConfig implements WebMvcConfigurer {
#Autowired
IncomingRequestInterceptor incomingRequestInterceptor;
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(incomingRequestInterceptor)
.addPathPatterns("/**");
}
}
if i do not call getReader() method, the controller is invoked. I was actually expecting the controller is called but i would get a null pointer or something like that.
Could anyone tell me how spring acts in this scenario ?

I'm looking for the way to handle pre & post processing of Controller in Spring Boot + thymeleaf

I have been looking for the way to handle pre & post processing of controller.
I want to add a procedure for every request & response.
For example:
Checking every requested header or adding hidden field include hash code in every form tags we response.
If there is sample, or any idea,give me please.
Thanks for advice.
I was able to find the result from this page.
http://www.concretepage.com/spring/spring-mvc/spring-handlerinterceptor-annotation-example-webmvcconfigureradapter
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addInterceptors(InterceptorRegistry registry) {
super.addInterceptors(registry);
registry.addInterceptor(new ControllerHandler());
TransactionInterceptor transactionInterceptor = new TransactionInterceptor();
}
}
public class ControllerHandler implements HandlerInterceptor {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("---Before Method Execution---");
return true;
}
#Override
public void postHandle( HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("---method executed---");
}
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
System.out.println("---Request Completed---");
}
}
I found another way to do,using #ControllerAdvice.
This annotaion seems to focus Error Handling.
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/ControllerAdvice.html1
#ControllerAdvice
public class ExceptionControllerAdvice {
#InitBinder
public void initBinder(WebDataBinder binder) {
System.out.println("controller advice: init binder");
}
#ExceptionHandler(Exception.class)
public String exception(Exception e) {
System.out.println("controller advice: exception Handler");
System.out.println(e.getMessage());
return "error";
}
#ModelAttribute
public void modelAttribute(){
System.out.println("controller advice:model Attribute");
}
}

Resources