I've read @EJB in @ViewScoped managed bean causes java.io.NotSerializableException, but my state saving setting is server
.
Here is what I have:
web.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>sispra</display-name>
<welcome-file-list>
<welcome-file>index.jsf</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>*.jsf</url-pattern>
</servlet-mapping>
<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.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
<context-param>
<param-name>facelets.BUILD_BEFORE_RESTORE</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.ALLOW_JAVASCRIPT</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.PRETTY_HTML</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.DETECT_JAVASCRIPT</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.AUTO_SCROLL</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>primefaces.THEME</param-name>
<param-value>glass-x</param-value>
</context-param>
<security-constraint>
<web-resource-collection>
<web-resource-name>Secure Application</web-resource-name>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>user</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>fileRealm</realm-name>
</login-config>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<security-role>
<role-name>user</role-name>
</security-role>
</web-app>
customer.xhtml
:
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>TODO supply a title</title>
</h:head>
<h:body>
<p:growl id="messages"/>
<h:form>
<p:commandButton actionListener="#{customerController.create}" value="save" update="@form :messages"/>
<p:panel>
<f:facet name="header">
<h:outputText value="Details"/>
</f:facet>
<h:panelGrid columns="3">
<h:outputLabel for="name" value="#{bundle['person.name']}"/>
<p:inputText id="name" label="#{bundle['person.name']}" value="#{customerController.selected.name}"/>
<p:message for="name"/>
<h:outputLabel for="surname" value="#{bundle['person.surname']}"/>
<p:inputText id="surname" label="#{bundle['person.surname']}" value="#{customerController.selected.surname}"/>
<p:message for="surname"/>
</h:panelGrid>
</p:panel>
</h:form>
</h:body>
</html>
CustomerController.java
:
package it.shape.sispra.controllers;
import it.shape.sispra.ejb.PersonFacade;
import it.shape.sispra.entities.Customer;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
@ManagedBean
@ViewScoped
public class CustomerController extends AbstractController<Customer>
{
private static final long serialVersionUID = 134755304347034L;
@EJB
private PersonFacade facade;
public CustomerController()
{
super(Customer.class);
}
@Override
public PersonFacade getFacade()
{
return facade;
}
}
PersonFacade.java
:
package it.shape.sispra.ejb;
import it.shape.sispra.entities.Person;
import javax.ejb.Stateless;
@Stateless
public class PersonFacade extends AbstractFacade<Person>
{
private static final long serialVersionUID = 4357823648345L;
public PersonFacade()
{
super(Person.class);
}
}
AbstractFacade.java:
package it.shape.sispra.ejb;
import it.shape.sispra.entities.AbstractEntity;
import java.io.Serializable;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import org.eclipse.persistence.jpa.JpaHelper;
import org.eclipse.persistence.queries.QueryByExamplePolicy;
import org.eclipse.persistence.queries.ReadAllQuery;
import org.eclipse.persistence.queries.ReadObjectQuery;
public abstract class AbstractFacade<T extends AbstractEntity> implements Serializable
{
private static final long serialVersionUID = 12467890452346123L;
@PersistenceContext(unitName = "sispra")
private EntityManager em;
private final Class<T> entityClass;
public AbstractFacade(Class<T> entityClass)
{
this.entityClass = entityClass;
}
public EntityManager getEntityManager()
{
return em;
}
public void create(T entity)
{
getEntityManager().persist(entity);
}
public void edit(T entity)
{
getEntityManager().merge(entity);
}
public void remove(T entity)
{
getEntityManager().remove(getEntityManager().merge(entity));
}
public void refresh(T entity)
{
getEntityManager().refresh(entity);
}
public T find(Object id)
{
return getEntityManager().find(entityClass, id);
}
public List<T> findAll()
{
CriteriaQuery<T> cq = getEntityManager().getCriteriaBuilder().createQuery(entityClass);
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).getResultList();
}
public List<T> findRange(int first, int max)
{
CriteriaQuery<T> cq = getEntityManager().getCriteriaBuilder().createQuery(entityClass);
cq.select(cq.from(entityClass));
TypedQuery<T> q = getEntityManager().createQuery(cq);
q.setMaxResults(max);
q.setFirstResult(first);
return q.getResultList();
}
public int count()
{
CriteriaQuery<Long> cq = getEntityManager().getCriteriaBuilder().createQuery(Long.class);
Root<T> rt = cq.from(entityClass);
cq.select(getEntityManager().getCriteriaBuilder().count(rt));
TypedQuery<Long> q = getEntityManager().createQuery(cq);
return q.getSingleResult().intValue();
}
@SuppressWarnings("unchecked")
public T findByExample(T entity)
{
// Create a native EclipseLink query using QBE policy
QueryByExamplePolicy policy = new QueryByExamplePolicy();
policy.addSpecialOperation(String.class, "like");
ReadObjectQuery roq = new ReadObjectQuery(entity, policy);
// Wrap the native query in a standard JPA Query and execute it
Query query = JpaHelper.createQuery(roq, getEntityManager());
return (T) query.getSingleResult();
}
@SuppressWarnings("unchecked")
public List<T> findAllByExample(T entity)
{
// Create a native EclipseLink query using QBE policy
QueryByExamplePolicy policy = new QueryByExamplePolicy();
policy.addSpecialOperation(String.class, "like");
ReadAllQuery raq = new ReadAllQuery(entity, policy);
// Wrap the native query in a standard JPA Query and execute it
Query query = JpaHelper.createQuery(raq, getEntityManager());
return query.getResultList();
}
@SuppressWarnings("unchecked")
public List<T> findByExample(T entity, int start, int max)
{
// Create a native EclipseLink query using QBE policy
QueryByExamplePolicy policy = new QueryByExamplePolicy();
policy.addSpecialOperation(String.class, "like");
ReadAllQuery raq = new ReadAllQuery(entity, policy);
// Wrap the native query in a standard JPA Query and execute it
Query query = JpaHelper.createQuery(raq, getEntityManager());
query.setFirstResult(start);
query.setMaxResults(max);
return query.getResultList();
}
public int countByExample(T entity)
{
//TODO find a better way...
return findAllByExample(entity).size();
}
}
and this is the stacktrace:
GRAVE: Exiting serializeView - Could not serialize state: com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate
java.io.NotSerializableException: com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1164)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…