开发者

How and who should inject PersistenceContext when running tests through Jersey/Grizzly?

I have this class (mix of JAX-RS/Jersey and 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();
  }
}

This is the unit test:

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

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 injec开发者_StackOverflow中文版ting PersistenceContext. What am I doing wrong here?


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?

  1. I'm not sure Grizzly offers injection.
  2. I'm not sure injection is supported in "any" Jersey resource anyway (Paul Sandoz seems to imply it should be in this thread but I couldn't find clear evidence of that claim).

So to my knowledge, the easiest solution would be to inject the EntityManager into an EJB 3.1 Stateless Session Bean (SLSB) which can be exposed directly as a REST resources (by annotating it with JAX-RS annotations).

Another option would make the JAX-RS resource a managed bean and to use CDI for injection. That's the approach of the TOTD #124: Using CDI + JPA with JAX-RS and JAX-WS.

In both cases, I think you'll need to use the Embedded GlassFish container as container for your Jersey Tests.

Resources

  • Jersey Test Framework makes it easy!
  • Jersey Test Framework re-visited!
  • RESTFul Calculator With JavaScript And ...EJB 3.1
  • TOTD #124: Using CDI + JPA with JAX-RS and JAX-WS


I found a solution for com.sun.jersey/jersey-grizzly2 version 1.x. I implemented a custom InjectableProvider. The following code is taken from an 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;
        }
    }
}

I had to slightly adapt it to fit my environment. Also note that the provider has to be in the same package as your service class, otherwise it won't be picked up (it does not say that in the article).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