【问题标题】:How and who should inject PersistenceContext when running tests through Jersey/Grizzly?通过 Jersey/Grizzly 运行测试时,应该如何以及谁应该注入 PersistenceContext?
【发布时间】:2010-09-28 15:51:40
【问题描述】:

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

public class Factory {
  @PersistenceContext(unitName = "abc")
  EntityManager em;
  @Path("/{id}")
  @GET
  public String read(@PathParam("id") int i) {
    return em.find(Employee.class, i).getName();
  }
}

这是单元测试:

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

这里一切都很好,除了一个:emNULLread() 中。看起来 Grizzly(我将此服务器与 Jersey 测试框架一起使用)没有注入 PersistenceContext。我在这里做错了什么?

【问题讨论】:

    标签: java hibernate jpa jersey jax-rs


    【解决方案1】:

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

    1. 我不确定 Grizzly 是否提供注射服务。
    2. 我不确定“任何”泽西资源是否支持注入(Paul Sandoz 似乎暗示它应该在 this thread 中,但我找不到该声明的明确证据)。

    据我所知,最简单的解决方案是将 EntityManager 注入到 EJB 3.1 无状态会话 Bean (SLSB) 中,它可以直接作为 REST 资源公开(通过使用 JAX- RS 注释)。

    另一种选择是使 JAX-RS 资源成为托管 bean 并使用 CDI 进行注入。这就是TOTD #124: Using CDI + JPA with JAX-RS and JAX-WS 的做法。

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

    资源

    【讨论】:

    • “在这两种情况下,我认为您都需要使用 Embedded GlassFish 容器作为 Jersey 测试的容器。” ——而不是灰熊?
    • @Vincenzo 是的,而不是 Grizzly。
    • “另一个选项将使 JAX-RS 资源成为托管 bean”——这意味着我必须将我的 Factory 类拆分为两个类 FactoryRestFactoryBean,然后是 CDI 注入 @ 987654330@ 转为FactoryRest。我没听错吗?
    • @Vincenzo 好吧,您可以尝试通过 CDI 注入 EMF(请记住,EntityManager 不是线程安全的)。或者你确实可以有 2 个类并注入一个 EJB。但是,如果您可以将 EJB 直接公开为 REST 资源,我真的看不出拥有 2 个类的意义。
    【解决方案2】:

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

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

    我不得不稍微调整一下以适应我的环境。另请注意,提供者必须与您的服务类在同一个包中,否则将不会被拾取(文章中没有说)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-06
      • 1970-01-01
      • 1970-01-01
      • 2013-01-11
      • 1970-01-01
      • 2021-11-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多