【问题标题】:EntityManager NullPointerExceptionEntityManager NullPointerException
【发布时间】:2014-06-06 16:15:07
【问题描述】:

又一个“EntityManager 为空”问题。我一直在寻找答案,但没有找到适合我的答案。我正在接管一个大型项目,并试图简化它以在调试时消除红鲱鱼。我只需要一个简单的客户/订单系统,我只是想部署它并查看客户列表。根据我提出的另一个问题和resulting suggestion,我得出以下结论(实际问题和堆栈跟踪位于底部):

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" 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_2_0.xsd">
  <persistence-unit name="my_PU" transaction-type="JTA">
      <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <jta-data-source>my_datasource</jta-data-source>
        <class>my.database.model.Customer</class>
        <class>my.database.model.Order</class>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
    </persistence-unit>
</persistence>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>MyWebApp</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/faces/*</url-pattern>
  </servlet-mapping>
  <context-param>
    <description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description>
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
    <param-value>client</param-value>
  </context-param>
  <context-param>
    <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
    <param-value>resources.application</param-value>
  </context-param>
  <context-param>
    <param-name>javax.faces.FACELETS_LIBRARIES</param-name>
    <param-value>/WEB-INF/balusc.taglib.xml</param-value>
  </context-param>
  <context-param>
    <param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
    <param-value>true</param-value>
  </context-param>
  <filter>
    <filter-name>PrimeFaces FileUpload Filter</filter-name>
    <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>PrimeFaces FileUpload Filter</filter-name>
    <servlet-name>Faces Servlet</servlet-name>
  </filter-mapping>
  <context-param>
    <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
    <param-value>false</param-value>
  </context-param>
  <listener>
    <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
  </listener>
</web-app>

网页 - menu.xhtml

<html
 xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core">
<head>
<link rel="stylesheet" type="text/css" media="screen,projection"
    href="../css/menu.css" /></head>
<ui:component>
    <div class="menu-container">
        <div class="menu-tab">
            <ul>
                <li><a href="index.xhtml"><span>Home</span></a></li>

                <li><h:outputLink
                        value="#{customerController.getUrl()}">
                        <span><h:outputText value="Customer" /></span>
                    </h:outputLink></li>
                <li><a href=""><span>Logout</span></a></li>
            </ul>
        </div>
    </div>
</ui:component>
</html>

CustomerController.java

package my.webapp.web.controller;

import java.util.List;
import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
import my.model.Customer;

@Named(value = "customerController")
@RequestScoped
public class CustomerController// extends FormRequestController
{
    private Customer customer;
    private String id;
    protected List<?> entityObjectList;
    protected boolean editMode;

    @PostConstruct
    public void init() {
        System.out.println("CustomerController init");
        setEntityObjectList(findAll());
    }

    public List<?> findAll() {
        List<Customer> dataList = Customer.getAllRecords();
        return dataList;

    }

    public String getUrl()
    {
        System.out.println("CustomerController getUrl");
        return "www.google.com";
    }
    //getters and setters ommitted for brevity
}

客户.java

package my.model;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.ejb.EJB;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import my.database.manager.PersistenceStoreManager;

@Entity
@Table(name=Customer.TBL_NAME)
@NamedQueries({
    @NamedQuery(name=Customer.QRY_ALL, query="select object(a) from Customer a")
})
public class Customer implements Serializable {
    private static final long serialVersionUID = 1L;

    /**
     * Manager class to manager DB connections
     */
    @EJB
    private static PersistenceStoreManager<Customer> psm;
    // Table constants
    public static final String TBL_NAME = "Customer";
    public static final String QRY_ALL = TBL_NAME + ".all";

    private int id;
    private String name;
    private Set<Order> orders;

    public Customer() {
    }


    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    public int getId() {
        return this.id;
    }

    //bi-directional many-to-one association to Order
    @OneToMany(mappedBy="id")
    public Set<Order> getOrders() {
        return this.orders;
    }

    public void setOrders(Set<Order> orders) {
        this.orders = orders;
    }

    public static List<Customer> getAllRecords(){
        Map<String, Object> params = new HashMap<String, Object>();
        return psm.getResultSetList(QRY_ALL, params);
    }
    //other getters and setters omitted for brevity
}

PersistenceStoreManager.java

package my.database.manager;

import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
 * This class is responsible for performing CRUD operations using the
 * EntityManager of the PersistenceContext.
 *
 *
 */
@Stateless
public class PersistenceStoreManager<T>
{
     @PersistenceContext(unitName = "my_PU")
    private EntityManager em;


    public PersistenceStoreManager ()
    {
        System.out.println("PersistenceStoreManager loaded");
        System.out.println("em is null: "+(em==null));
    }

