When a Spring bean is annotated with SCOPE_REQUEST
, it is created and destroyed every time a HTTP request is received by the servlet. If this bean creation fails, a server error is sent back to the caller.
In this trivial example, the creation of the MyInputs
bean is dependent on the contents of the HTTP request.
@Configuration
class ApplicationConfiguration {
@Bean
@Scope(scopeName = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public MyInputs myInputs(HttpServletRequest request) {
String header1 = request.getHeader("header1");
if (header1 == null) {
throw new MyException("header1 is missing");
}
return new MyInputs(header1);
}
}
If the HTTP request does not contain a required header, a BeanCreationException
will be thrown. This is translated into an unhelpful "500 Internal Server Error" response.
I would like to return a more user-friendly response code and body, for example, a "400 Bad Request" with a helpful message. How do I customize this response translation? I cannot find any lifecycle hooks which will allow this.
Note: This is how the request-scoped bean is consumed:
@RestController
public class MyController {
private final Provider<MyInputs> myInputsProvider;
@Autowired
public MyController(Provider<MyInputs> myInputsProvider) {
this.myInputsProvider = myInputsProvider;
}
@GetMapping("/do-stuff")
public void doStuff() {
// Get the inputs for the current request
MyInputs myInputs = myInputsProvider.get();
// ...
}
}
You can use @ControllerAdvice
annotation in order to handle exceptions after are thrown.
Also you need to use @ExceptionHandler
in order to handle the exception.
@Order(Ordered.HIGHEST_PRECEDENCE)
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MyException.class)
public final ResponseEntity<CustomError> handleException(MyException ex, WebRequest request) {
CustomError error = new CustomError();
error.setMessage(ex.getMessage());
error.setStatus(HttpStatus.BAD_REQUEST);
return new ResponseEntity<>(error, null, HttpStatus.BAD_REQUEST);
}
}