RESTEasy mock framework works fine without exception mapper--request is 
received and entity is returned with expected contents.

After registering exception mapper and forcing an exception, call fails when 
innards of RESTEasy call ResteasyProviderFactory.getContextData(type), which 
returns null, resulting in unexpected error message: "Unable to find contextual 
data of type: javax.servlet.http.HttpServletRequest".

Couldn't find any examples anywhere online of RESTEasy mock plus an exception 
mapper, and couldn't find anything useful about the error either.

Client 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;
        }
    }

Object factory:

    package com.foo;

    import javax.xml.bind.annotation.XmlRegistry;

    @XmlRegistry
    public class ObjectFactory {

        public ObjectFactory() {
        }

        public Foo createFoo() {
            return new Foo();
        }
    }

Validation 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 mapper:

    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;

    /*
    Set breakpoint on line below.
    Step over line and you get the exception in the logs.
    Step into the line and the problem is in ResteasyProviderFactory:

    public static <T> T getContextData(Class<T> type)
    {
        return (T) getContextDataMap().get(type); <<< type == 
javax.servlet.http.HttpServletRequest
    }

    The type is not in the map, so it returns null.

    The null results in this error in ContextParameterInjector:

    private class GenericDelegatingProxy implements InvocationHandler
    {
        public Object invoke(Object o, Method method, Object[] objects) throws 
Throwable
        {
            try
            {
                Object delegate = ResteasyProviderFactory.getContextData(type);
                if (delegate == null)
                   throw new LoggableFailure("Unable to find contextual data of 
type: " + type.getName()); <<< ERROR IN LOGS
    */

            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)

http://stackoverflow.com/questions/12136780/resteasy-mock-vs-exception-mapper-vs-context
 
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Resteasy-users mailing list
Resteasy-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/resteasy-users

Reply via email to