I'm developing a REST service using JAX-RS with Java 6 and Jersey 1.8 and my server is JBoss 5.1.0 GA, I've started with a simple endpoint that receives a parameter and return a null value.
Following this article, I mapped my expected exceptions with ExceptionMapper to three classes: AppException for exceptions within the scope of the project, NotFoundException for exceptions of records not found and GenericException for any other exception outside the expected errors.
I can return the exceptions as application/json responses just fine, but when I try to return a response as an application/xml, I get an HTML page from my server with HTTP 500 status code.
For example, if I don't send the required parameter to my endpoint, I get a HTTP 400 status code with its JSON response correctly:
{
"status": 400,
"message": "org.xml.sax.SAXParseException: Premature end of file.",
"developerMessage": "javax.ws.rs.WebApplicationException: org.xml.sax.SAXParseException: Premature end of file.... 40 more\r\n"
}
But if I try to return a XML response I get this HTML page:
<html>
<head>
<title>JBoss Web/2.1.3.GA - Informe de Error</title>
</head>
<body>
<h1>Estado HTTP 500 - </h1>
<HR size="1" noshade="noshade">
<p>
<b>type</b> Informe de estado
</p>
<p>
<b>mensaje</b>
<u></u>
</p>
<p>
<b>descripción</b>
<u>El servidor encontró un error interno () que hizo que no pudiera rellenar este requerimiento.</u>
</p>
<HR size="1" noshade="noshade">
<h3>JBoss Web/2.1.3.GA</h3>
</body>
</html>
My ErrorMessage class looks as described in the article I linked:
import java.lang.reflect.InvocationTargetException;
import javax.ws.rs.core.Response;
import org.apache.commons.beanutils.*;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.sun.jersey.api.NotFoundException;
@XmlRootElement(name = "errorMessage")
public class ErrorMessage {
@XmlElement(name = "status")
int status;
@XmlElement(name = "message")
String message;
@XmlElement(name = "developerMessage")
String developerMessage;
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getDeveloperMessage() {
return developerMessage;
}
public void setDeveloperMessage(String developerMessage) {
this.developerMessage = developerMessage;
}
public ErrorMessage(AppException ex) {
try {
BeanUtils.copyProperties(this, ex);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
public ErrorMessage(NotFoundException ex) {
this.status = Response.Status.NOT_FOUND.getStatusCode();
this.message = ex.getMessage();
}
public ErrorMessage() {
}
@Override
public String toString(){
return "ErrorMessage{" + "status=" + status + ", message='" + message + '\'' + ", developerMessage='" + developerMessage + "'}";
}
}
Why am I unable to return a XML response when specified?
This is the GenericExceptionMapper class I'm using
@Provider
public class GenericExceptionMapper implements ExceptionMapper<Throwable> {
@Override
public Response toResponse(Throwable exception) {
ErrorMessage errorMessage = new ErrorMessage();
setHttpStatus(exception, errorMessage);
errorMessage.setMessage(exception.getMessage());
StringWriter errorStackTrace = new StringWriter();
exception.printStackTrace(new PrintWriter(errorStackTrace));
errorMessage.setDeveloperMessage(errorStackTrace.toString());
// The only change is the MediaType.APPLICATION_XML, originally it was MediaType.APPLICATION_JSON
return Response.status(errorMessage.getStatus()).entity(errorMessage).type(MediaType.APPLICATION_XML).build();
}
private void setHttpStatus(Throwable ex, ErrorMessage errorMessage) {
if(ex instanceof WebApplicationException ) {
errorMessage.setStatus(((WebApplicationException)ex).getResponse().getStatus());
} else {
errorMessage.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
}
}
}
ExceptionMapperin the Jersey framework. What was the exception? My first guess would be that you don't have any appropriateMessageBodyWriterconfigured for theapplication/xmlresponseContent-Type- Alex2015-02-04 13:37:22,229 ERROR [STDERR] (http-localhost%2F127.0.0.1-8080-1) [Fatal Error] :-1:-1: Premature end of file.- Uriel ArvizutoResponsemethod is the same as in the article I linked, I only change the type from MediaType.APPLICATION_JSON to MediaType.APPLICATION_XML, when it's JSON I get an error response in JSON just like I want, but when it's XML I get the HTML error page. See my edited answer to check my class for mapping the exception, you'll see it's the same as the one in the article. - Uriel ArvizuMessageBodyWriterimplementations on your Classpath and registered with Jersey to support writing various MediaType based responses (i.e. JSON or XML). Check the real documentation for details on how to make XML work: jersey.java.net/documentation/1.18/xml.html - Alex