Java 当通过Jersey/Grizzly运行测试时,应该如何以及由谁注入PersistenceContext?

Java 当通过Jersey/Grizzly运行测试时,应该如何以及由谁注入PersistenceContext?,java,hibernate,jpa,jersey,jax-rs,Java,Hibernate,Jpa,Jersey,Jax Rs,我有这个类(JAX-RS/Jersey和JPA/Hibernate的混合): 这是单元测试: public class FactoryTest extends JerseyTest { public FactoryTest() throws Exception { super("com.XXX"); } @Test public void testReadingWorks() { String name = resource().path("/1").get(St

我有这个类(JAX-RS/Jersey和JPA/Hibernate的混合):

这是单元测试:

public class FactoryTest extends JerseyTest {
  public FactoryTest() throws Exception {
    super("com.XXX");
  }
  @Test
  public void testReadingWorks() {
    String name = resource().path("/1").get(String.class);
    assert(name.length() > 0);
  }
}
这里一切正常,除了一个:
em
NULL
内部
read()
。看起来Grizzly(我将此服务器与Jersey测试框架一起使用)没有注入
PersistenceContext
。我做错了什么

这里一切正常,除了一个:em在read()中为NULL。看起来Grizzly(我将此服务器与Jersey测试框架一起使用)没有注入PersistenceContext。我做错了什么

  • 我不确定灰熊是否提供注射
  • 我不确定“任何”Jersey资源是否支持注入(Paul Sandoz似乎暗示应该支持注入,但我找不到明确的证据证明这一说法)
  • 据我所知,最简单的解决方案是将EntityManager注入EJB3.1无状态会话Bean(SLSB),该会话Bean可以直接作为REST资源公开(通过使用JAX-RS注释对其进行注释)


    另一个选项是使JAX-RS资源成为托管bean,并使用CDI进行注入。这就是我们的方法


    在这两种情况下,我认为您都需要使用嵌入的GlassFish容器作为测试的容器

    资源
    我找到了com.sun.jersey/jersey-grizzly2 1.x版的解决方案。我实现了一个定制的InjectableProvider。以下代码取自一个:

    导入javax.ejb.ejb;
    导入javax.naming.InitialContext;
    导入javax.naming.NamingException;
    导入javax.ws.rs.ext.Provider;
    导入com.sun.jersey.core.spi.component.ComponentContext;
    导入com.sun.jersey.core.spi.component.ComponentScope;
    导入com.sun.jersey.spi.inject.Injectable;
    导入com.sun.jersey.spi.inject.InjectableProvider;
    @提供者
    公共类EJBProvider实现InjectableProvider{
    公共范围getScope(){
    返回范围。单例;
    }
    公共可注入getInjectable(ComponentContext cc,EJB,类型t){
    if(!(t instanceof Class))返回null;
    试一试{
    c类=(t类);
    Context ic=新的InitialContext();
    最终对象o=ic.lookup(c.getName());
    返回新的可注射(){
    公共对象getValue(HttpContext c){
    返回o;
    }                    
    };            
    }捕获(例外e){
    e、 printStackTrace();
    返回null;
    }
    }
    }
    

    我不得不稍微调整它以适应我的环境。还请注意,提供者必须与您的服务类位于同一个包中,否则将无法获取它(文章中没有这样说)。

    “在这两种情况下,我认为您都需要使用嵌入的GlassFish容器作为球衣测试的容器。”-而不是Grizzly?@Vincenzo是的,而不是Grizzly。“另一个选项将使JAX-RS资源成为托管bean“-这意味着我必须将我的
    Factory
    类分为两个类
    FactoryRest
    FactoryBean
    ,然后CDI将
    FactoryBean
    注入
    FactoryRest
    。我理解的对吗?@Vincenzo嗯,你可以尝试通过CDI注入EMF(记住EntityManager不是线程安全的)。或者您确实可以有两个类并注入一个EJB。但是,如果您可以将EJB直接公开为REST资源,那么我并不认为拥有两个类有什么意义。
    public class FactoryTest extends JerseyTest {
      public FactoryTest() throws Exception {
        super("com.XXX");
      }
      @Test
      public void testReadingWorks() {
        String name = resource().path("/1").get(String.class);
        assert(name.length() > 0);
      }
    }
    
    import javax.ejb.EJB;
    import javax.naming.InitialContext;
    import javax.naming.NamingException;
    import javax.ws.rs.ext.Provider;
    
    import com.sun.jersey.core.spi.component.ComponentContext;
    import com.sun.jersey.core.spi.component.ComponentScope;
    import com.sun.jersey.spi.inject.Injectable;
    import com.sun.jersey.spi.inject.InjectableProvider;
    
    @Provider
    public class EJBProvider implements InjectableProvider<EJB, Type> {
    
        public Scope getScope() {
            return Scope.Singleton;
        }
    
        public Injectable getInjectable(ComponentContext cc, EJB ejb, Type t) {
            if (!(t instanceof Class)) return null;
    
            try {
                Class c = (Class)t;        
                Context ic = new InitialContext();
    
                final Object o = ic.lookup(c.getName());
    
                return new Injectable<Object>() {
                    public Object getValue(HttpContext c) {
                        return o;
                    }                    
                };            
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    }