JSF 2.2 + EJB 3 + JPA on Glassfish 4 and Postgres ConnectionPool
ejb, glassfish, jpa, postgresql
Solution
Thanks @unwichtich for your answers but I finally found what the problem was and it was caused by my oversight! I imported the wrong @SessionScope, the one coming with JSF context (javax.faces.bean.SessionScoped) instead of the one coming with enterprise context (javax.enterprise.context.SessionScoped). Now the registration works!
Problem
my application is based on JSF 2.2 EJB 3 JPA on Glassfish 4 with Postgres 9.2 DB. I have create a ConnectionPool and Datasource on Glassfish and I use it on my application through the related Datasource JNDI name. I have two Facelets pages: login.xhtml which calls a BackingBean LoginBacking which calls login method on UserManagement EJB which checks the login by using JPA Persistence Unit. In this case everything works, the user is able to logging in and in case the email is already present the system inform the user that he is already registered. registration.xhtml which calls a BackingBean RegistrationBacking which calls register method on UserManagement EJB which persists the user into DB by using JPA Persistence Unit. The registration doesn't work! By looking into Glassfish log I found the following exception: ``` Finer: client acquired: 553217772 Finer: TX binding to tx mgr, status=STATUS_ACTIVE Finer: acquire unit of work: 218748741 Finer: begin unit of work flush Finer: end unit of work flush Finest: Execute query ReadAllQuery(referenceClass=MomUser sql="SELECT id, classname, company, email, firstname, insertion_date, lastname, password, status, systemuser FROM momuser WHERE (email = ?)") Finest: Connection acquired from connection pool [read]. Finest: reconnecting to external connection pool Fine: SELECT id, classname, company, email, firstname, insertion_date, lastname, password, status, systemuser FROM momuser WHERE (email = ?) bind => [1 parameter bound] Finest: Connection released to connection pool [read]. Finer: TX beforeCompletion callback, status=STATUS_ACTIVE Finer: begin unit of work commit Finer: TX afterCompletion callback, status=COMMITTED Finer: end unit of work commit Finer: release unit of work Finer: client released Finer: client acquired: 1869986747 Finer: TX binding to tx mgr, status=STATUS_ACTIVE Finer: acquire unit of work: 76560055 Finer: TX afterCompletion callback, status=ROLLEDBACK Finer: release unit of work Finer: client released Warning: EJB5184:A system exception occurred during an invocation on EJB MomUserManager, method: public void eu.fabrig.mom.session.MomUserManager.registerUser(eu.fabrig.mom.jpa.entity.MomUser) throws eu.fabrig.mom.exception.UserExistsException Warning: javax.ejb.EJBException at com.sun.ejb.containers.EJBContainerTransactionManager.processSystemException(EJBContainerTransactionManager.java:748) at com.sun.ejb.containers.EJBContainerTransactionManager.completeNewTx(EJBContainerTransactionManager.java:698) ... at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544) at java.lang.Thread.run(Thread.java:744) Caused by: java.lang.IllegalArgumentException: Object: MomUser{id=null, classname=MOMUser, status=A, systemuser=null, insertionDate=null, email=a@c.it, password=098f6bcd4621d373cade4e832627b4f6, firstname=test, lastname=test, company=Test S.p.A.} is not a known entity type. at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerNewObjectForPersist(UnitOfWorkImpl.java:4222) ... at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:212) ... 54 more Severe: javax.ejb.EJBException at com.sun.ejb.containers.EJBContainerTransactionManager.processSystemException(EJBContainerTransactionManager.java:748) at com.sun.ejb.containers.EJBContainerTransactionManager.completeNewTx(EJBContainerTransactionManager.java:698) ... at java.lang.Thread.run(Thread.java:744) Caused by: java.lang.IllegalArgumentException: Object: MomUser{id=null, classname=MOMUser, status=A, systemuser=null, insertionDate=null, email=a@c.it, password=098f6bcd4621d373cade4e832627b4f6, firstname=test, lastname=test, company=Test S.p.A.} is not a known entity type. at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerNewObjectForPersist(UnitOfWorkImpl.java:4222) at org.eclipse.persistence.internal.jpa.EntityManagerImpl.persist(EntityManagerImpl.java:496) ... at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:212) ... 54 more Info: ### You can do the cleanup here ``` Below my persistence.xml: ``` <?xml version="1.0" encoding="UTF-8"?> <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> <persistence-unit name="eu.fabrig_MOM.PU" transaction-type="JTA"> <jta-data-source>myDataSource</jta-data-source> <exclude-unlisted-classes>false</exclude-unlisted-classes> <!-- <class>eu.fabrig.mom.jpa.entity.MomUser</class> --> <properties> <property name="eclipselink.logging.level" value="FINEST"/> </properties> </persistence-unit> </persistence> ``` My Entity and Managed Bean class: ``` @Entity @Table(name = "momuser") @Named @RequestScoped @XmlRootElement public class MomUser implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_seq_gen") @SequenceGenerator(name = "user_seq_gen", sequenceName = "mom_seq_id") @Basic(optional = false) @Column(name = "id") private Integer id; @Basic(optional = false) @Size(min = 1, max = 100) @Column(name = "classname") private String classname = "MOMUser"; @Column(name = "status") private Character status = 'A'; @Size(max = 100) @Column(name = "systemuser") private String systemuser; @Basic(optional = false) @Column(name = "insertion_date", insertable = false, updatable = false) @Temporal(TemporalType.TIMESTAMP) private Date insertionDate; @Basic(optional = false) @NotNull @Size(min = 1, max = 255) @Column(name = "email") private String email; @Basic(optional = false) @NotNull @Size(min = 1, max = 255) @Column(name = "password") private String password; @Basic(optional = false) @NotNull @Size(min = 1, max = 255) @Column(name = "firstname") private String firstname; @Basic(optional = false) @NotNull @Size(min = 1, max = 255) @Column(name = "lastname") private String lastname; @Size(max = 100) @Column(name = "company") private String company; ... // Getters and Setters ``` Below the EJB method: ``` @Override public void registerUser(MomUser user) throws UserExistsException { try { user.setPassword(generateMD5Hash(user.getPassword())); em.persist(user); } catch (UnsupportedEncodingException | NoSuchAlgorithmException ex) { Logger.getLogger(MomUserManager.class.getName()).log(Level.SEVERE, null, ex); } } ``` The Backing bean method: ``` public String register(){ try { MomUser currentMomUser = (MomUser) evaluateEL("#{momUser}", MomUser.class); MomUser momUser = userManager.getUser(currentMomUser.getEmail()); if (momUser != null) { getContext().addMessage(null, new FacesMessage(EMAIL_ALREADY_EXISTS)); return null; } try { userManager.registerUser(currentMomUser); } catch (UserExistsException ex) { Logger.getLogger(RegistrationBacking.class.getName()).log(Level.SEVERE, null, ex); getContext().addMessage(null, new FacesMessage(EMAIL_ALREADY_EXISTS)); return null; } } catch (Exception ex) { Logger.getLogger(RegistrationBacking.class.getName()).log(Level.SEVERE, null, ex); getContext().addMessage(null, new FacesMessage(SYSTEM_ERROR)); return null; } return "login"; } ``` And the registration Facelet: ``` <f:facet name="header"> <h:outputText value="#{bundle['application.registerpage.registrationMessage']}"/> </f:facet> <h:outputText value="#{bundle['momuser.email']}"/><h:inputText id="email" value="#{momUser.email}" required="true" requiredMessage="#{bundle['momuser.email.validation']}" validatorMessage="#{bundle['momuser.email.invalid']}"> <f:validateRegex pattern="[\w\.-]*[a-zA-Z0-9_]@[\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]"/> </h:inputText> <h:message for="email" styleClass="errorMessage"/> <h:outputText value="#{bundle['momuser.password']}"/> <h:inputSecret id="password" value="#{momUser.password}" required="true" requiredMessage="#{bundle['momuser.password.validation']}"></h:inputSecret> <h:message for="password" styleClass="errorMessage"/> <h:outputText value="#{bundle['momuser.firstname']}"/> <h:inputText id="firstname" value="#{momUser.firstname}" required="true" requiredMessage="#{bundle['momuser.firstname.validation']}"/> <h:message for="firstname" styleClass="errorMessage"/> <h:outputText value="#{bundle['momuser.lastname']}"/> <h:inputText id="lastname" value="#{momUser.lastname}" required="true" requiredMessage="#{bundle['momuser.lastname.validation']}"/> <h:message for="lastname" styleClass="errorMessage"/> <h:outputText value="#{bundle['momuser.company']}"/> <h:inputText id="company" value="#{momUser.company}" required="false"/> <h:message for="company" styleClass="errorMessage"/> <f:facet name="footer"> <h:panelGroup style="display:block; text-align:center"> <h:commandButton value="#{bundle['application.registrationpage.proceed']}" action="/registration/registrationconfirm?faces-redirect=true"/> <h:commandButton value="Register" action="#{registrationBacking.register}"/> <h:link value="#{bundle['application.registrationpage.gotologin']}" outcome="/login"/> <h:messages globalOnly="true" styleClass="errorMessage"/> </h:panelGroup> </f:facet> </h:panelGrid> </h:form> ``` Do you have any idea? Why am I able to loggin in but I am not able to register new user? Thanks