RESTeasy InMemoryClient不将@Context UriInfo字段注入Spring@Transact



我们在测试中遇到了一个问题,即当资源封装在TransactionalProxy中时,字段UriInfo没有正确注入。我们尝试使用SpringResourceFactory,但也无济于事。

我试图为这个用例提取相关的类:


public class InMemoryClientFactory implements FactoryBean<InMemoryClientExecutor>{
    @Inject
    private SessionResource sessionResource;
    @Override
    public InMemoryClientExecutor getObject() throws Exception {
        Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
        Registry registry = dispatcher.getRegistry();
        registry.addSingletonResource(sessionResource);
        final InMemoryClientExecutor inMemoryClientExecutor = new InMemoryClientExecutor(dispatcher);
    }
    @Override
    public Class getObjectType() {
        return InMemoryClientExecutor.class;
    }
    @Override
    public boolean isSingleton() {
        return true;
    }
}

@Path("session")
public interface SessionResource {
    @GET
    @Path("{sessionId}")
    @Produces({MediaType.APPLICATION_XML})
    Response get(@PathParam("sessionId") String sessionId);
    @DELETE
    @Path("{sessionId}")
    Response delete(@PathParam("sessionId") String sessionId);
}

@Service
@Transactional
public class SessionResourceImpl implements SessionResource {
    @Context
    private UriInfo uriInfo;
    @Override
    public Response get(String sessionId) {
         // uriInfo will be null here
         String url = uriInfo.getBaseUriBuilder().path(SessionResource.class).path(SessionResource.class, "delete").build(sessionId)
                .toString());
        return Response.ok(session).build();
    @Override
    public Response delete(String sessionId) {
         System.out.println("Deleted Session "+1);
    }
}

@ContextConfiguration(locations = ["classpath:/META-INF/testContext.xml"])
@Transactional
@RunWith(SpringJUnit4ClassRunner.class)
public class SessionResourceIT {
    @Inject
    InMemoryRestClientFactory inMemoryClientFactory;
    @Inject
    SessionResource resource;
    @Test
    public void test() {
        SessionResource resource = inMemoryClientFactory.createProxy(SessionResource.class);
        ClientResponse cr = client.get(sessionId);
        assertNotNull(cr.getEntity(String.class));
    }
}

一个可能的解决方法是打开测试的事务代理,只要测试本身用@transactional注释,这就可以工作。我希望有人能找到比这更好的解决方案。


public class InMemoryClientFactory implements FactoryBean<InMemoryClientExecutor>{
    @Inject
    private SessionResource sessionResource;
    @Override
    public InMemoryClientExecutor getObject() throws Exception {
        Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
        Registry registry = dispatcher.getRegistry();
        registry.addSingletonResource(unwrapProxy(sessionResource));
        final InMemoryClientExecutor inMemoryClientExecutor = new InMemoryClientExecutor(dispatcher);
    }
    @Override
    public Class getObjectType() {
        return InMemoryClientExecutor.class;
    }
    @Override
    public boolean isSingleton() {
        return true;
    }
    private static Object unwrapProxy(Object bean) throws Exception {
        Object result = bean;
        /*
         * If the given object is a proxy, set the return value as the object
         * being proxied, otherwise return the given object.
         */
        if (AopUtils.isAopProxy(bean) && bean instanceof Advised) {
            Advised advised = (Advised) bean;
            result = advised.getTargetSource().getTarget();
        }
        return result;
    }
}

最新更新