【问题标题】:JAX-RS Application subclass injectionJAX-RS 应用程序子类注入
【发布时间】:2013-11-14 20:12:55
【问题描述】:

我正在编写自定义 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;

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

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

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

【问题讨论】:

  • 你能告诉我们ClassCastException吗?
  • 抱歉,现在检测不到。但我确信它在我调试问题时存在(可能仍然是 Jersey 2.2),异常是由于将ResourceConfig$WrappingResourceConfig 映射到我的WebApp。异常被捕获并且没有执行。

标签: java jersey jax-rs jersey-2.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);
            }
        });
    }
}

【讨论】:

  • 应用程序提供的应用程序子类的实例”来自引用的规范。特别提到了我的WebApp
  • 至于我的用例,我想开发一种与 JAX-RS 实现无关的方式将应用程序注入资源。 HK2 binder 看起来几乎完美,仅在 Application 子类的代码中留下 Glassfish 依赖项。
  • 我认为这句话的意思是你可以注入Application类型,你会得到你的子类的一个实例,但不是你可以直接将你的子类注入WebApp字段。
  • 事实并非如此。正如我在问题中所写,当我定义字段 @Context Application app 时,结果是相同的:app 有 Jersey 包装对象,而不是我的子类对象。
【解决方案2】:

我在使用 Jersey 2.4.1 时也遇到过这种情况。

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

我有一个不涉及 glassfish.hk2 但仍将 Jersey 特定代码集中在应用程序派生类中的替代解决方法。

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

希望这是有用的。

【讨论】:

  • 当然,我现在注意到原始发帖人找到了“getApplication()”解决方法,这是我所谓的贡献的核心。
【解决方案3】:

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

编辑:或者也许版本是无关紧要的。请参阅此答案的 cmets。

【讨论】:

  • 能否请您发送您注入的Application子类的代码、注入它的资源和web.xml?我仍然在 Jersey 2.17 中发生包装
  • @pwes 我对您原始帖子中的WebAppTest 类进行了快速测试,只更改了包/类名称,它输出了未包装的WebApp 类的名称。也许不同之处在于 Web 服务器及其设置方式。我使用 Jetty 并这样做:JettyHttpContainerFactory.createServer(uri, new WebApp());。我不使用 web.xml 文件。
  • 似乎包装是在 Jersey 的 ResourceConfig.java 中的 forApplicationClass() 方法中完成的。 Searching their GitHub repo for this method name 给出了一些有趣的结果。例如,在似乎用于 Servlet 3.x 部署的 JerseyServletContainerInitializer.java 中,该方法在多个代码路径中使用。我的猜测是,您正在观察的包装是由您的部署方法以及 Jersey 如何选择实现该方法引起的。
猜你喜欢
  • 1970-01-01
  • 2017-06-18
  • 2015-06-13
  • 1970-01-01
  • 2017-03-28
  • 1970-01-01
  • 2016-12-06
  • 1970-01-01
  • 2022-01-19
相关资源
最近更新 更多