PersistenceContext EntityManager injection NullPointerException

Ho una guerra che contiene quanto segue:

META-INF/MANIFEST.MF WEB-INF/classs/META-INF/persistence.xml WEB-INF/classs/com/test/service/TestServlet.class WEB-INF/classs/com/test/service/TestEntity.class WEB-INF/classs/jndi.properties WEB-INF/classs/postgresql-ds.xml WEB-INF/jboss-web.xml WEB-INF/web.xml index.jsp 

persistence.xml:

    org.hibernate.ejb.HibernatePersistence java:/TestDS        

web.xml:

   Test Web Application  resteasy.scan true   org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap   Resteasy org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher   Resteasy /service/*   TestDS javax.sql.DataSource Container Shareable   

La mia class TestServlet è la seguente:

 package com.test.service; import java.util.*; import javax.persistence.*; import javax.ws.rs.*; @Path("/service") public class TestService { @PersistenceContext(unitName = "test") private EntityManager em; @GET @Path("/get") @Produces("application/json") public List get() { return em.createQuery("from TestEntity").getResultList(); } } 

Quando viene richiamato il metodo get () ottengo una NullPointerException; EntityManager non è stato iniettato. Qualche suggerimento su cosa potrei mancare o su come posso diagnosticare? C’è molto poco nel registro del server.

Sono sicuro che ho funzionato senza jboss-web.xml o la voce dell’origine dati in web.xml. Ho anche distribuito il ds.xml nella directory deploy separatamente e questo è stato sicuramente rilevato – Posso vederlo nella console JMX.

Ho provato a utilizzare JBoss 4.2.3 e una build 6.0 con lo stesso risultato.

Un gestore di quadro può essere iniettato solo in classi in esecuzione all’interno di una transazione. In altre parole, può essere iniettato solo in un EJB. Altre classi devono utilizzare EntityManagerFactory per creare e distruggere un EntityManager.

Poiché TestService non è un EJB, l’annotazione @PersistenceContext viene semplicemente ignorata. Non solo, in JavaEE 5, non è ansible iniettare un EntityManager né un EntityManagerFactory in un servizio JAX-RS. Devi andare con un server JavaEE 6 (JBoss 6, Glassfish 3, ecc.).

Ecco un esempio di iniezione di EntityManagerFactory:

 package com.test.service; import java.util.*; import javax.persistence.*; import javax.ws.rs.*; @Path("/service") public class TestService { @PersistenceUnit(unitName = "test") private EntityManagerFactory entityManagerFactory; @GET @Path("/get") @Produces("application/json") public List get() { EntityManager entityManager = entityManagerFactory.createEntityManager(); try { return entityManager.createQuery("from TestEntity").getResultList(); } finally { entityManager.close(); } } } 

Il modo più semplice per andare qui è dichiarare il tuo servizio come EJB 3.1, assumendo che tu stia utilizzando un server JavaEE 6.

Domanda correlata: iniettare un EJB in JAX-RS (servizio RESTful)

Se il componente è un EJB, quindi, non dovrebbe esserci un problema nell’iniettare un EM.

Ma … In JBoss 5, l’integrazione JAX-RS non è eccezionale. Se si dispone di un bean, non è ansible utilizzare la scansione ed è necessario elencare manualmente nel contesto-rest restibley.jndi.resource. Se è ancora in corso la scansione, Resteasy analizzerà la class di risorse e la registrerà come un servizio JAX-RS vanigliato e gestirà il ciclo di vita.

Questo è probabilmente il problema.