Spring #Validated Causing HTTP 400 - spring

When I add the #validate annotaion to a method signature in my controller, I get a HTTP 400 with the description, "The request sent by the client was syntactically incorrect ().". Does anyone have an idea why?
Good Code
public ModelAndView startAccountSubmittal(
AccountCredential accountCred, HttpServletResponse response)
throws MessagingException {
Bad Code
public ModelAndView startAccountSubmittal(
#Validated(value={AccountStates.Submitted.class})
AccountCredential accountCred,
HttpServletResponse response, BindingResult result)
throws MessagingException {
Thanks in advance,
Joe

The uncaught exception I had configured was not catching the error. I added an exception handler to the controller and I was able to get the details. I had a few extra fields it was trying to validate, which contained nulls, but required values. This what caused the HTTP 400. Turning on the exception handler helped get the exception and stacktrace. I modified the code and added extra groups, then added those new groups to the object and controller. It works as planned.

Related

Can not handle JDBCConnectionException in spring rest with custom exception handler

I use a global exception handler in my spring rest app and I would like to hide jdbc exceptions, but it doesn't work as expected. I shut down the database to force a connection exception and I can see the following exception in the log and I receive the default spring error response, but not the one I defined in the exception handler
java.lang.IllegalStateException: Could not resolve parameter [1] in public org.springframework.http.ResponseEntity<java.lang.Object> ...
throws java.io.IOException: No suitable resolver
Here's the code.
#ControllerAdvice
public class CustomGlobalExceptionHandler extends ResponseEntityExceptionHandler {
#ExceptionHandler({JDBCConnectionException.class})
public ResponseEntity<Object> dbError(JDBCConnectionException exception,
HttpHeaders headers,
HttpStatus status,
WebRequest request) throws IOException
{
Map<String,Object> body = new HashMap<>();
body.put("errorId",Long.valueOf(201));
body.put("state",HttpStatus.SERVICE_UNAVAILABLE.value());
body.put("message", "internal failure");
body.put("time", new Date().toString());
return new ResponseEntity<>(body, headers, status);
}
Hope you can help me.
I've found the failure...spring can not resolve these two parameters, for that kind of exception.
HttpHeaders headers,
HttpStatus status
It's obviouse the exception mentioned paramter [1]
java.lang.IllegalStateException: Could not resolve parameter [1] in public org.springframework.http.ResponseEntity<java.lang.Object> ...
throws java.io.IOException: No suitable resolver
I removed these two parameters and the exception handler handles the exception.
This code works now
#ExceptionHandler(JDBCConnectionException.class)
public ResponseEntity<Object> dbError(Exception ex,
WebRequest request)
{
Map<String,Object> body = new HashMap<>();
body.put("errorId",Long.valueOf(201));
body.put("state",HttpStatus.SERVICE_UNAVAILABLE.value());
body.put("message", "internal failure");
body.put("time", new Date().toString());
return new ResponseEntity<Object>(body, HttpStatus.INTERNAL_SERVER_ERROR);
}
As the annotation implies #ControllerAdvice is used as an extension on your REST endpoints, these exception handlers will process the exception for the REST API and does not influence how it is logged in the console. It will instead determine how exceptions are reported to your end users and allow you to write concise error messages without leaking information about your program.
If you want to completely catch an exception and not only for the REST API take a look at this blog.
However I would not recommend doing this since this will greatly reduce the information available to you as a developer, this information cannot be seen by end users and therefore the REST API custom exception should provide enough abstraction.
I hope this helps you.

Spring - Changing Order of Global Error handler and Filter

I have a filter like:
#Component
#Order(8)
public class LogReqFilter extends OncePerRequestFilter
{
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException
{...}
}
it basically logs all requests and responses. When there is a 400 error however the response is blank. There is a global exception handler that replaces the body with the custom error:
#RestControllerAdvice
public class GlobalExceptHandler extends ResponseEntityExceptionHandler {
#Override
#ResponseStatus(HttpStatus.BAD_REQUEST)
protected ResponseEntity<Object> handleArgNotValid(MethodArgumentNotValidException ex
, HttpHeaders headers, HttpStatus status, WebRequest request) {...}
}
I noticed that the Global Exception handler is called after the filter and I think that this is why the response is blank in the filter. Is there a way to have the filter called after the Global Exception Handler?
Edited:
TLDR
No You can't change the order as per the OP Title because your GlobalError Handler is always in the layer that holds the ControllerAdvices and that is always between the RequestFilter layer and the Controller.
Long Version
You are somewhat right.
i refer you to this answer: https://stackoverflow.com/a/17716298/405749
expanding on this:
be aware that before and after depends from which you are looking from, ie.
inbound (before it reaches your controller code) OR
outbound (after the controller is done)
now you can plug in different components on this path, e.g. here RequestFilter and Controller Advice
depending on the method you implement, it gets called only on the inbound or outbound track or both, here:
doFilterInternal() is called inbound. Only if you call filterChain.doFilter(request, response); the request continues on the inbound track otherwise it stops here and the response is returned with whatever is already in its output stream or will be added by this filter or filters still be encountered on the way out
this is the call sequence assuming we only have this filter and advice
'inbound'-methods from request filters
'inbound'-methods from controller advice(s)
'outbound'-methods from controller advice(s)
'outbound'-methods from request filters
Now, the handleArgNotValid() only gets called in case such an exception is thrown and potentially adds content to the Response-Output stream. Your example doesnt show if you return an object here or not, but i guess from your OP that you dont. and as a consequence the output stream is empty.
Plz also note, that there is no easy way to dump/look into the output stream unless you wrap it, but that's another topic.

How to handle HttpMediaTypeNotAcceptableException by writing error content to the response body using exception handler annotation?

When a client request for a resource producing application/json content with Accept Header of application/xml. The request fails with HttpMediaTypeNotAcceptableException exception and is wrapped into error message body in the response entity object by using exception handler annotation as mentioned in below code. However, we receive HttpMediaTypeNotAcceptableException again when return values are written to the response with HttpMessageConverter. It is because it checks the producible content type for the response with the acceptable request type, but this is exactly something we are trying to communicate to the client using error message. How do I workaround this issue ? Btw, all the other exceptions are parsing fine to error message. Please advise.
#ControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {
#Override
protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body,
HttpHeaders headers, HttpStatus status, WebRequest request) {
// Setting the response content type to json
headers.setContentType(MediaType.APPLICATION_JSON);
return ResponseEntity.status(status).headers(headers).body(body);
}
}
A few options come to my mind. One is that your controller method produces all content types and then you throw an exception in your method if the content type is not the one you are expecting, then the exception handler can take this exception and transform it. This is the only one that works with exception handlers, as exception handlers only deal with exceptions produced in the controller method.
The other options are:
Use an interceptor (but I'm not sure if this will work, as Spring might try to resolve first the controller method rather than invoking the interceptors).
Extend RequestMappingHandlerMapping to call the exception handler if it doesn't find a suitable method. You'll probably need to override the method handleNoMatch. In there you'll need to get a reference to the list of HandlerExceptionResolver
The first one is the simplest to understand, and the latest one might be the most 'extensible', but it also requires some understanding of the internals of Spring.
Resolved by setting different content negotiation strategy FixedContentNegotiationStrategy for ExceptionHandlerExceptionResolver and HeaderContentNegotiationStrategy for RequestResponseBodyMethodProcessor.
I have been using a serialized enum-based response (enum annotated with jackson #JsonFormat(shape = Shape.OBJECT) to standardize the error messages in my exception handler class and faced the same issue when it caught with a HttpMediaTypeNotAcceptableException.
The workaround is to set the media type you expect to return directly to the builder method available in the ResponseEntity.
The below code works fine for me.
#ExceptionHandler(HttpMediaTypeNotAcceptableException.class)
public final ResponseEntity<ResponseMessagesEnum> handleHttpMediaTypeNotAcceptableException(
HttpMediaTypeNotAcceptableException e, HttpServletRequest request) {
logger.error("No acceptable representation found for [{}] | supported {}", request.getHeader("Accept"), e.getSupportedMediaTypes());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).contentType(MediaType.APPLICATION_JSON)
.body(ResponseMessagesEnum.EX_001);
}

EHCache and DropWizard: Returning no response

I have successfully integrated SimplePageCachingFilter with DropWizard.
However, there is one thing standing in my way. Whenever an exception in my application is thrown, instead of being routed to my ExceptionMapper I get "Response contains no data" in my API Browser. I also happen to see this pass by in the log.
WARN [2015-02-12 04:06:21,768] net.sf.ehcache.constructs.web.GenericResponseWrapper: Discarding message because this method is deprecated.
Traditionally my ExceptionMapper returns the appropriate Json Responses.
Has anyone else seen anything similar?
I would put a breakpoint in http://grepcode.com/file/repo1.maven.org/maven2/com.sun.jersey/jersey-server/1.18.1/com/sun/jersey/server/impl/application/WebApplicationImpl.java#WebApplicationImpl on line 1472 then trigger your error.
That's throwing an exception, and the mapping of the exception to the exception mapper happens in the catch a little deeper in the stack. Probably in ContainerResponse.mapException
Hopefully this will give you enough insight into why it's not being called.
FYI. I got to that code by putting a breakpoint in a exception mapper that was being fired, and looking at the call stack.
After attaching a debugger to DropWizard (per #CAB's advice) I discovered that the CachingFilter does not write out a response unless the status code is 200.
I extended CachingFilter and overrode the doFilter method and ignored the status check. This appears to have solved my problem.
#Override
protected void doFilter(final HttpServletRequest request,
final HttpServletResponse response, final FilterChain chain) throws Exception {
if (response.isCommitted()) {
throw new AlreadyCommittedException("Response already committed before doing buildPage.");
}
logRequestHeaders(request);
PageInfo pageInfo = buildPageInfo(request, response, chain);
writeResponse(request, response, pageInfo);
}

difference between Spring mvc redirect and general jsp name return

Please consider these code snippets
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {
return new ModelAndView("redirect:DummyRedirectPage.htm");
}
and
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {
return new ModelAndView("somejsp");
}
Can anyone tell me the difference between the two? In both the cases the handler method is navigating the flow to a view page.
With the first one user will receive HTTP 302 response to redirect into DummyRedirectPage.htm. If the handler was mapped to a POST method, this will force user to perform GET to DummryRedierctPage.htm
On the second one your view resolver will resolve "somejsp" into an actual view. No HTTP 302 response is given to user.
Please read about PRG (Post Redirect Get) design pattern to find out why this matters.

Resources