Skip to content

Complete, ready to use exception handling for Spring Boot REST services.

License

Notifications You must be signed in to change notification settings

mkopylec/errorest-spring-boot-starter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

87 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ErroREST Spring Boot Starter

Build Status Coverage Status Maven Central

Complete, ready to use exception handling for Spring Boot REST services.

Features

  • unified HTTP response format for every unhandled exception (thrown from controllers or servlet filters)
  • unified exception log format
  • JSON and XML HTTP response body types
  • configurable HTTP response body format
  • support for custom exceptions
  • support for Bean Validation exceptions
  • support for Spring Web 4xx errors
  • RestTemplate that supports ErroREST HTTP responses
  • support for Spring Security exceptions

Installing

repositories {
    mavenCentral()
}
dependencies {
    compile 'com.github.mkopylec:errorest-spring-boot-starter:2.0.0'
}

HTTP response format

The starter maps all unhandled exceptions to specific ErroREST HTTP responses.

JSON format

If the incoming HTTP request contains Accept: application/json header, the HTTP response will contain Content-Type: application/json header. The response body will be:

{
    "id":"<random id>",
    "errors":[
        {
            "code":"<some error code>",
            "description":"<some error description>"
        }
    ]
}

XML format

If the incoming HTTP request contains Accept: application/xml header, the HTTP response will contain Content-Type: application/xml header. The response body will be:

<body>
    <id>random id</id>
    <errors>
        <error>
            <code>some error code</code>
            <description>some error description</description>
        </error>
    </errors>
</body>

Log format

All unhandled exceptions are logged using the following template:

ID: <random id> | <http request method> <http request uri> <http response status> | <some error code>: <some error description> | <another error code>: <another error description> | ...

Exceptions are always logged with stack trace.

Basic usage

To start using the starter in a REST service the service must be a Spring Boot web application:

@SpringBootApplication
public class Application {

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

No extra configuration and no custom exception handler is needed to ensure that all thrown exceptions will be properly mapped to ErroREST HTTP responses.

Advanced usage

The starter supports the following features to make error handling as easy as possible.

HTTP response body type

By default response body includes error codes and descriptions. To hide error descriptions set an appropriate configuration property:

errorest.response-body-format: without_descriptions

Custom exceptions

Custom exceptions can be configured how they will be mapped to ErroREST HTTP responses by extending ApplicationException, for example:

public class SampleApplicationException extends ApplicationException {

    public SampleApplicationException(String message, Throwable cause) {
        super(new ApplicationExceptionConfiguration()
                .withResponseHttpStatus(BAD_REQUEST)
                .withLoggingLevel(WARN)
                .withCause(cause)
                .addError("SAMPLE_ERROR_CODE", message)
        );
    }
}

The SampleApplicationException from the example will be mapped to ErroREST HTTP response with 400 (bad request) status and body like so:

{
    "id":"<random id>",
    "errors":[
        {
            "code":"SAMPLE_ERROR_CODE",
            "description":message
        }
    ]
}

The exception will be logged as warning.

Bean Validation exceptions

The starter is able to map Bean Validation exceptions to ErroREST HTTP responses with 422 statuses (unprocessable entity). For this kind of exceptions a validation constraint message is mapped to an error code and an error description becomes a description of the invalid value. For example, if the following validation fails:

public class SampleRequestBody {

    @NotNull(message = "EMPTY_MESSAGE")
    private String message;
    @Max(message = "NUMBER_TOO_BIG", value = 10)
    private int number;

    ...
}

the result will mapped to ErroREST HTTP response with body:

{
    "id":"<random id>",
    "errors":[
        {
            "code":"EMPTY_MESSAGE",
            "description":"Invalid 'message' value: null"
        },        
        {
            "code":"NUMBER_TOO_BIG",
            "description":"Invalid 'number' value: 11"
        }
    ]
}

By default all validation errors are logged with WARN level. To change the logging level set an appropriate configuration property:

errorest.bean-validation-error.logging-level: <logging level>

HTTP 4xx errors

Spring Web includes a set of generic exceptions that represents HTTP client errors, for example HttpMessageNotReadableException or HttpRequestMethodNotSupportedException. Those exceptions are automatically mapped to ErroREST HTTP responses with a proper HTTP statuses. By default 4xx HTTP errors are logged with WARN level. To change the logging level set an appropriate configuration property:

errorest.http-client-error.logging-level: <logging level>

RestTemplate

The starter includes a special RestTemplate called ErrorestTemplate which fully supports ErroREST HTTP responses. The ErrorestTemplate in case of HTTP error throws ExternalHttpRequestException which extends HttpStatusCodeException. The ExternalHttpRequestException overrides the getMessage() method to return much more detailed information about HTTP error than HttpStatusCodeException. It also defines getResponseBodyAsErrors() method which maps ErroREST HTTP response bodies to Errors objects. The usage of ErrorestTemplate is the same as of normal RestTemplate:

    RestOperations client = new ErrorestTemplate();
    try {
        client.getForObject("http://exmaple.com", String.class);
    } catch (ExternalHttpRequestException ex) {
        String detailedMessage = ex.getMessage();
        Errors errors = ex.getResponseBodyAsErrors();
        ...
    }

If the ExternalHttpRequestException will not be handled manually it will be handled automatically by the starter. In that case a received ErroREST HTTP response will be proxied up to the client.

Spring Security exceptions

The starter supports mapping Spring Security exceptions to ErroREST HTTP responses if the following dependency is added:

dependencies {
    compile 'org.springframework.boot:spring-boot-starter-security:2.0.1.RELEASE'
}

To support the HTTP Security configuration and method secured with annotations ErrorestAccessDeniedHandler and ErrorestAuthenticationEntryPoint are needed:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private ErrorestAuthenticationEntryPoint authenticationEntryPoint;
    @Autowired
    private ErrorestAccessDeniedHandler accessDeniedHandler;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.exceptionHandling()
                .authenticationEntryPoint(authenticationEntryPoint)
                .accessDeniedHandler(accessDeniedHandler)
                .and()
                ...
    }
}

Configuration properties list

The following list contains all available configuration properties with their default values.

errorest:
  response-body-format: full # HTTP response body format.
  http-client-error:
    logging-level: warn # HTTP 4xx errors logging level.
  bean-validation-error:
    logging-level: warn # Validation errors logging level.

License

ErroREST Spring Boot Starter is published under Apache License 2.0.