[jboss-user] [JBoss Seam] - Re: Problems with list page, persistence, and detached entit

Oberiko do-not-reply at jboss.com
Fri Jan 18 12:14:42 EST 2008


Here's how I want it to work:

  | * Save users to a database on the entry page
  | * On navigation to the list page, pull users from the database into a list in the scope and display them
  | * Do not call the database to update the list since it's in the scope
  | * When leaving the page, remove all traces from the scope
  | 
  | 
  | Now, I got that working with the following:
  | 
  | 
  |   | package org.domain.myProject.session;
  |   | 
  |   | import static javax.persistence.PersistenceContextType.EXTENDED;
  |   | 
  |   | import java.util.List;
  |   | 
  |   | import javax.ejb.Remove;
  |   | import javax.ejb.Stateful;
  |   | import javax.persistence.EntityManager;
  |   | import javax.persistence.PersistenceContext;
  |   | 
  |   | import org.domain.myProject.entity.User;
  |   | import org.domain.myProject.session.local.UserEditLocal;
  |   | 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.Scope;
  |   | import org.jboss.seam.annotations.datamodel.DataModel;
  |   | import org.jboss.seam.annotations.datamodel.DataModelSelection;
  |   | import org.jboss.seam.contexts.Contexts;
  |   | import org.jboss.seam.faces.FacesMessages;
  |   | import org.jboss.seam.log.Log;
  |   | 
  |   | @Stateful
  |   | @Name("userEdit")
  |   | @Scope(ScopeType.SESSION)
  |   | public class UserEditForm implements UserEditLocal {
  |   | 
  |   |     @Logger 
  |   |     private Log log;
  |   |     
  |   |     @In 
  |   |     FacesMessages facesMessages;
  |   |     
  |   |     @PersistenceContext(type = EXTENDED)
  |   |     private EntityManager em;
  |   |     
  |   |     @DataModelSelection
  |   |     @Out(required=false)
  |   |     private User user;
  |   | 	  
  |   |     @DataModel(scope=ScopeType.PAGE)
  |   |     private List<User> users;
  |   |     
  |   |     @SuppressWarnings("unchecked")
  |   | 		@Factory("users")
  |   |     public void findUsers(){
  |   |     	log.info("*********************************************  Finding the users");
  |   |     	if (users == null)
  |   |     		log.info("users is null");
  |   |     	else if (users.size() == 0)
  |   |     		log.info("users has a size of zero");
  |   |     	else
  |   |     		log.info("Strange, because users has " +users.size() + " entries");
  |   |     	
  |   |     	users = em.createQuery("from User u").getResultList();
  |   |     
  |   |     }
  |   |     
  |   |     public void remove(){
  |   |     	log.info("Deleting " +user.getName());
  |   |     	em.remove(user);
  |   |     	users.remove(user);
  |   |     }
  |   |     
  |   |     public void clear(){
  |   |     	log.info("Clearing the userEdit bean from the session");
  |   |     	Contexts.getSessionContext().remove("userEdit");
  |   |     }
  |   | 		
  |   |     public void update() {
  |   |     	//TODO write the update method
  |   |     }
  |   |     
  |   |     @Destroy @Remove                                                                      
  |   |     public void destroy() {}
  |   | }
  |   | 
  | 
  | 
  |   | package org.domain.myProject.session;
  |   | 
  |   | import javax.ejb.Stateless;
  |   | import javax.persistence.EntityManager;
  |   | import javax.persistence.PersistenceContext;
  |   | 
  |   | import org.domain.myProject.entity.User;
  |   | import org.domain.myProject.session.local.SaveUserLocal;
  |   | 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.contexts.Context;
  |   | import org.jboss.seam.contexts.Contexts;
  |   | 
  |   | import org.jboss.seam.faces.FacesMessages;
  |   | import org.jboss.seam.log.Log;
  |   | 
  |   | @Stateless
  |   | @Name("saveUser")
  |   | public class SaveUserAction implements SaveUserLocal {
  |   | 
  |   | 	@Logger
  |   | 	private Log log;
  |   | 	
  |   | 	@In
  |   | 	FacesMessages facesMessages;
  |   | 
  |   | 	@PersistenceContext
  |   | 	private EntityManager em;
  |   | 	
  |   | 	/* We have an '@Out' on this to push back user (after any modifications we make
  |   | 	 * in our bean here) onto the page.  Since we're nullifying user in our save method, 
  |   | 	 * we need to state that it's not required to have any value.
  |   | 	 */  
  |   | 	@In @Out(required=false)
  |   | 	private User user;
  |   | 
  |   | 	public void saveUser() {
  |   | 		//Simple persisting with the EntityManager
  |   | 		em.persist(user);
  |   | 		
  |   | 		//Note that the id of our user was generated and populated.  
  |   | 		facesMessages.add("User was saved with an id of "+ user.getId());
  |   | 		
  |   | 		log.info(user.getName() +" was saved.");
  |   | 		
  |   | 		//We're nullifying user so that the page is blank after saving.
  |   | 		user = null;
  |   | 		
  |   | 		//All items in the session context, only here for testing the list page
  |   | 		for (String s:Contexts.getSessionContext().getNames()){
  |   | 			if (s.startsWith("org.jboss") || s.startsWith("javax") || s.startsWith("org.ajax4jsf"))
  |   | 				continue;
  |   | 			log.info(s + " is in the session");
  |   | 		}
  |   | 	}
  |   | }
  |   | 
  |   | 
  | 
  | And my .xhtml files
  | 
  |   | <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  |   |                       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  |   | <html xmlns="http://www.w3.org/1999/xhtml"
  |   | 	xmlns:s="http://jboss.com/products/seam/taglib"
  |   | 	xmlns:f="http://java.sun.com/jsf/core"
  |   | 	xmlns:h="http://java.sun.com/jsf/html">
  |   | 
  |   | <f:view>
  |   | 	<h:form>
  |   | 		<s:validateAll>
  |   | 			Name: 
  |   | 			<h:inputText value="#{user.name}" required="true" 
  |   | 				requiredMessage="You need to enter a name"/>
  |   | 			<br />
  |   | 			<h:commandButton value="Save" action="#{saveUser.saveUser()}" />
  |   | 			<s:button value ="List" view="/listUsers.xhtml"/>
  |   | 		</s:validateAll>
  |   | 	</h:form>
  |   | <h:messages />	
  |   | </f:view>
  |   | 
  |   | </html>
  |   | 
  | 
  | 
  |   | <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  |   |                       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  |   | <html xmlns="http://www.w3.org/1999/xhtml"
  |   | 	xmlns:s="http://jboss.com/products/seam/taglib"
  |   | 	xmlns:f="http://java.sun.com/jsf/core"
  |   | 	xmlns:h="http://java.sun.com/jsf/html">
  |   | 
  |   | <f:view>
  |   | 	<h:messages />
  |   | 	<h:form>
  |   | 	<h:dataTable value="#{users}" var="user">
  |   | 		<h:column>
  |   | 			<f:facet name="header">
  |   | 				<h:outputText value="Id" />
  |   | 			</f:facet>
  |   | 			<h:outputText value="#{user.id}" />
  |   | 		</h:column>
  |   | 		<h:column>
  |   | 			<f:facet name="header">
  |   | 				<h:outputText value="Name" />
  |   | 			</f:facet>
  |   | 			<h:outputText value="#{user.name}" />
  |   | 		</h:column>
  |   | 		<h:column>
  |   | 			<f:facet name="header">
  |   | 				<h:outputText value="Actions" />
  |   | 			</f:facet>
  |   | 			<s:button action="#{userEdit.remove()}" value="S. Delete"/>
  |   | 			<h:commandButton action="#{userEdit.remove()}" value="H. Delete" />
  |   | 		</h:column>
  |   | 	</h:dataTable>
  |   | 	</h:form>
  |   | 	<s:button action="#{userEdit.clear()}" view="/user.xhtml" value="S. Return"/>
  |   | </f:view>
  |   | 
  |   | </html>
  |   | 
  | 
  | And here's my log (trimmed for brevity)
  | 
  |   | 11:41:01,347 INFO  [SaveUserAction] Luke was saved.
  |   | 11:41:06,809 INFO  [SaveUserAction] Skywalker was saved.
  |   | 11:41:11,567 INFO  [SaveUserAction] Darth was saved.
  |   | 11:41:15,417 INFO  [SaveUserAction] Vader was saved.
  |   | 11:41:18,813 INFO  [SaveUserAction] Yoda was saved.
  |   | 11:41:25,605 INFO  [SaveUserAction] I forgot about Yoda! was saved.
  |   | 11:41:40,770 INFO  [UserEditForm] *********************************************  Finding the users
  |   | 11:41:40,770 INFO  [UserEditForm] users is null
  |   | 11:41:45,043 INFO  [UserEditForm] Deleting I forgot about Yoda!
  |   | 11:41:48,548 INFO  [UserEditForm] Deleting Darth
  |   | 11:41:54,762 INFO  [UserEditForm] Clearing the userEdit bean from the session
  |   | 11:42:04,684 INFO  [SaveUserAction] Solo was saved.
  |   | 11:45:11,096 INFO  [UserEditForm] *********************************************  Finding the users
  |   | 11:45:11,096 INFO  [UserEditForm] users is null
  |   | 11:45:18,702 INFO  [UserEditForm] Deleting Vader
  |   | 
  | 
  | Now, with that working (though not as cleanly as I'd like), I started trying to figure out what I could ditch to make it simpler.
  | 
  | I started by getting rid of the page scope on my DataModel and adding a check to see the users being removed from the session:
  | 
  | 
  |   | ...
  |   | //    @DataModel(scope=ScopeType.PAGE)
  |   |     @DataModel
  |   |     private List<User> users;
  |   | ...
  |   | public void clear(){
  |   |     	log.info("Clearing the userEdit bean from the session");
  |   |     	Contexts.getSessionContext().remove("userEdit");
  |   |     	
  |   |     	if (Contexts.getSessionContext().isSet("users")){
  |   |     		log.info("Clearing the users from the session");
  |   |       	Contexts.getSessionContext().remove("users");
  |   |       	
  |   |       	if (Contexts.getSessionContext().isSet("users"))
  |   |       		log.info("You're still here?");
  |   |     	}
  |   | ...
  |   | 
  | 
  | But for some reason, now the "users" keeps getting plugged back into the session, even though I removed (and verified removing) it.
  | 
  | 
  |   | 11:51:23,638 INFO  [SaveUserAction] Jean Luc was saved.
  |   | 11:51:27,457 INFO  [SaveUserAction] Picard was saved.
  |   | 11:51:30,696 INFO  [SaveUserAction] Data was saved.
  |   | 11:51:34,155 INFO  [SaveUserAction] Worf was saved.
  |   | 11:51:37,943 INFO  [UserEditForm] *********************************************  Finding the users
  |   | 11:51:37,943 INFO  [UserEditForm] users is null
  |   | 11:51:51,058 INFO  [UserEditForm] Deleting Picard
  |   | 11:52:00,119 INFO  [UserEditForm] Deleting Data
  |   | 11:52:04,908 INFO  [UserEditForm] Clearing the userEdit bean from the session
  |   | 11:52:04,908 INFO  [UserEditForm] Clearing the users from the session
  |   | 11:52:28,634 INFO  [SaveUserAction] Locutus was saved.
  |   | 11:52:28,634 INFO  [SaveUserAction] users is in the session
  |   | 11:52:56,758 INFO  [SaveUserAction] Q was saved.
  |   | 11:52:56,758 INFO  [SaveUserAction] users is in the session
  |   | 
  | 
  | So it looks like I need the page scope.
  | 
  | So, is my top way, of putting the whole bean in the session-scope and the data model in the page-scope the cleanest way of doing this?  
  | 
  | I'm trying to avoid the session-scope as much as possible since, coming from a Struts background, I know the hassle (in both maintenaince and leaks) it can cause, especially when several other people start working on something with you.  
  | 
  | Would it be of any use to start looking at creating a Seam Managed Persistence Context?  I'm using EAR deployment (so I can use EJB's) and I know that I can't use the default of:
  | @In private EntityManager entityManager
  | Due to http://jira.jboss.org/jira/browse/JBIDE-1409?decorator=printable
  | 
  | 
  | Also, why does "users" keep popping back into the session when not assigned to the page-scope, even after removing it?
  | 
  | I know this is all quite the mouthful, but anyone have any suggestions?

View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4121369#4121369

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4121369



More information about the jboss-user mailing list