2013-11-14 25 views
3

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

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子类本身,因为这会创建循环依赖关系。

应用程序提供的子类ApplicationWebApp,不JAX-RS特定于实现的包装。

此外,更改该片段

@Context 
    Application app; 

@Context 
    WebApp app; 

导致app上下文注射期间为null,由于ClassCastException,所以声明的类型并不重要。

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

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

+0

你能向我们展示'ClassCastException'吗? –

+0

对不起,现在无法检测到。但是当我调试这个问题的时候,我相信它是存在的(可能仍然是Jersey 2.2),并且这个例外是由于将'ResourceConfig $ WrappingResourceConfig'映射到我的'WebApp'。这个例外正在被捕获,并且没有进行调查。 – pwes

回答

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

“*应用程序提供的应用程序子类*”的实例来自引用的规范。具体说我的'WebApp'。 – pwes

+0

至于我的用例,我想开发一个将应用程序注入资源的JAX-RS实现不可知的方式。 HK2绑定器看起来几乎完美,只留下Application子类的代码中的Glassfish依赖项。 – pwes

+0

我认为这句话的含义是你可以注入'Application'类型,你会得到你的子类的一个实例,但不是你可以直接将你的子类注入到'WebApp'字段中。 –

1

我也曾经遇到过这种使用泽西2.4.1。

FWIW:我同意它看起来像根据规范8.2.1的错误。声明“应用程序提供的应用程序子类”的实例似乎非常清楚。

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

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

希望这是有用的。

+0

当然,我现在注意到,原始海报发现了“getApplication()”解决方法,这是我所认为的贡献的核心。 –

0

这似乎是固定在更高版本泽西。至少对泽西2.16来说,同样的方法也适用于我。我注入的Application对象是正确的子类,没有任何包装。

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

+0

您能否将您的代码发送给注入的应用程序子类,注入的资源和web.xml?我仍然在Jersey 2.17 – pwes

+0

@pwes中发生了包装你用你的原始文章中的WebApp和Test类做了一个快速测试,只改变了包/类名,并且输出了解包的WebApp类的名字。也许不同之处在于Web服务器以及它的设置方式。我使用Jetty并执行此操作:'JettyHttpContainerFactory.createServer(uri,new WebApp());'。我不使用web.xml文件。 – Zero3

+0

看起来像包裹是在Jersey的ResourceConfig.java中的'forApplicationClass()'方法中完成的。 [搜索他们的GitHub回购这个方法名称](https://github.com/jersey/jersey/search?utf8=%E2%9C%93&q=forApplicationClass)给出了一些有趣的结果。例如,在似乎用于Servlet 3.x部署的JerseyServletContainerInitializer.java中,该方法在多个代码路径中使用。我的猜测是,你正在观察的包装是由你的部署方法以及泽西岛如何选择实现该方法引起的。 – Zero3