Jersey 2中的JAX-RS @Context用法与Jersey 1相比

时间:2015-11-20 12:24:00

标签: java jersey jax-rs jersey-2.0 hk2

[编辑] 问题在于 register(new ServiceBinder<>(MyService.class)); 泽西岛生成警告并忽略除第一个之外的所有注册(此类型的现有先前注册);它只考虑类型擦除的ServiceBinder类来决定是否存在冲突。 看起来我需要使用更复杂的寄存器版本来解决这个问题。 [/编辑]

在Jersey 1中,我能够使用自定义注射提供程序通过扩展将我的对象注入到类字段和方法参数中 LazySingletonInjectableProvider

我无法弄清楚如何将该模式移植到Jersey 2(在Tomcat 7上使用hk2)。我已经阅读了有关该主题的所有内容,包括Jersey custom method parameter injection with inbuild injection - 但我不想使用自定义注释,我也不想尝试注入请求参数。

[编辑]我做了错误的假设,关于哪些有效,哪些无效:

  • 注入ContainerRequestFilter中的类字段可以正常工作
  • 注入资源,无论是作为类字段还是方法参数都不起作用

[编辑2]:如下所述的InjectionResolver实际上根本不起作用,我已将其删除。 Jersey已经有一个ContextInjectionResolver,大概应该处理@Context注释。

我创建并注册了一个AbstractBinder,,并且该类字段注入工作正常;但是方法参数注入没有(绑定从不被调用,参数保持为null)。 我试图绑定一个InjectionResolver,但这也无济于事。

我们非常感谢任何有关如何完成这项工作的建议......这是当前的代码:

HK2活页夹:

public class ServiceBinder<T> extends AbstractBinder
{
    private final Factory<T> _factory;
    private final Class<? extends T> _clazz;

    public OsgiServiceBinder(Class<T> clazz)
    {
        _factory = new ServiceFactory<>(clazz);
        _clazz = clazz;
    }

    protected void configure()
    {
        bindFactory(_factory).to(_clazz); //.in(RequestScoped.class);
        bind(ServiceInjectionResolver.class)
            .to(new TypeLiteral<InjectionResolver<Context>>() { })
            .in(PerLookup.class);
    }
}

注射旋转变压器:

public class ServiceInjectionResolver<T> implements InjectionResolver<Context>
{
    private Class<T> _clazz;

    public OsgiServiceInjectionResolver(Class<T> clazz)
    {
        _clazz = clazz;
    }

    public Object resolve(Injectee injectee, ServiceHandle<?> root)
    {
        if (_clazz.getCanonicalName().equals(injectee.getRequiredType().getTypeName())) {
            return Framework.getService(_clazz);
        }
        return null;
    }

    public boolean isConstructorParameterIndicator()
    {
        return false;
    }

    public boolean isMethodParameterIndicator()
    {
        return true;
    }
}

JAX-RS注册:

public class MyApplication extends Application
{
    public MyApplication()
    {
        registerClasses(<resource classes>);
        register(new ServiceBinder<>(MyService.class));
    }
}

资源类:

   @Path("/schedules")
public class SchedulesResource
{
    @Context UriInfo _uriInfo;

    // This injection works fine, _service1 is properly initialized
    @Context MyService _service1;

    @PUT
    @Consumes({MediaType.APPLICATION_JSON})
    @Path("{jobGroup}/{jobName}")
    public Response putSchedule(@Context MyService service2,
                                ...)
    {
        // The injection of service2 doesn't work...
    }
}

工厂类:

public class ServiceFactory<T> implements Factory<T>
{
    private Class<T> _clazz;

    protected ServiceFactory(Class<T> clazz)
    {
       _clazz = clazz;
    }

    public T provide()
    {
        return Framework.getService(_clazz);
    }
}

public void dispose(T t)
{
}

}

1 个答案:

答案 0 :(得分:0)

问题实际上是泽西岛组件注册。 即使我正在注册binder实例,Jersey也在检查类(ServiceBinder)并丢弃除第一次注册之外的所有注册(WARN:找到该类型的现有注册)。

考虑到我正在注册实例,这似乎有点虚假,我希望Jersey能够在出现错误时失败,而不是在未能注册组件时记录警告,但解决方案是简单地稍微更改注册模式:

// Doesn't work
 register(new ServiceBinder<>(MyService1.class));
 register(new ServiceBinder<>(MyService2.class));

// Works like a charm
register(new ServiceBinder(MyService1.class, MyService2.class));

显然,ServiceBinder被调整为为每个提供的服务调用bindFactory。