JAX-RS应用程序子类注入

时间:2013-11-14 20:12:55

标签: java jersey jax-rs jersey-2.0

我正在编写自定义JAX-RS 2.0应用程序(在Jersey 2.3.1下),它包含一些数据供所有资源使用。

public class WebApp extends org.glassfish.jersey.server.ResourceConfig {
    public WebApp() {
        packages("my.resources.package");
    }
}

(我也可以使用API​​的javax.ws.rs.core.Application,描述的结果是相同的)

然后我将对象注入资源

@Path("test")
public class Test {
    @Context
    Application app;

    @GET
    @Path("test")
    public String test() {
        return "Application class: " + app.getClass();
    }
}

然而,通话的结果是

Application class: class org.glassfish.jersey.server.ResourceConfig$WrappingResourceConfig

让我使用了一些丑陋的技巧,比如

if (app instanceof WebApp) {
    return (WebApp) app;
} else if (app instanceof ResourceConfig) {
    return (WebApp) ((ResourceConfig) app).getApplication();
}

我对JAX-RS 2.0规范9.2.1的理解:

  

可以使用Application注释将应用程序提供的@Context子类的实例注入到类字段或方法参数中。访问Application子类实例允许将配置信息集中在该类中。请注意,这不能注入Application子类本身,因为这会产生循环依赖。

应用程序提供的Application子类是我的WebApp,而不是JAX-RS特定于实现的包装器。

另外,更改此片段

    @Context
    Application app;

到这个

    @Context
    WebApp app;

导致appnull,因为在上下文注入期间ClassCastException,因此声明的类型无关紧要。

这是泽西岛的一个错误还是我的误解?

更新:我检查了RESTEasy 3.0下的行为。注入的对象是我的WebApp,没有任何包装器。我把它称为泽西岛的一个错误。

3 个答案:

答案 0 :(得分:1)

这似乎不是一个错误。根据JAX-RS 2.0规范,您可以将Application注入资源类(例如),但它没有说明直接注入Application的自定义扩展。不确定您的用例是什么,但您可以注册自定义HK2 binder,以便您直接将WebApp注入资源:

public class WebApp extends org.glassfish.jersey.server.ResourceConfig {
    public WebApp() {
        packages("my.resources.package");

        register(new org.glassfish.hk2.utilities.binding.AbstractBinder() {
            @Override
            protected void configure() {
                bind(WebApp.this);
            }
        });
    }
}

答案 1 :(得分:1)

我也使用Jersey 2.4.1遇到过这个。

FWIW:根据规范8.2.1,我同意这似乎是一个错误。语句“应用程序提供的应用程序子类的实例”似乎非常清楚。

我有一个替代解决方法,不涉及glassfish.hk2,但仍然将特定于Jersey的代码集中在Application派生类中。

public class MyApp extends ResourceConfig {
...
    static MyApp getInstance( Application application) {
        try {
            // for a conformant implementation
            return (MyApp) application;
        } catch (ClassCastException e) {
            // Jersey 2.4.1 workaround
            ResourceConfig rc = (ResourceConfig) application;
            return (MyApp) rc.getApplication();
        }
    }
...
}

public class MyResource {
...
    @Context Application application;
    ...
    SomeMethod() {
    ... MyApp.getInstance( application);
    }
}

希望这很有用。

答案 2 :(得分:0)

这似乎在以后的版本og Jersey中修复。同样的方法至少适用于泽西岛2.16。我注入的Application对象是正确的子类,没有任何包装。

编辑:或许毕竟版本无关紧要。请参阅此答案的评论。