Session scoped variabele is at one point null
derkd Apr 3, 2010 10:00 PMHi all,
I have been struggeling with this issue for over 8 hours now.
I make use of the Home Pattern. When I register a user the account is saved. I than go to the a page where the user can fill in their personal data (JobSeeker object). The user object is wired with the account with an page action.
<?xml version="1.0" encoding="UTF-8"?> <page xmlns="http://jboss.com/products/seam/pages" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jboss.com/products/seam/pages http://jboss.com/products/seam/pages-2.0.xsd" no-conversation-view-id="/jobseeker/index.xhtml" login-required="true"> <begin-conversation join="true" flush-mode="manual"/> <action execute="#{jobSeekerAccountHome.wire}"/> <navigation from-action="#{jobSeekerAccountHome.persist}"> <end-conversation/> <redirect view-id="/jobseeker/my_profile.xhtml"/> </navigation> <navigation from-action="#{jobSeekerAccountHome.update}"> <end-conversation/> <redirect view-id="/jobseeker/my_profile.xhtml"/> </navigation> <navigation from-action="#{jobSeekerAccountHome.remove}"> <end-conversation/> <redirect view-id="/jobseeker/my_profile.xhtml"/> </navigation> </page>
package nu.anoniemsolliciteren.account.jobseeker; import java.util.ArrayList; import java.util.Date; import java.util.List; import javax.ejb.Remove; import javax.persistence.NoResultException; import javax.persistence.Query; import nu.anoniemsolliciteren.account.GenderHome; import nu.anoniemsolliciteren.account.preferences.JobSeekerPreferencesHome; import nu.anoniemsolliciteren.account.role.Role; import nu.anoniemsolliciteren.account.role.RoleHome; import nu.anoniemsolliciteren.entities.account.jobseeker.JobSeekerAccount; import nu.anoniemsolliciteren.entities.user.JobSeeker; import nu.anoniemsolliciteren.entities.user.home.JobSeekerHome; import nu.anoniemsolliciteren.validator.AccountValidator; import org.jboss.seam.ScopeType; import org.jboss.seam.annotations.Destroy; import org.jboss.seam.annotations.Factory; import org.jboss.seam.annotations.In; import org.jboss.seam.annotations.Logger; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Out; import org.jboss.seam.annotations.Transactional; import org.jboss.seam.annotations.datamodel.DataModel; import org.jboss.seam.faces.FacesMessages; import org.jboss.seam.framework.EntityHome; import org.jboss.seam.framework.EntityNotFoundException; import org.jboss.seam.log.Log; @Name("jobSeekerAccountHome") public class JobSeekerAccountHome extends EntityHome<JobSeekerAccount> { /** * */ private static final long serialVersionUID = -2144474684920785886L; private String lastStateChanged; @In protected FacesMessages facesMessages; @In protected AccountValidator accountValidator; @In private String ipAddress; @In(required = false) protected Long accountId; @In(create = true) protected JobSeekerPreferencesHome jobSeekerPreferencesHome; @In(create = true) protected RoleHome roleHome; @In(create = true) protected JobSeekerHome jobSeekerHome; @In(create = true) protected GenderHome genderHome; private List<JobSeekerAccount> jobSeekerAccounts; @Out(required = false, scope = ScopeType.SESSION) private Long userId; @Logger private static Log log; /* * create the account instance... * @see org.jboss.seam.framework.Home#createInstance() */ @Override protected JobSeekerAccount createInstance() { log.debug("createInstance is called, trying to return JobSeekerAccount "); JobSeekerAccount jobSeekerAccount = super.createInstance(); return jobSeekerAccount; } // @Begin(join = true, flushMode = FlushModeType.MANUAL) @Override @Factory(value = "jobSeekerAccount", scope = ScopeType.CONVERSATION) public JobSeekerAccount getInstance() { log.debug("getInstance is called, trying to return JobSeekerAccount "); JobSeekerAccount jobSeekerAccount = null; if(accountId != null && accountId != 0){ log.debug("accountId != null " + accountId); setId(accountId); jobSeekerAccount = super.getInstance(); } else{ log.debug("accountId == null "); jobSeekerAccount = super.getInstance(); } if(jobSeekerAccount.getDateRegistered() == null) { jobSeekerAccount.setDateRegistered(new java.sql.Date(System.currentTimeMillis())); } jobSeekerAccount.setDateModified(new java.sql.Date(System.currentTimeMillis())); jobSeekerAccount.setIpAddress(ipAddress); log.debug("returning JobSeekerAccount's username " + jobSeekerAccount.getEmail()); log.debug("returning JobSeekerAccount's ID " + jobSeekerAccount.getId()); if(jobSeekerAccount.getUser() != null && jobSeekerAccount.getUser().getId() != 0) { userId = jobSeekerAccount.getUser().getId(); log.debug("jobSeekerAccount: userId = " + userId); } return jobSeekerAccount; } public JobSeekerAccount getDefinedInstance() { return isIdDefined() ? getInstance() : null; } public String validateEntityFound() { try { this.getInstance(); } catch (EntityNotFoundException e) { return "invalid"; } return this.isManaged() ? "valid" : "invalid"; } public void wire() { // is this necessary, because it is already saved in JobSeekerHome log.debug("wire JobSeeker to JobSeekerAccount"); JobSeeker jobSeeker = jobSeekerHome.getInstance(); if (jobSeeker != null) { getInstance().setUser(jobSeeker); } } public boolean isWired() { if (getInstance().getUser() == null) { return false; } return true; } public boolean isUsernameAvailable(String userName) { return getEntityManager().createQuery( "select a from JobSeekerAccount a where a.userName = :userName") .setParameter("userName", userName) .getResultList().size() == 0; } public boolean isEmailRegistered(String email) { return getEntityManager().createQuery( "select a from JobSeeker a where a.email = :email") .setParameter("email", email) .getResultList().size() > 0; } public JobSeekerAccount getJobSeekerAccountByUserName(String userName){ return (JobSeekerAccount) getEntityManager().createQuery( "select distinct a from JobSeekerAccount a where a.userName = :userName") .setParameter("userName", userName) .getSingleResult(); } public String next(){ return "next"; } @Transactional public JobSeekerAccount getUserByActivation(String activationKey) { Query q = getEntityManager() .createQuery("from JobSeekerAccount u where u.active=0 AND u.activationKey=:activationKey"); q.setParameter("activationKey", activationKey); JobSeekerAccount activatedUser = null; try { activatedUser = (JobSeekerAccount) q.getSingleResult(); } catch (javax.persistence.NoResultException nre) { // safe to ignore ... } if (activatedUser != null) { activatedUser.setActive(true); activatedUser.setActivationKey(null); accountId = activatedUser.getId(); // credentials.setUsername(loginUserId); log.info("UserId {0} activated successfully.", accountId); } return activatedUser; } public JobSeekerAccount byUserName(String userName) { try { Query q = getEntityManager() .createQuery("from JobSeekerAccount u where u.userName = :userName"); q.setParameter("userName", userName); return (JobSeekerAccount) q.getSingleResult(); } catch (NoResultException nre) { log.error("no user found with username "+ userName +" in JobSeekerAccountHome.byUserName(" + userName + ")"); log.error("error: " + nre); return null; } } protected boolean hasUser(String userName) { boolean hasUser = false; if (userName != null) { Query q = getEntityManager() .createQuery("select u.userName from JobSeekerAccount u where u.userName = :userName"); q.setParameter("userName", userName); hasUser = (q.getResultList().size() > 0); } return hasUser; } protected Role getRole(String roleName) { try { Query q = getEntityManager() .createQuery("from Role r where r.name = :roleName"); q.setParameter("roleName", roleName); return (Role) q.getSingleResult(); } catch (NoResultException nre) { log.error("error" + nre); return null; } } @DataModel(scope = ScopeType.PAGE) public List<JobSeekerAccount> getJobSeekerAccounts() { return jobSeekerAccounts; } public void setJobSeekerAccounts(List<JobSeekerAccount> jobSeekerAccounts) { this.jobSeekerAccounts = jobSeekerAccounts; } @Transactional @SuppressWarnings("unchecked") public void retrieveJobSeekers() { log.debug("retrieveJobSeekers is called "); jobSeekerAccounts = (List<JobSeekerAccount>) getEntityManager().createQuery( "from JobSeekerAccount jobSeeker") .getResultList(); if(jobSeekerAccounts == null) { log.debug("jobSeekerAccounts == null "); jobSeekerAccounts = new ArrayList<JobSeekerAccount>(); }else { log.debug("courses != null, size is: " + jobSeekerAccounts.size()); for(JobSeekerAccount jobSeekerAccount : jobSeekerAccounts) { log.debug("jobSeekerAccount name and id"); log.debug(jobSeekerAccount.getUserName()); log.debug(jobSeekerAccount.getId()); log.debug("-----------------"); } } } // @SuppressWarnings("unchecked") @Override @Transactional public String persist() { log.debug("persist jobSeekerAccount..."); JobSeekerAccount jobSeekerAccount = getInstance(); // IPreferences<JobSeekerPreferences> prefs = jobSeekerPreferencesHome.getInstance(); // prefs.setUserId(jobSeekerAccount.getId()); // prefs.setCountry("US"); // prefs.setProfilePolicy(ProfilePolicy.PRIVATE); // jobSeekerPreferencesHome.persist(); // jobSeekerAccount.setPreferences(prefs); Role userRole = getRole("jobSeeker"); if (userRole == null) { log.debug("userRole is null"); userRole = roleHome.getInstance(); userRole.setName("jobSeeker"); userRole.setDescription("General jobSeeker role."); log.debug("try to persist userRole"); roleHome.persist(); } jobSeekerAccount.addRole(userRole); jobSeekerAccount.setDateRegistered(new Date(System.currentTimeMillis())); lastStateChanged = super.persist(); // userId = getInstance().getUser().getId(); return lastStateChanged; } // @End @Override @Transactional public String update() { log.debug("update jobSeekerAccount..."); JobSeekerAccount jobSeekerAccount = getInstance(); log.info("Updating JobSeekerAccount #{account.userName}"); log.debug("pass bij updaten is: " + jobSeekerAccount.getPasswordHash()); jobSeekerAccount.setDateModified(new java.sql.Date(System.currentTimeMillis())); jobSeekerAccount.setIpAddress(ipAddress); lastStateChanged = super.update(); if(getInstance().getUser() != null && getInstance().getUser().getId() != 0) { userId = getInstance().getUser().getId(); } log.debug("userId: " + userId); log.debug("account isManaged? " + isManaged()); log.debug("account " + jobSeekerAccount.getEmail() + " updated " + lastStateChanged); return lastStateChanged; } // @End @Override @Transactional public String remove() { lastStateChanged = super.remove(); userId = null; log.debug("account removed " + lastStateChanged); return lastStateChanged; } @Destroy @Remove public void destroy(){ log.debug("jobSeekerAccountHome destroyed"); } }
package nu.anoniemsolliciteren.entities.user.home; import nu.anoniemsolliciteren.account.jobseeker.JobSeekerAccountHome; import nu.anoniemsolliciteren.entities.account.jobseeker.JobSeekerAccount; import nu.anoniemsolliciteren.entities.user.JobSeeker; import org.jboss.seam.ScopeType; import org.jboss.seam.annotations.Factory; import org.jboss.seam.annotations.In; import org.jboss.seam.annotations.Logger; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Transactional; import org.jboss.seam.framework.EntityHome; import org.jboss.seam.framework.EntityNotFoundException; import org.jboss.seam.log.Log; @Name("jobSeekerHome") public class JobSeekerHome extends EntityHome<JobSeeker> { /** * */ private static final long serialVersionUID = 5589141978796577591L; private String lastStateChanged; @Logger private static Log log; @In(create = true) protected JobSeekerAccountHome jobSeekerAccountHome; @In(required = false) private Long userId; /* * create the a user instance... * @see org.jboss.seam.framework.Home#createInstance() */ // @Begin(join = true, flushMode = FlushModeType.MANUAL) @Override @Factory(value = "jobSeeker", scope = ScopeType.CONVERSATION) public JobSeeker getInstance() { log.debug("getInstance is called, trying to return a jobSeeker "); if(userId != null && userId != 0) { log.debug("userId: " + userId); setId(userId); }else{ log.debug("userId is null: " + userId); } JobSeeker jobSeeker = super.getInstance(); return jobSeeker; } @Override public Object getId() { if(userId == null) { log.debug("userId in getId() is null"); return userId; }else{ log.debug("userId in getId() is null"); return super.getId(); } } public JobSeeker getDefinedInstance() { return isIdDefined() ? getInstance() : null; } public String validateEntityFound() { try { this.getInstance(); } catch (EntityNotFoundException e) { return "invalid"; } return this.isManaged() ? "valid" : "invalid"; } public void wire() { log.debug("wire JobSeeker to JobSeekerAccount"); JobSeekerAccount jobSeekerAccount = jobSeekerAccountHome.getInstance(); log.debug("get jobSeekerAccountID " + jobSeekerAccount.getId()); if (jobSeekerAccount != null) { jobSeekerAccount.setUser(getInstance()); } } public boolean isWired() { JobSeekerAccount jobSeekerAccount = jobSeekerAccountHome.getInstance(); if (jobSeekerAccount != null && jobSeekerAccount.getUser() != null) { return true; } return false; } // @End @Override @Transactional public String update() { lastStateChanged = super.update(); // userId = getInstance().getId(); log.debug("jobSeeker is updated and isManaged? " + isManaged()); log.debug("jobSeeker with userId: " + userId + " is updated"); return lastStateChanged; } // @End @Override @Transactional public String remove() { lastStateChanged = super.remove(); // userId = null; log.debug("jobSeeker removed " + lastStateChanged); return lastStateChanged; } // @End @Override @Transactional public String persist() { lastStateChanged = super.persist(); // userId = getInstance().getId(); log.debug("jobSeeker persisted and isManaged? " + isManaged()); log.debug("jobSeeker with userId: " + userId + " is saved"); return lastStateChanged; } }
The first weird thing is that when I wire the object, an insert occurs. But besides that everything works like expected. Next I want to add a course to the JobSeeker object.
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:s="http://jboss.com/products/seam/taglib" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:rich="http://richfaces.org/rich" template="/layout/jobseeker/template.xhtml"> <ui:define name="body"> <h:messages globalOnly="true" styleClass="message" errorClass="errormsg" infoClass="infomsg" warnClass="warnmsg" id="globalMessages"/> <h:form id="courseForm"> <rich:panel id="addCoursePnl"> <f:facet name="header"> Add course </f:facet> <s:validateAll> <s:decorate id="titleField" template="/layout/edit.xhtml"> <ui:define id="label" name="label">Title:</ui:define> <h:inputText id="title" value="#{course.title}" required="true"/> </s:decorate> <s:decorate id="descriptionField" template="/layout/edit.xhtml"> <ui:define id="label" name="label">Description:</ui:define> <h:inputTextarea id="description" cols="80" rows="3" value="#{course.description}" required="true"/> </s:decorate> </s:validateAll> <div class="actionButtons"> <h:commandButton id="NextCourse" value="Save" action="#{jobSeekerHome.persist}" rendered="#{!jobSeekerHome.managed}" disabled="#{!jobSeekerHome.wired}"/> <h:commandButton id="updateCourse" value="Update" action="#{jobSeekerHome.update}" rendered="#{jobSeekerHome.managed}"/> <s:button id="discardResume" value="Discard changes" propagation="end" view="/jobseeker/jobseeker_index.xhtml" rendered="#{jobSeekerHome.managed}"/> <s:button id="cancelResume" value="Cancel" propagation="end" view="/#{empty courseFrom ? 'courseList' :courseFrom}.xhtml" rendered="#{!jobSeekerHome.managed}"/> </div> </rich:panel> <rich:panel id="listCoursesPnl"> <rich:extendedDataTable id="cTable" value="#{courseHome.courses}" var="_course"> <rich:column> <f:facet name="header"> <h:outputText value="id"/> </f:facet> <h:outputText value="#{_course.id}" /> </rich:column> <rich:column> <f:facet name="header"> <h:outputText value="title"/> </f:facet> <h:outputText value="#{_course.title}" /> </rich:column> <rich:column> <f:facet name="header"> <h:outputText value="description"/> </f:facet> <h:outputText value="#{_course.description}" /> </rich:column> </rich:extendedDataTable> </rich:panel> </h:form> </ui:define> </ui:composition>
When I want to add a course to the JobSeeker object I see in the logging that at one point the userId is null. When entering course.xhtml a page action is fired (courseHome.wire() ). The userId is in session scope, how can it be null at some time, I think it has something to do with the scoping but I can't figure it out...
package nu.anoniemsolliciteren.action; import java.util.List; import javax.ejb.Remove; import nu.anoniemsolliciteren.entities.user.Course; import nu.anoniemsolliciteren.entities.user.JobSeeker; import nu.anoniemsolliciteren.entities.user.home.JobSeekerHome; import org.jboss.seam.ScopeType; import org.jboss.seam.annotations.Destroy; import org.jboss.seam.annotations.Factory; import org.jboss.seam.annotations.In; import org.jboss.seam.annotations.Logger; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.datamodel.DataModel; import org.jboss.seam.faces.FacesMessages; import org.jboss.seam.framework.EntityHome; import org.jboss.seam.log.Log; @Name("courseHome") public class CourseHome extends EntityHome<Course> { /** * */ private static final long serialVersionUID = 1928470766987512649L; private List<Course> courses; private String lastStateChange; @In(create = true) private JobSeekerHome jobSeekerHome; @Logger private static Log log; @In(required = false) private Long userId; @Override protected Course createInstance() { Course course = super.createInstance(); //retrieveCourses(); this one is called in the pages.xml return course; } // @Begin(join = true, flushMode = FlushModeType.MANUAL) @Override @Factory(value = "course", scope = ScopeType.EVENT) public Course getInstance(){ Course course = super.getInstance(); log.debug("getInstance of Course"); log.debug("getId() " + course.getId()); return course; } @DataModel(scope = ScopeType.PAGE) public List<Course> getCourses() { return courses; } public void setCourses(List<Course> courses) { this.courses = courses; } public void retrieveCourses() { log.debug("retrieveCourses is called "); JobSeeker jobSeeker = jobSeekerHome.getInstance(); courses = jobSeeker.getCourse(); } public Course getDefinedInstance() { return isIdDefined() ? getInstance() : null; } public void wire() { log.debug("wire() is called"); log.debug("userId according injection (session) " + userId); JobSeeker jobSeeker = jobSeekerHome.getInstance(); log.debug("get jobSeekerID " + jobSeeker.getId()); if (jobSeeker.getCourse() != null) { log.debug("jobSeeker.getCourse() != null"); jobSeeker.getCourse().add(getInstance()); } } public boolean isWired() { JobSeeker jobSeeker = jobSeekerHome.getInstance(); if (jobSeeker != null && jobSeeker.getCourse() != null) { for(Course c : jobSeeker.getCourse()){ if(c.getId() == getInstance().getId()){ log.debug("course is wired"); return true; }else{ log.debug("course is not wired"); return false; } } } log.debug("course is not wired"); return false; } // @End @Override public String persist() { // wire(); lastStateChange = super.persist(); FacesMessages.instance().add("Course of #{course.title} saved succesfully"); return lastStateChange; } // @End @Override public String update() { // wire(); lastStateChange = super.persist(); FacesMessages.instance().add("Course of #{course.title} updated succesfully"); return lastStateChange; } // @End @Destroy @Remove public void destroy(){ log.debug("courseHome destroyed"); } }