Flush-mode=manual: strange behaviour, entity is commited when changed
dpaterson.dpaterson.convexsolutions.com May 8, 2009 6:31 PMI am seeing strange problem with entities being committed to the database automatically even though I have the flush mode set to manual in the page.xml fragment:
<begin-conversation join="true" flush-mode="manual"/>
In my facelet I have the following:
<s:decorate id="email" template="/layout/edit.xhtml"> <ui:define name="label">Email:</ui:define> <h:inputText tabindex="7" validator="#{globalUserHome.validateEmail}" required="true" requiredMessage="Email required" value="#{globalUserHome.instance.email}"> <a4j:support reRender="email" ajaxSingle="true" event="onblur"/> </h:inputText> </s:decorate>
And validateEmail looks like this:
public void validateEmail(FacesContext context, UIComponent toValidate, Object value) { log.info("validateEmail begin"); String email (String) value; if (((isManaged() && !originalEmail.equals(email)) || !isManaged())) { if (emailExists(email)) { FacesMessage message = new FacesMessage("Email address: " + email + " already exists."); context.addMessage(toValidate.getClientId(context), message); } } if(!IDSUtil.emailValid(email)){ FacesMessage message = new FacesMessage("Email address: " + email + " is not valid."); context.addMessage(toValidate.getClientId(context), message); } log.info("validateEmail end"); }
The entity fragement for this field is:
@Entity @EntityListeners(JPAValidateListener.class) @Table(name = "GLOBAL_USERS", uniqueConstraints = { @UniqueConstraint(columnNames = "EMAIL"), @UniqueConstraint(columnNames = "LOGIN_NAME") }) public class GlobalUser extends AbstractEntity implements java.io.Serializable { ... @Email(message="Email is in an invalid format") @NotNull @Column(name = "EMAIL", unique = true, nullable = false) public String getEmail() { return this.email; } public void setEmail(String email) { this.email = email; } ... }
What is happening is sometimes after validateEmail is executed I am seeing an update query fire in the server log:
12:10:28,359 INFO [GlobalUserHome] Could not find result for email: qqqqaaa@gmail.com 12:10:28,359 INFO [GlobalUserHome] emailExists end 12:10:28,359 INFO [GlobalUserHome] validateEmail end 12:10:28,421 INFO [STDOUT] Hibernate: update DPATERSON_MASTER1.GLOBAL_USERS set EMAIL=?, LAST_MODIFIED=?, LOGIN_NAME=?, POD_ID=? where GLOBAL_USERS_ID=?
This does not happen all the time, about 50% of the time validateEmail fires and the entity is left in a dirty state as it should be because of flushMode=MANUAL.
Has anyone else seen this kind of behavior or have any tips as to how I can debug it? Seam is a bit of a black box here and it's difficult to see exactly what's going on. I don't want any changes to the database until the user executes an action to commit the entity. Especially in this case, the validation may fail, finding a duplicate email address, but the entity is still commited causing a constraint violation error on commit, very bad. I am using Seam 2.0.3.CR1.