How and who should inject PersistenceContext when running tests through Jersey/Grizzly?
我有这个课程(JAX-RS / Jersey和JPA / Hibernate的混合):
1 2 3 4 5 6 7 8 9 | 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(); } } |
这是单元测试:
1 2 3 4 5 6 7 8 9 10 |
在这里一切都很好,除了以下一项:
Everything is fine here except one this: em is NULL inside read(). Looks like Grizzly (I'm using this server together with Jersey Test Framework) is not injecting PersistenceContext. What am I doing wrong here?
据我所知,最简单的解决方案是将EntityManager注入到EJB 3.1无状态会话Bean(SLSB)中,该Bean可以直接作为REST资源公开(通过使用JAX-RS注释对其进行注释)。
另一个选择是使JAX-RS资源成为托管bean,并使用CDI进行注入。这就是TOTD#124的方法:将CDI JPA与JAX-RS和JAX-WS一起使用。
在两种情况下,我认为您都需要使用Embedded GlassFish容器作为Jersey测试的容器。
资源
- 泽西测试框架使一切变得简单!
- 重新访问Jersey测试框架!
- 带有JavaScript和... EJB 3.1的RESTFul计算器
- TOTD#124:将CDI JPA与JAX-RS和JAX-WS结合使用
我找到了com.sun.jersey / jersey-grizzly2版本1.x的解决方案。我实现了一个自定义的InjectableProvider。以下代码摘自Oracle文章:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | 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; } } } |
我必须对其稍作调整以适合我的环境。还请注意,提供程序必须与您的服务类位于同一程序包中,否则它将不会被提取(在文章中没有说明)。