[jboss-user] [JBoss Seam] - FlushModeType.MANUAL in conversation

kai222 do-not-reply at jboss.com
Sun Dec 16 17:30:07 EST 2007


Hi,

I cannot control the synchronization from a persistent object to the database. The more I read and the more I try out the more I get confused. I hope that somebody can give me a helping hint.

For testing I generated a simple ear project with seam-gen (Seam 2.0.0.GA) and added an entity class and a stateful session bean.

The use case: 
A logged in user wants to change his email address (unique field in table). 
A server-side validation with a database selection is effected and fails if the new email address exists in the database.

What happens:
If I enter a new email and press Save, a synchronization (flush) takes place just before the selection of the existing email addresses has been started. In FlushMode.AUTO this is normal, but not in FlushMode.MANUAL. The effect is that EVERY new email is known to the system and the validation does not work as it should.


The entity class MyUser is:

  | package some.model;
  | 
  | // imports...
  | 
  | @Entity
  | @Table
  | @Name("user")
  | public class MyUser implements Serializable {
  | 	
  | 	@Id @GeneratedValue
  | 	private Long id = null;
  | 	
  | 	// username is the business key
  | 	@Column(name="username", nullable = false, unique = true)
  | 	private String username;
  | 
  | 	@Email
  | 	@Column(name="email", nullable = false, unique = true)
  | 	private String email;
  | 	
  | 	private String firstname;
  | 	private String lastname;
  | 	
  | 	public MyUser() {
  | 	}
  | 	
  | 	//... getter and setter ...
  | 
  | }
  | 
The stateful session bean implementation is:

  | package some.controller;
  | 
  | // imports ...
  | 
  | @Name( "userAction" )
  | @Scope( ScopeType.CONVERSATION )
  | @Stateful
  | public class UserActionBean implements Serializable, UserAction {
  | 	private static final long serialVersionUID = 1L;
  | 
  | 	@PersistenceContext(type=PersistenceContextType.EXTENDED)
  | 	private EntityManager entityManager;
  | 
  |     	@In(create=true)
  |     	private transient FacesMessages facesMessages;
  | 
  | 	@In( value = "user", required = false )
  | 	@Out( value = "user", required = false )
  | 	private MyUser selectedUser;
  | 	
  | 	@In 
  | 	private Identity identity;
  | 
  |     	private String backupEmail;
  | 
  |     	@Begin(flushMode=FlushModeType.MANUAL, join=true)
  | 	public String selectLoggedInUser() {
  | 		System.out.println( "Selected logged in User: " + identity.getUsername() );
  | 		List<MyUser> existing = (List<MyUser>) entityManager
  | 			.createQuery("from MyUser u where u.username = :uname)")
  | 			.setParameter("uname", identity.getUsername())
  | 			.getResultList();
  | 		if (existing.size() == 1) {
  | 			selectedUser = (MyUser) existing.get(0);
  | 			backupEmail = selectedUser.getEmail();
  | 			System.out.println( "Redirecting to /editLoggedInUser.xhtml" );
  | 			return "/editLoggedInUser.xhtml";
  | 		} else {
  | 			return "/home.xhtml";
  | 		}
  | 	}
  | 
  | 	@End
  | 	public String saveLoggedInUser() {
  | 		
  | 		// Try if email exists
  | 		// There should NOT be a flush before the query is effected
  | 		// But there IS a flush before the query is effected
  | 		if (emailExists()) {
  | 			selectedUser.setEmail(backupEmail);
  | 			return null;
  | 		}
  | 		
  | 		// Normal flush (success case)
  | 		entityManager.flush();
  | 		
  | 		FacesMessages.instance().add( "#{user.username} has been saved." );
  | 		return "/home.xhtml";
  | 	}
  | 
  | 	private boolean emailExists() {
  | 		List<String> existing = (List<String>)
  | 			entityManager.createQuery("from MyUser u where u.email = :email)")
  | 				.setParameter("email", selectedUser.getEmail())
  | 				.getResultList();
  | 		if(existing.size() != 0) {
  | 			facesMessages.add("#{messages['NewEmailExists']}" + selectedUser.getEmail());
  | 			return true;
  | 		}
  | 		return false;
  | 	}
  | 		
  | 	@Remove @Destroy
  | 	public void destroy() {}	
  | }
  | 
