问题描述:

Yet another 'EntityManager is null' question. I've searched for an answer but haven't found one that works for me. I'm taking over a large project and I'm trying to simplify it to cut out red herrings when debugging. I'm down to a simple Customer/Order system and I'm just trying to deploy it and view the list of customers. Based on another question I asked and a resulting suggestion I'm down to the following (actual question and stack trace at bottom):

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>

webpage - 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

}

Customer.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;

}

}

My Application deploys but I get the ubiquitous NullPointerException when trying to view the menu.xhtml page. The following is logged when I deploy my application:

-WARNING|org.apache.catalina.connector.Request|_ThreadID=37;_ThreadName=Thread-2;|PWC4011: Unable to set request character encoding to UTF-8 from context , because request parameters have already been read, or ServletRequest.getReader() has already been called|#]

-INFO|uploadFileName=MyWebApp-0.0.1-SNAPSHOT.war|#]

-INFO|javax.enterprise.system.container.ejb.com.sun.ejb.containers|Portable JNDI names for EJB PersistenceStoreManager: [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 loaded|#]

-INFO|javax.enterprise.system.std.com.sun.enterprise.server.logging|em is null: true|#]

-INFO|javax.enterprise.resource.webcontainer.jsf.config|Initializing Mojarra 2.1.6 (SNAPSHOT 20111206) for context '/MyWebApp-0.0.1-SNAPSHOT'|#]

-INFO|org.primefaces.webapp.PostConstructApplicationEventListener|Running on PrimeFaces 3.4.1|#]

-INFO|javax.enterprise.system.container.web.com.sun.enterprise.web|WEB0671: Loading application [MyWebApp-0.0.1-SNAPSHOT] at [/MyWebApp-0.0.1-SNAPSH 6243 OT]|#]

-INFO|javax.enterprise.system.tools.admin.org.glassfish.deployment.admin|MyWebApp-0.0.1-SNAPSHOT was successfully deployed in 1,598 milliseconds.|#]

When I navigate to myserver:8080/MyWebApp-0.0.1-SNAPSHOT/faces/index.xhtml The following is logged:

[#|2014-06-06T16:51:56.988+0100|SEVERE|glassfish3.1.2|javax.enterprise.resource.webcontainer.jsf.application|_ThreadID=36;_ThreadName=Thread-2;|Error Rendering View[/index.xhtml]

javax.el.ELException: /templates/menu.xhtml @15,64 value="#{customerController.getUrl()}": org.jboss.weld.exceptions.WeldException: WELD-000049 Unable to invoke [method] @PostConstruct public my.webapp.web.controller.CustomerController.init() on [email protected]

at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:114)

at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194)

...[long stack trace]...

Caused by: java.lang.NullPointerException

at my.model.Customer.getAllRecords(Customer.java:64)

at my.webapp.web.controller.CustomerController.findAll(CustomerController.java:41)

at my.webapp.web.controller.CustomerController.init(CustomerController.java:37)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

...[long stack trace]...

None of the logging in the postInject() methods in Customer, CustomerController and PersistenceStoreManager is being output. Since they are annotated with @PostConstruct and should be called after injection, I assume that the EJB injection isn't taking place.

Can anyone see why the EJB injection isn't happening?

网友答案:

EJB is not injected because they can be only injected in container managed classes and entities are not container managed classes. Container managed classes are listed for example in Java EE 6 specification.

相关阅读:
Top