1

I'm trying to implement a Spring Web MVC @ExceptionHandler with a @ResponseBody to return an object containing validation errors. (Strategy E documented here).

In Spring 3.0.x, there was a confirmed bug , since resolved, that prohibited this from working properly. I'm using Spring 3.1.2, and shouldn't be running into that one.

I am, however, running into an exception"Could not find acceptable representation".

Here's the exception:

[10/21/12 12:56:53:296 CDT] 00000045 ExceptionHand E redacted.loggi ng.jdk14.LogWrapper error Failed to invoke @ExceptionHandler method: public redacted.model.view.ValidationErrorResponse redacted.controller.Re stController.handleValidationException(redacted.util.ValidationExceptio n,javax.servlet.http.HttpServletResponse) Originating Class/Method:redacted.web.ui.filter.AccessControlFilter.pr ocessFilter() org.springframework.web.HttpMediaTypeNotAccepta bleException: Could not find acceptable representation at org.springframework.web.servlet.mvc.method.annotation.AbstractMessage ConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMeth odProcessor.java:115) 

And here's the code:

@ExceptionHandler(ValidationException.class) @ResponseStatus(value = HttpStatus.PRECONDITION_FAILED) @ResponseBody public ValidationErrorResponse handleValidationException(ValidationException ex, HttpServletResponse response) { List<ValidationError> errs = new LinkedList<ValidationError>(); for (ObjectError er : ex.getErrors()) { errs.add(new ValidationError(er.getObjectName(), er.getDefaultMessage())); } return new ValidationErrorResponse(errs); } @RequestMapping(value = "/search") @ResponseBody public SearchResult search(@Valid @ModelAttribute SearchRequest searchRequest, BindingResult bResult) { if (bResult.hasErrors()) { throw new ValidationException(bResult.getAllErrors()); } return searchService.search(searchRequest); } 

Any ideas?

1
  • You do have an Accept header of "application/json" right, if so can you please show how your ValidationException looks. Commented Oct 22, 2012 at 16:48

3 Answers 3

1

If you're reading this you probably have some question about how I got this to work. The short answer is that I don't know. I reverted off my code and re-implemented (actually copy and pasted the controller bits) from here, and it suddenly started working.

If you're using Spring 3.1.2, @ExceptionHandler and @ResponseBody does work.

My tentative explanation as to why this didn't work initially was that it was probably a user error or an error in the (very complicated, this application is massive) deployment scripts I was uing.

Sign up to request clarification or add additional context in comments.

Comments

1

I've had this issue when I needed to return a JSON error response for a request that ends with some known extension like "/blah/blah.xml". In this case Spring favors the extension-based representation matching, and ignores the Accept header (also is the case with the latest Spring 4.1.5).

I used the following to "lock" to the JSON response no matter what the request is.

@Configuration @EnableWebMvc public class ApplicationConfiguration extends WebMvcConfigurerAdapter { public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer.favorPathExtension(false); configurer.ignoreAcceptHeader(true); configurer.defaultContentType(MediaType.APPLICATION_JSON); } } 

Comments

0

The problem seems to be that Spring Does not how waht to convert the ValidationErrorResponse to, for example should it convert it to JSON, or XML or something else? try returning a ResponseEntity because you can control the content type directly.

protected ResponseEntity<ValidationErrorResponse> createResponseEntity(ValidationErrorResponse restApiError) { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); // assuming your ValidationErrorResponse object has an http code stored in it HttpStatus responseStatus = HttpStatus.valueOf(restApiError.getHttpStatus()); ResponseEntity<RestApiError> result = new ResponseEntity<>(restApiError, headers, responseStatus); return result; } 

I use something like in my application, also I have a bunch of RuntimeExceptions that I can throw which contain wihtin them enough information be able to generate proper error responses.

1 Comment

Is there a way to "default" or "lock" response representation to JSON?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.