Extension of "menu.xhtml" to start the conversation:

  | ...
  |      <rich:toolBarGroup rendered="#{identity.loggedIn}">
  |      	 <s:link action="#{userAction.selectLoggedInUser}" value="#{messages['MyUser']}"/>
  |      </rich:toolBarGroup>
  | ...
  | 
The form "editLoggedInUser.xhtml" is:

  | <!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:j4j="http://javascript4jsf.dev.java.net/"
  |                 xmlns:rich="http://richfaces.ajax4jsf.org/rich"
  |                 template="layout/template.xhtml">
  | 
  | <ui:define name="body">
  |     
  |     <h:messages styleClass="message" globalOnly="true"/>
  |     
  |     <h:form id="editLoggedInUser">
  |     
  |         <rich:panel>
  |             <f:facet name="header">#{messages['MyUser']}</f:facet>
  |     
  |             <div class="dialog">
  |         	  <s:validateAll>
  |                 <h:panelGrid columns="2" rowClasses="prop" columnClasses="name,value">
  |                 
  |                     <h:outputLabel>#{messages['Username']}</h:outputLabel>
  |                     <h:outputText value="#{user.username}"/>
  |                     
  |                     <h:outputLabel for="firstname">#{messages['FirstName']}</h:outputLabel>
  |                     <s:decorate>
  |                         <h:inputText id="firstname" required="true"
  |                             value="#{user.firstname}"/>
  |                     </s:decorate>
  |                     
  |                     <h:outputLabel for="lastname">#{messages['LastName']}</h:outputLabel>
  |                     <s:decorate>
  |                         <h:inputText id="lastname" required="true"
  |                             value="#{user.lastname}"/>
  |                     </s:decorate>
  |                     
  |                     <h:outputLabel for="email">#{messages['Email']}</h:outputLabel>
  |                     <s:decorate>
  |                         <h:inputText id="email" required="true"
  |                             value="#{user.email}"/>
  |                     </s:decorate>
  |                     
  |                 </h:panelGrid>
  |         	  </s:validateAll>
  |             </div>
  |                 
  |         </rich:panel>
  |             
  |         <div class="actionButtons">
  |             <h:commandButton id="saveLoggedInUser" value="#{messages['Save']}"
  |                 action="#{userAction.saveLoggedInUser}"/>     			  
  |         </div>
  |           
  |     </h:form>
  | 
  |  </ui:define> 
  | </ui:composition>
  | 
The persistence.xml shows that Hibernate is the persistence provider, so MANUAL FlushMode should work:

  | ...
  |    <persistence-unit name="aValidationTest">
  |       <provider>org.hibernate.ejb.HibernatePersistence</provider>
  |       <jta-data-source>java:/aValidationTestDatasource</jta-data-source>
  |       <properties>
  |          <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
  |          <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
  |          <property name="hibernate.show_sql" value="true"/>
  |          <property name="hibernate.format_sql" value="true"/>
  |          <property name="jboss.entity.manager.factory.jndi.name" value="java:/aValidationTestEntityManagerFactory"/>
  |       </properties>
  |    </persistence-unit>
  | ...
  | 
components.xml:

  | ...
  |    <persistence:managed-persistence-context name="entityManager"
  |                                      auto-create="true"
  |                       persistence-unit-jndi-name="java:/aValidationTestEntityManagerFactory"/>
  | ...
  | 
import-dev.sql:

  | insert into MyUser (ID, USERNAME, FIRSTNAME, LASTNAME, EMAIL) values (1, 'admin', 'Frederic', 'Chopin', 'one at email.com');
  | insert into MyUser (ID, USERNAME, FIRSTNAME, LASTNAME, EMAIL) values (2, 'user', 'Baby', 'Love', 'two at email.com');
  | 
What's wrong in my thinking? 

Thank you very much for all answers.

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

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



More information about the jboss-user mailing list