RESTEasy mock framework works fine without exception mapper - the request is received, and the object is returned with the expected content.
After registering an exception handler and forcing an exception, the call fails when the internal RESTEasy calls cause ResteasyProviderFactory.getContextData (type), which returns null, which leads to an unexpected error message: "Could not find context data like: javax.servlet.http.HttpServletRequest "
It was not possible to find any examples on the Internet from RESTEasy mock plus an exception display unit, and also could not find anything useful in this error.
Customer Class:
package com.foo; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "foo-type", propOrder = { "name" }) @XmlRootElement(name = "foo") public class Foo { protected String name; public String getName() { return name; } public void setName(String value) { this.name = value; } }
Factory object:
package com.foo; import javax.xml.bind.annotation.XmlRegistry; @XmlRegistry public class ObjectFactory { public ObjectFactory() { } public Foo createFoo() { return new Foo(); } }
Check Exception:
package com.foo; public class ValidationException extends RuntimeException { private static final long serialVersionUID = -8100360206713223313L; public ValidationException(String message) { super(message); } public ValidationException(Exception innerException) { super(innerException); } public ValidationException(String message, Exception innerException) { super(message, innerException); } }
Service Endpoint:
package com.foo; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; @Path("/rest/v1") public class FooService { @GET @Path("/foo") @Produces("application/xml") public Foo alwaysBlowUp() throws ValidationException { if (System.currentTimeMillis() > 0) { throw new ValidationException("FOO"); } return null; } }
Exception Editor:
package com.foo; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.ResponseBuilder; import javax.ws.rs.core.Response.Status; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; @Provider public class FooExceptionMapper implements ExceptionMapper<ValidationException> { @Context private static HttpServletRequest request; @Context private static HttpHeaders headers; @Override public Response toResponse(ValidationException exception) { MediaType mediaType = null; String acceptHeader = request.getHeader("accept"); if (MediaType.APPLICATION_XML.equals(acceptHeader)) { mediaType = MediaType.APPLICATION_XML_TYPE; } else if (MediaType.APPLICATION_JSON.equals(acceptHeader)) { mediaType = MediaType.APPLICATION_JSON_TYPE; } else { mediaType = headers.getMediaType(); if (mediaType == null) { mediaType = MediaType.APPLICATION_XML_TYPE; } } ResponseBuilder builder = Response.status(Status.BAD_REQUEST); builder.type(mediaType); return builder.build(); } }
Test:
package com.foo; import java.net.URISyntaxException; import org.jboss.resteasy.core.Dispatcher; import org.jboss.resteasy.mock.MockDispatcherFactory; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; import org.jboss.resteasy.plugins.server.resourcefactory.POJOResourceFactory; public final class TestFooExceptionMapper { public static void main(String[] args) throws URISyntaxException { Dispatcher dispatcher = MockDispatcherFactory.createDispatcher(); dispatcher.getRegistry().addResourceFactory(new POJOResourceFactory(FooService.class)); dispatcher.getProviderFactory().addExceptionMapper(FooExceptionMapper.class); MockHttpRequest request = MockHttpRequest.get("/rest/v1/foo"); MockHttpResponse response = new MockHttpResponse(); dispatcher.invoke(request, response); } }
Error:
Aug 26, 2012 10:44:26 PM org.jboss.resteasy.core.SynchronousDispatcher SEVERE: Failed executing GET /rest/v1/foo org.jboss.resteasy.spi.LoggableFailure: Unable to find contextual data of type: javax.servlet.http.HttpServletRequest at org.jboss.resteasy.core.ContextParameterInjector$GenericDelegatingProxy.invoke(ContextParameterInjector.java:56) at $Proxy18.getHeader(Unknown Source) at com.foo.FooExceptionMapper.toResponse(FooExceptionMapper.java:51) at com.foo.FooExceptionMapper.toResponse(FooExceptionMapper.java:1) at org.jboss.resteasy.core.SynchronousDispatcher.executeExceptionMapper(SynchronousDispatcher.java:330) at org.jboss.resteasy.core.SynchronousDispatcher.unwrapException(SynchronousDispatcher.java:359) at org.jboss.resteasy.core.SynchronousDispatcher.handleApplicationException(SynchronousDispatcher.java:348) at org.jboss.resteasy.core.SynchronousDispatcher.handleException(SynchronousDispatcher.java:220) at org.jboss.resteasy.core.SynchronousDispatcher.handleInvokerException(SynchronousDispatcher.java:196) at org.jboss.resteasy.core.SynchronousDispatcher.getResponse(SynchronousDispatcher.java:551) at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:513) at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:125) at com.foo.TestFooExceptionMapper.main(TestFooExceptionMapper.java:20)