RESTEasy Mock vs. Exception Mapper vs. Context [英] RESTEasy Mock vs. Exception Mapper vs. Context

查看:149
本文介绍了RESTEasy Mock vs. Exception Mapper vs. Context的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

RESTEasy模拟框架在没有异常映射器的情况下工作正常 - 收到请求并返回实体与预期内容。

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

注册异常映射器并强制异常后,调用失败当RESTEasy的内部调用ResteasyProviderFactory.getContextData(type)时,它返回null,导致意外的错误消息:无法找到类型的上下文数据:javax.servlet.http.HttpServletRequest。

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

无法在网上任何地方找到RESTEasy模拟加上异常映射器的任何示例,也无法找到有关错误的任何有用信息。

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

客户端类:

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)


推荐答案

问题是'模拟框架'没有向上下文提供 HttpServletRequest 。它与 ExceptionMapper 没有直接关系。

The problem is that the 'mock framework' does not supply a HttpServletRequest to the context. It's not directly related to the ExceptionMapper.

Resteasy根据 ResteasyProviderFactory.getContextDataMap中的数据注入 @Context 字段()。当此映射不包含 HttpServletRequest 的实例时,它会突然出现错误'无法找到类型的上下文数据...'

Resteasy injects @Context fields based on data that is present in the ResteasyProviderFactory.getContextDataMap(). When this map does not contain an instance of HttpServletRequest, it blows up whith the error 'Unable to find contextual data of type...'

我通过将一个模拟 HttpServletRequest 放入resteasy上下文来解决这个问题:

I have worked around this by putting a mock HttpServletRequest into the resteasy context:

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

这篇关于RESTEasy Mock vs. Exception Mapper vs. Context的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