2011-01-16 14 views
38

Ich habe einen Krieg mit folgendem Inhalt:PersistenceContext EntityManager Injektion Nullpointer

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

persistence.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> 
    <persistence-unit name="test"> 
     <provider>org.hibernate.ejb.HibernatePersistence</provider> 
     <jta-data-source>java:/TestDS</jta-data-source> 

     <properties> 
      <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/> 
      <property name="hibernate.hbm2ddl.auto" value="update" /> 
      <property name="hibernate.show_sql" value="true" /> 
     </properties> 
    </persistence-unit> 
</persistence> 

web.xml:

<!DOCTYPE web-app PUBLIC 
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" 
"http://java.sun.com/dtd/web-app_2_3.dtd" > 

<web-app> 
    <display-name>Test Web Application</display-name> 

    <context-param> 
     <param-name>resteasy.scan</param-name> 
     <param-value>true</param-value> 
    </context-param> 
    <listener> 
     <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class> 
    </listener> 
    <servlet> 
     <servlet-name>Resteasy</servlet-name> 
     <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class> 
    </servlet> 
    <servlet-mapping> 
     <servlet-name>Resteasy</servlet-name> 
     <url-pattern>/service/*</url-pattern> 
    </servlet-mapping> 

    <resource-ref> 
     <res-ref-name>TestDS</res-ref-name> 
     <res-type>javax.sql.DataSource</res-type> 
     <res-auth>Container</res-auth> 
     <res-sharing-scope>Shareable</res-sharing-scope> 
    </resource-ref> 
</web-app> 

Meine TestServlet Klasse wird wie folgt :

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

Wenn die Methode get() aufgerufen wird, bekomme ich eine NullPointerException; Der EntityManager wurde nicht injiziert. Irgendwelche Vorschläge, was ich vermisse oder wie ich es diagnostizieren kann? Es gibt sehr wenig im Serverprotokoll.

Ich bin mir sicher, dass ich dies ohne die jboss-web.xml oder den Datenquelleneintrag in web.xml funktionierte. Ich habe die ds.xml auch separat in das Deploy-Verzeichnis deployed und das ist definitiv abgeholt - ich kann es in der JMX-Konsole sehen.

Erprobt mit JBoss 4.2.3 und einem Build 6.0 mit dem gleichen Ergebnis.

+0

Raten Sie, es gibt Probleme beim Veröffentlichen von XML in Codeabschnitten ?! – rich

+0

Sie müssten < and > -> <und> – adrianboimvaser

+3

Ich habe es nie in der Praxis versucht, also nicht mich daran fest, aber ist es wirklich möglich, JPA auf einer Webapp ausführen, die als Servlet deklariert wurde 2.3 (J2EE 1.3) anstelle von Servlet 2.5 (Java EE 5, als JPA zum ersten Mal eingeführt wurde)? – BalusC

Antwort

70

Ein Entity Manager kann nur in Klassen injiziert werden, die innerhalb einer Transaktion ausgeführt werden. Mit anderen Worten, es kann nur in einem EJB injiziert werden. Andere Klassen müssen eine EntityManagerFactory verwenden, um einen EntityManager zu erstellen und zu zerstören.

Da Ihr TestService kein EJB ist, wird die Annotation @PersistenceContext einfach ignoriert. Darüber hinaus ist es in JavaEE 5 nicht möglich, einen EntityManager oder eine EntityManagerFactory in einen JAX-RS-Service zu injizieren. Sie müssen mit einem JavaEE 6 Server (JBoss 6, Glassfish 3, usw.) gehen.

Hier ist ein Beispiel einer EntityManagerFactory der Injektion:

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

Der einfachste Weg zu gehen, ist Ihr Service als EJB 3.1 zu erklären, Sie verwenden ein JavaEE 6-Server vorausgesetzt.

Verwandte Frage: Inject an EJB into JAX-RS (RESTful service)

+1

Danke, ähnliches Problem obwohl, dass ich eine NPE in dieser Zeile:

 EntityManager entityManager = entityManagerFactory.createEntityManager(); 
rich

+0

Vielen Dank, das hat für mich funktioniert! Ich benutze CXF 2.7.5, Hibernate 4.x, Spring 3.x und JPA 2.x. –

+0

Bitte leemme wissen, warum ich keinen Entity Manager in zustandslosen Beans injizieren kann @PersistenceContext (unitName = "Tester2PU") private EntityManager em; in Tomcat 7.0.27 ist null. Danke senthil – user1503117

2

Wenn die Komponente ein EJB ist, dann sollte es kein Problem Injizieren eines EM sein.

Aber .... In JBoss 5 ist die JAX-RS-Integration nicht großartig. Wenn Sie ein EJB haben, können Sie das Scannen nicht verwenden und Sie müssen es manuell im Kontextparameter resesteasy.jndi.resource auflisten. Wenn Sie noch nicht gescannt haben, sucht Rasteasy nach der Ressourcenklasse und registriert sie als JAX-RS-Dienst von Vanilla und wickelt den Lebenszyklus ab.

Dies ist wahrscheinlich das Problem.

Verwandte Themen