Search code examples
javaspringspring-restcontroller

Spring rest controller @ExceptionHandler return xml content and json errors


So I have a @RestController and I want to return and validate XML based on a schema for a front-end application in order to display them in an editor. I want the errors to be in json format in order to handle and display them with js.

@RestController
public class UserController {

    @RequestMapping(value = "/test",
        method = RequestMethod.GET,
        produces = MediaType.APPLICATION_XML_VALUE)
    public ResponseEntity<String> throwException(
        @RequestParam(value = "flag", defaultValue = "false") Boolean flag
    ) throws Exception {
        if (flag) {
            throw new Exception();
        } else {
            return ResponseEntity.ok("<xml>hello</xml>");
        }
    }


    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(Exception.class)
    @ResponseBody
    ServerError exceptionHandler(HttpServletRequest req, Exception ex) {
        return new ServerError(req.getRequestURL().toString(),ex);
    }

}

The ServerError I want to return in JSON format :

public class ServerError {

    public final String url;
    public final String error;

    public ServerError(String url, Exception ex) {
        this.url = url;
        this.error = ex.getMessage();
    }

    public String getUrl() {
        return url;
    }

    public String getError() {
        return error;
    }
}

So the <xml>hello</xml> is returned just fine but when I set the flag to true I get

ERROR   2017-10-18 12:56:53,189 [http-nio-0.0.0.0-8080-exec-2] org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver  - Failed to invoke @ExceptionHandler method: eu.openminted.registry.core.exception.ServerError eu.openminted.registry.service.UserController.malformedExeption(javax.servlet.http.HttpServletRequest,java.lang.Exception)
org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation

Also, setting the produces to both XML and JSON yields the same result

@RequestMapping(value = "/test",
        method = RequestMethod.GET,
        produces = {MediaType.APPLICATION_XML_VALUE,MediaType.APPLICATION_JSON_UTF8_VALUE})

Solution

  • I have managed to solve this by removing the produces from @RequestMapping and specifying with ResponseEntity the type I want to return

    @RequestMapping(value = "/test", method = RequestMethod.GET)
    public ResponseEntity<String> throwException(
        @RequestParam(value = "flag", defaultValue = "false") Boolean flag
    ) throws Exception {
        if (flag) {
            throw new Exception();
        } else {
            ResponseEntity response = ResponseEntity.ok().
                contentType(MediaType.APPLICATION_XML).
                body("<xml>hello</xml>");
            return response;
        }
    }
    

    The problem with that solution is that all of the methods have an @annotation with the type they produce and this doesn't, breaking uniformity.