Question

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 injecting PersistenceContext. What am I doing wrong here?

Was it helpful?

Solution

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

OTHER TIPS

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).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top