2011-01-16 36 views
38

Tôi có một cuộc chiến tranh có chứa những điều sau đây:PersistenceContext EntityManager tiêm NullPointerException

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> 

lớp TestServlet của tôi là như sau :

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

Khi phương thức get() được gọi, tôi nhận được NullPointerException; EntityManager chưa được tiêm. Bất kỳ đề xuất nào về những gì tôi có thể bị thiếu hoặc cách tôi có thể chẩn đoán nó? Có rất ít trong nhật ký máy chủ.

Tôi chắc rằng tôi đã làm việc này mà không cần tệp jboss-web.xml hoặc mục nguồn dữ liệu trong tệp web.xml. Tôi cũng đã triển khai ds.xml vào thư mục triển khai một cách riêng biệt và chắc chắn đã được chọn - tôi có thể thấy nó trong giao diện điều khiển JMX.

Đã thử sử dụng JBoss 4.2.3 và bản dựng 6.0 có cùng kết quả.

+0

Đoán có vấn đề với việc đăng XML trong phần mã ?! – rich

+0

Bạn sẽ phải thoát khỏi < and > -> < và > – adrianboimvaser

+3

Tôi chưa bao giờ thử nó trong thực tế, do đó, không ghim tôi vào nó, nhưng nó thực sự có thể chạy JPA trên một webapp được khai báo để chạy như Servlet 2.3 (J2EE 1.3) thay vì Servlet 2.5 (Java EE 5, khi JPA được giới thiệu lần đầu tiên)? – BalusC

Trả lời

70

Trình quản lý đối tượng chỉ có thể được chèn vào các lớp đang chạy bên trong một giao dịch. Nói cách khác, nó chỉ có thể được tiêm vào một EJB. Classe khác phải sử dụng EntityManagerFactory để tạo và phá hủy một EntityManager.

Vì TestService của bạn không phải là EJB, chú thích @PersistenceContext chỉ bị bỏ qua. Không chỉ vậy, trong JavaEE 5, không thể tiêm một EntityManager và EntityManagerFactory trong một dịch vụ JAX-RS. Bạn phải đi với một máy chủ JavaEE 6 (JBoss 6, Glassfish 3, vv).

Dưới đây là một ví dụ về cách tiêm một 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(); 
     } 
    } 
} 

Cách đơn giản nhất để đi ở đây là để tuyên bố dịch vụ của bạn như một EJB 3.1, giả sử bạn đang sử dụng một máy chủ JavaEE 6.

câu hỏi liên quan: Inject an EJB into JAX-RS (RESTful service)

+1

Cảm ơn, vấn đề tương tự mặc dù trong đó tôi nhận được một NPE trên dòng này:

 EntityManager entityManager = entityManagerFactory.createEntityManager(); 
rich

+0

Cảm ơn, điều này đã làm việc cho tôi! Tôi đang sử dụng CXF 2.7.5, Hibernate 4.x, Spring 3.x, và JPA 2.x. –

+0

Xin vui lòng cho tôi biết lý do tại sao tôi không thể tiêm một người quản lý thực thể trong các bean không có trạng thái @PersistenceContext (unitName = "Tester2PU") riêng EntityManager em; trong tomcat 7.0.27 là null. cảm ơn senthil – user1503117

2

Nếu thành phần này là một EJB, sau đó, có nên không phải là một vấn đề tiêm một EM.

Nhưng .... Trong JBoss 5, tích hợp JAX-RS không tuyệt vời. Nếu bạn có một EJB, bạn không thể sử dụng chức năng quét và bạn phải tự liệt kê trong context-param resteasy.jndi.resource. Nếu bạn vẫn còn quét, Resteasy sẽ quét lớp tài nguyên và đăng ký nó như một dịch vụ JAX-RS vani và xử lý vòng đời.

Đây có thể là sự cố.

Các vấn đề liên quan