Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to customize DefaultHandlerExceptionResolver logic?

I want to customize DefaultHandlerExceptionResolver in my Spring Boot application but custom implementation was never reached when exception was occurred.

build.gradle

buildscript {
    ext {
        springBootVersion = '2.1.1.RELEASE'
    }
    repositories {
        mavenCentral()
    }
}

plugins {
    id 'java'
    id 'org.springframework.boot' version '2.1.1.RELEASE'
    id 'io.spring.dependency-management' version '1.0.6.RELEASE'
    id 'io.franzbecker.gradle-lombok' version '1.14'
}

lombok {
    version = '1.18.4'
    sha256 = ""
}

group = 'ua.com.javaman'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    implementation('org.springframework.boot:spring-boot-starter-web')
}

Application.java

@SpringBootApplication
@RestController
@Configuration
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @ResponseBody
    @PostMapping("/mouse")
    public Mouse postMouse(@Valid Mouse mouse) {
        // mouse creation logic
        return mouse;
    }

    @Bean
    public HandlerExceptionResolver customHandlerExceptionResolver() {
        return new CustomExceptionHandlerResolver();
    }
}

Mouse.java

@Value
public class Mouse {
    private final Long id;
    @NotEmpty
    @Min(2)
    private final String name;
}

CustomExceptionHandlerResolver.java

public class CustomExceptionHandlerResolver extends DefaultHandlerExceptionResolver {
    @Override
    protected ModelAndView handleBindException(
        BindException ex, HttpServletRequest request, HttpServletResponse response, @Nullable Object handler
    ) throws IOException {
        System.out.println("In CustomExceptionHandlerResolver");
        response.sendError(HttpServletResponse.SC_BAD_REQUEST);
        return new ModelAndView();
    }
}

Package structure

.
├── build.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── LICENSE
├── README.md
├── settings.gradle
└── src
    └── main
        └── java
            └── ua
                └── com
                    └── javaman
                        └── exception_handling
                            ├── Application.java
                            ├── CustomExceptionHandlerResolver.java
                            └── Mouse.java

When I invoke application with wrong values for Mouse entity, for example,

POST localhost:8080/mouse?name=1

than handleBindException() method in DefaultHandlerExceptionResolver is invoked but not in my CustomExceptionHandlerResolver.

How can I handle BindException with my CustomExceptionHandlerResolver?

like image 912
Roman Cherepanov Avatar asked Dec 29 '18 23:12

Roman Cherepanov


People also ask

How do you handle Defaulthandlerexceptionresolver?

Method SummaryHandle the case where an async request timed out. Handle the case where an @ModelAttribute method argument has binding or validation errors and is not followed by another method argument of type BindingResult . Handle the case when a WebDataBinder conversion cannot occur.

How do you handle a spring boot exception?

Exception HandlerThe @ExceptionHandler is an annotation used to handle the specific exceptions and sending the custom responses to the client. Define a class that extends the RuntimeException class. You can define the @ExceptionHandler method to handle the exceptions as shown.

How do you handle exception globally in spring boot?

In Java, exception handling is done by try, catch blocks but spring boot also allows us to provide customized global exception handling where we need not to add try catch block everwhere, we can create a separate class for handling exceptions and it also separates the exception handling code from businesss logic code.

How do you use a controller advice?

@ControllerAdvice is a specialization of the @Component annotation which allows to handle exceptions across the whole application in one global handling component. It can be viewed as an interceptor of exceptions thrown by methods annotated with @RequestMapping and similar.

What is defaulthandlerexceptionresolver in Spring MVC?

Spring MVC may throw a number of exceptions internally while processing a request. These exceptions are handled by DefaultHandlerExceptionResolver. The important aspect of this resolver is, it translates the internal exception to specific HTTP status codes.

What happens if the default exception handler is not working properly?

If these functions are developed without perfect processing of exception capture or even the logic itself exists BUG, it may lead to the exception not being properly captured and processed, and the default exception handler DefaultErrorWebExceptionHandler, the processing logic of the default exception handler may not meet our expected results.

Can I customize the logic of a process builder?

Can I customize the logic of a process builder as below? Yes, You can add this in the process builder.

What is defaulterrorwebexceptionhandler gethttpstatus?

DefaultErrorWebExceptionHandler#getHttpStatus () is a wrapper for the response status code, the original logic is based on the status attribute of the exception property getErrorAttributes () for parsing. The custom JsonErrorWebExceptionHandler is as follows.


1 Answers

SpringBoot 's auto configuration will always create a bunch of exception handlers by default which one of them is DefaultHandlerExceptionResolver at order 0 (lower value has the higher priority) . Your handler by default will has lower priority than these default , so it will not be invoked as the exception is already handled by the default.

You can implement your configuration class with WebMvcConfigurer and override extendHandlerExceptionResolvers() to modify the default settings. The idea is to find out the DefaultHandlerExceptionResolver instance and replace it with yours.

But a better idea is to define your CustomExceptionHandlerResolver with @ControllerAdvice , which make sure that you will not mess up with the default settings while still add the customised behaviour that your want (i.e use your logic to handle BindException) :

@Component
@ControllerAdvice
public class CustomExceptionHandlerResolver {

    @ExceptionHandler(value= BindException.class)
    @Override
    protected ModelAndView handleBindException(
            BindException ex, HttpServletRequest request, HttpServletResponse response, @Nullable Object handler)
            throws IOException {
        System.out.println("In CustomExceptionHandlerResolver");
        response.sendError(HttpServletResponse.SC_BAD_REQUEST);
        return new ModelAndView();
    }

}
like image 75
Ken Chan Avatar answered Sep 28 '22 12:09

Ken Chan