Backstopper is a framework-agnostic API error handling and (optional) model validation solution for Java 7 and greater.
This readme focuses specifically on the Backstopper Spring Web MVC integration. If you are looking for a different framework integration check out the relevant section of the base readme to see if one already exists. The base project README.md and User Guide contain the main bulk of information regarding Backstopper.
NOTE: There is a Spring Web MVC sample application that provides a simple concrete example of the information covered in this readme.
This backstopper-spring-web-mvc
library can be used in any Spring Web MVC 4.3.x
environment or later. This includes
Spring 5, Spring Boot 1, and Spring Boot 2.
NOTE: This library does not cover Spring WebFlux (Netty) applications. Spring Web MVC and Spring WebFlux are mutually exclusive. If you're looking for Backstopper support for Spring WebFlux please see the backstopper-spring-web-flux module instead of this one.
- Pull in the
com.nike.backstopper:backstopper-spring-web-mvc
dependency into your project. - Register Backstopper components with Spring Web MVC, either via
@Import({BackstopperSpringWebMvcConfig.class})
, or@ComponentScan(basePackages = "com.nike.backstopper")
. See the javadocs onBackstopperSpringWebMvcConfig
for some related details.- This causes
SpringApiExceptionHandler
andSpringUnhandledExceptionHandler
to be registered with the Spring Web MVC error handling chain in a way that overrides the default Spring Web MVC error handlers so that the Backstopper handlers will take care of all errors. It sets upSpringApiExceptionHandler
with a default list ofApiExceptionHandlerListener
listeners that should be sufficient for most projects. You can override that list of listeners (and/or many other Backstopper components) if needed in your project's Spring config. - It also registers
SpringContainerErrorController
to handle errors that happen outside Spring Web MVC (i.e. in the Servlet container), and make sure they're routed through Backstopper as well. Note that you'll need to configure your Servlet container to route container errors to the path this controller listens on (default/error
) for it to work.
- This causes
- Expose your project's
ProjectApiErrors
and a JSR 303javax.validation.Validator
implementation in your Spring dependency injection config.ProjectApiErrors
creation is discussed in the base Backstopper readme here.- JSR 303 setup and generation of a
Validator
is discussed in the Backstopper User Guide here. If you're not going to be doing any JSR 303 validation outside what is built-in supported by Spring Web MVC, and you don't want to bother jumping through the hoops to get a handle on Spring's JSR 303 validator impl provided byWebMvcConfigurer.getValidator()
, and you don't want to bother creating a realValidator
yourself then you can simply registerNoOpJsr303Validator#SINGLETON_IMPL
as theValidator
that gets exposed by your Spring config.ClientDataValidationService
andFailFastServersideValidationService
would fail to do anything, but if you don't use those then it wouldn't matter.
- Setup the reusable unit tests for your project as described in the Backstopper User Guide here and shown in the sample application.
The base Backstopper readme covers the usage basics. There should be no difference when running in a Spring Web MVC environment, but since Spring Web MVC integrates a JSR 303 validation system into its core functionality we can get one extra nice tidbit: to have Spring Web MVC run validation on objects deserialized from incoming user data you can simply add @Valid
annotations on the objects you're deserializing for your controller endpoints (@RequestBody
object, @ModelAttribute
objects, etc). For example:
@RequestMapping(method=RequestMethod.POST)
@ResponseBody
@ResponseStatus(HttpStatus.CREATED)
public SomeOutputObject postSomeInput(
@ModelAttribute @Valid HeadersAndQueryParams headersAndQueryParams,
@RequestBody @Valid SomeInputObject inputObject) {
// ... Normal controller processing
}
This method signature with the two @Valid
annotations would cause both the @ModelAttribute
headersAndQueryParams
and @RequestBody
inputObject
arguments to be run through JSR 303 validation. Any constraint violations caught at this time will cause a Spring-specific exception to be thrown with the constraint violation details buried inside. This backstopper-spring-web-mvc
plugin library's error handler listeners know how to convert this to the appropriate set of ApiError
cases (from your ProjectApiErrors
) automatically using the Backstopper JSR 303 naming convention, which are then returned to the client using the standard error contract.
This feature allows you to enjoy the Backstopper JSR 303 validation integration support automatically at the point where caller-provided data is deserialized and passed to your controller endpoint without having to inject and manually call a ClientDataValidationService
.
This backstopper-spring-web-mvc
module does not export any transitive Spring or Servlet API dependencies to prevent runtime
version conflicts with whatever Spring and Servlet environment you deploy to.
This should not affect most users since this library is likely to be used in a Spring/Servlet environment where the required dependencies are already on the classpath at runtime, however if you receive class-not-found errors related to Spring or Servlet API classes then you'll need to pull the necessary dependency into your project.
The dependencies you may need to pull in:
- Spring Web MVC: org.springframework:spring-webmvc:[spring-version]
- Servlet API (choose one of the following, depending on your environment needs):
- Servlet 3+ API: javax.servlet:javax.servlet-api:[servlet-api-version]
- Servlet 2 API: javax.servlet:servlet-api:[servlet-2-api-version]
See the base project README.md, User Guide, and Backstopper repository source code and javadocs for all further information.
Backstopper is released under the Apache License, Version 2.0