The response to this wasn’t exactly overwhelming. One email said the mock 
framework is going to be deprecrated, which is fine, but in the meantime it 
would be good to find the cause of this.

A few minor changes to show that it’s tied to the exception:

package com.foo;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

@Path("/rest/v1")
public class FooService {
    
    public static boolean BLOW_UP = false;

    @GET
    @Path("/foo")
    @Produces({"application/xml"})
    public Foo doFoo() throws FooValidationException {
        if (BLOW_UP) {
            throw new FooValidationException("FOO");
        }
        Foo foo = new Foo();
        foo.setName("FOO");
        return foo;
    }
}

package com.foo;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
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, 
UnsupportedEncodingException, IOException {
        Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
        dispatcher.getRegistry().addResourceFactory(new 
POJOResourceFactory(FooService.class));
        
dispatcher.getProviderFactory().addExceptionMapper(FooExceptionMapper.class);
        
        MockHttpRequest request;
        MockHttpResponse response;
        
        System.out.println("Test without exception:");
        request = MockHttpRequest.get("/rest/v1/foo");
        response = new MockHttpResponse();
        dispatcher.invoke(request, response);
        System.out.println(new 
String(((ByteArrayOutputStream)response.getOutputStream()).toByteArray(), 
"UTF-8"));
        
        System.out.println();
        System.out.println("Test with exception:");
        request = MockHttpRequest.get("/rest/v1/foo");
        response = new MockHttpResponse();
        FooService.BLOW_UP = true;
        dispatcher.invoke(request, response);
        System.out.println(new 
String(((ByteArrayOutputStream)response.getOutputStream()).toByteArray(), 
"UTF-8"));
    }
}

Test without exception:
<?xml version="1.0" encoding="UTF-8" 
standalone="yes"?><foo><name>FOO</name></foo>

Test with exception:

Sep 03, 2012 2:34:37 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:50)
    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:35)

At the point where it blows up, it’s trying to get contextual data for 
HttpServletRequest.

Why is it doing that when the type of mock request sent in is a subclass of 
HttpRequest? Where does it get confused about the appropriate type to be 
looking up? This seems like a bug.

I thought about changing our POM to download resteasy-jaxrs-beta1.jar, which 
has a MockHttpServletRequest, but then our test configuration differs from our 
runtime configuration in too many ways.

Sent: Monday, August 27, 2012 9:42 AM
To: resteasy-users@lists.sourceforge.net 
Subject: [Resteasy-users] Problem using RESTEasy mock framework withexception 
mapper

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