    @PostConstruct
    public void postInject()
    {
        System.out.println("postInject");
        System.out.println("em is null: "+(em==null));
    }

    /**
     * @param namedQuery
     * @param criteria
     * @return
     */
    public List<T> getResultSetList(String namedQuery,
            Map<String, Object> criteria) {

        Query q = em.createNamedQuery(namedQuery);
        for (Map.Entry<String, Object> entry : criteria.entrySet()) {
            q.setParameter(entry.getKey(), entry.getValue());
        }
        List<T> resultSetList = q.getResultList();
        return resultSetList;
    }
}

我的应用程序已部署,但在尝试查看 menu.xhtml 页面时,我得到了无处不在的 NullPointerException。部署应用程序时会记录以下内容:

-WARNING|org.apache.catalina.connector.Request|_ThreadID=37;_ThreadName=Thread-2;|PWC4011: Unable to set request character encoding to UTF-8 from context ,因为已经读取了请求参数,或 ServletRequest.getReader() 已被调用|#]
-INFO|uploadFileName=MyWebApp-0.0.1-SNAPSHOT.war|#]
-INFO|javax.enterprise.system.container.ejb.com.sun.ejb.containers|EJB PersistenceStoreManager 的可移植 JNDI 名称:[java:global/MyWebApp-0.0.1-SNAPSHOT/PersistenceStoreManager, java:global/MyWebApp-0.0 .1-SNAPSHOT/PersistenceStoreManager!my.database.manager.PersistenceStoreManager]|#]
-INFO|javax.enterprise.system.std.com.sun.enterprise.server.logging|PersistenceStoreManager 已加载|#]
-INFO|javax.enterprise.system.std.com.sun.enterprise.server.logging|em 为空:true|#]
-INFO|javax.enterprise.resource.webcontainer.jsf.config|为上下文“/MyWebApp-0.0.1-SNAPSHOT”初始化 Mojarra 2.1.6 (SNAPSHOT 20111206)|#]
-INFO|org.primefaces.webapp.PostConstructApplicationEventListener|在 PrimeFaces 3.4.1 上运行|#]
-INFO|javax.enterprise.system.container.web.com.sun.enterprise.web|WEB0671:在 [/MyWebApp-0.0.1-SNAPSH 6243 OT]|#] 处加载应用程序 [MyWebApp-0.0.1-SNAPSHOT]
-INFO|javax.enterprise.system.tools.admin.org.glassfish.deployment.admin|MyWebApp-0.0.1-SNAPSHOT 在 1,598 毫秒内成功部署。|#]

当我导航到 myserver:8080/MyWebApp-0.0.1-SNAPSHOT/faces/index.xhtml 时会记录以下内容:

[#|2014-06-06T16:51:56.988+0100|SEVERE|glassfish3.1.2|javax.enterprise.resource.webcontainer.jsf.application|_ThreadID=36;_ThreadName=Thread-2;|错误渲染视图[/index.xhtml]
javax.el.E​​LException: /templates/menu.xhtml @15,64 value="#{customerController.getUrl()}": org.jboss.weld.exceptions.WeldException: WELD-000049 无法调用 [方法] @PostConstruct在 my.webapp.web.controller.CustomerController@4085f7ff
上公开 my.webapp.web.controller.CustomerController.init() 在 com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:114)
在 javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194)
...[长堆栈跟踪]...
引起:java.lang.NullPointerException
在 my.model.Customer.getAllRecords(Customer.java:64)
在 my.webapp.web.controller.CustomerController.findAll(CustomerController.java:41)
在 my.webapp.web.controller.CustomerController.init(CustomerController.java:37)
在 sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)
在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
...[长堆栈跟踪]...

Customer、CustomerController 和 PersistenceStoreManager 中的 postInject() 方法中的任何日志都没有输出。由于它们使用@PostConstruct 进行注释并且应该在注入后调用,因此我假设 EJB 注入没有发生。

谁能明白为什么没有发生 EJB 注入?

【问题讨论】:

    标签: jakarta-ee jpa ejb glassfish-3


    【解决方案1】:

    EJB 没有被注入,因为它们只能注入到容器管理的类中,而实体不是容器管理的类。例如在Java EE 6 specification 中列出了容器管理的类。

    【讨论】:

    • 谢谢你,这是一个更根本问题的结果——我试图让一个实体做自己的持久性。该任务应该真正分配给控制器,然后由容器管理。我将psm 对象和使用它的方法移动到CustomerController 类并将其更改为非静态(如您提到的规范中所示)并且它正在工作!
    猜你喜欢
    • 2011-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-10
    • 2021-01-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多