3

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})

4 Answers 4

4

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.

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

2 Comments

Since you solved the issue, you should accept your own answer so people that will see your question know it's solved and therefore could be helpful.
@araknoid there is a 2 day waiting period before I can accept it.
3

You need to add below dependency in your pom.xml and it will work with your code with produces = MediaType.APPLICATION_XML_VALUE,

    <dependency>
        <groupId>com.fasterxml.jackson.dataformat</groupId>
        <artifactId>jackson-dataformat-xml</artifactId>
    </dependency>

2 Comments

I didn't (de)serialize any XML in this minimal example, why would this help?
You did try to serialize by converting ServerError object to XML, so above dependency will take care of serializing this object when sending it as XML
0

One option is to add content type to ResponseEntity explicitly in ExceptionHandler.

Controller:

@GetMapping("/path", produces = [MediaType.TEXT_XML_VALUE])

ControllerAdvice:

@ExceptionHandler(org.springframework.validation.BindException::class)
    fun handleBindException(
        e: org.springframework.validation.BindException
    ): ResponseEntity<ErrorResponse> {    
        return ResponseEntity
            .status(HttpStatus.BAD_REQUEST)
            .contentType(MediaType.APPLICATION_JSON_UTF8)
            .body(ErrorResponse(e.message))
    }

ErrorResponse

data class ErrorResponse(val message: String?)

Tested on Spring Boot 2.1.3.RELEASE with Kotlin

Comments

0

In order to make ExceptionHandler return XML format(by default it returns JSON format), there two steps need to do:

  1. import the maven dependency:
 <dependency>
     <groupId>com.fasterxml.jackson.dataformat</groupId>
     <artifactId>jackson-dataformat-xml</artifactId>
 </dependency>
  1. use ResposneEntity's static method internalServerError(): ResponseEntity.internalServerError().header("MyHeader","MyValue").contentType(MediaType.APPLICATION_XML).body(ex);

inside the contentType, specify MediaType.APPLICATION_XML.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.