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