2012-08-27 8 views
6

रीस्टेसी मॉक फ्रेमवर्क अपवाद मैपर के बिना ठीक काम करता है - अनुरोध प्राप्त होता है और इकाई अपेक्षित सामग्री के साथ वापस आती है।रीस्टेसी मॉक बनाम अपवाद मैपर बनाम संदर्भ

अपवाद नक्शाकार दर्ज की और एक अपवाद के लिए मजबूर करने के बाद, कॉल विफलताओं जब RESTEasy के धर्मशाला फोन ResteasyProviderFactory.getContextData (प्रकार) है, जो अशक्त देता है, अप्रत्याशित त्रुटि संदेश में जिसके परिणामस्वरूप: javax.servlet: "असमर्थ प्रकार के प्रासंगिक डेटा खोजने के लिए। http.HttpServletRequest "।

रीस्टेसी मॉक और अपवाद मैपर के कहीं भी कहीं भी कोई उदाहरण नहीं मिला, और त्रुटि के बारे में कुछ भी उपयोगी नहीं मिला।

ग्राहक वर्ग:

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

वस्तु कारखाना:

package com.foo; 

import javax.xml.bind.annotation.XmlRegistry; 

@XmlRegistry 
public class ObjectFactory { 

    public ObjectFactory() { 
    } 

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

मान्यता अपवाद:

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

सेवा समाप्ति बिंदु:

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

अपवाद नक्शाकार:

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

टेस्ट:

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

त्रुटि:

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) 

उत्तर

11

समस्या यह है कि 'नकली ढांचे' संदर्भ के लिए एक HttpServletRequest की आपूर्ति नहीं करता है। यह सीधे ExceptionMapper से संबंधित नहीं है।

रीस्टेसी @Context फ़ील्ड ResteasyProviderFactory.getContextDataMap() में मौजूद डेटा के आधार पर इंजेक्ट करता है। इस नक्शे HttpServletRequest का एक उदाहरण शामिल नहीं करता है, यह त्रुटि whith ऊपर चल रही है 'प्रकार की प्रासंगिक डेटा प्राप्त करने में असमर्थ ...'

मैं इस के आसपास resteasy संदर्भ में एक नकली HttpServletRequest रख कर काम किया है:

Dispatcher dispatcher = MockDispatcherFactory.createDispatcher(); 
dispatcher.getRegistry().addSingletonResource(new Service()); 

ResteasyProviderFactory 
     .getContextDataMap() 
     .put(HttpServletRequest.class, new MockHttpServletRequest()); 

MockHttpResponse response = new MockHttpResponse(); 

dispatcher.invoke(
    MockHttpRequest.get("/"), 
    response 
); 
+1

उत्तर देने के लिए धन्यवाद! यह बहुत उपयोगी है। मैंने एक साल पहले आपको धन्यवाद दिया होगा, लेकिन ईमेल अधिसूचना गलत ईमेल पर गई, और अब तक मैंने आपकी पोस्ट नहीं देखी। – user1461450

संबंधित मुद्दे