Resolved the issue - now it works fine: I extracted validation to the separate method with @OnEvent(value=EventContants.VALIDATE, component="submitForm") Also switched to 5.2.1.
@OnEvent(value = EventConstants.VALIDATE, component = "registerForm") void validate(){ detectErrors(); } @OnEvent(value = EventConstants.SUCCESS, component = "registerForm") Object saveCustomerAndUser() { user.setPassword(generateHash(user.getPassword())); customer.addUser(user); customerService.save(customer); // redirect with a message parameter return Index.class; } private void detectErrors() { if (!verifyPassword.equals(user.getPassword())) { registerForm.recordError(messages.get("error.verify.password")); } if (userService.getUserByLogin(user.getLogin()) != null) { registerForm.recordError(messages.get("error.user.already.exists")); } if (customerService.getCustomerByBusinessName(customer.getBusinessName()) != null) { registerForm.recordError(messages.get("error.customer.already.exists")); } } Anton 2010/10/25 Anton Mezerny <anton.meze...@gmail.com> > I am using 5.1.0.7. Also I figured how to reproduce such a behavior - if i > fill all fields with proper values, but set not equal passwords - all data > is lost, but if I set invalid email and proper passwords - everything works > fine. > > P.S. There is one error in previous code - in recordErrors() method shoud > be: > > registerForm.recordError(messages.get("error.verify.password")); > instead of > registerForm.recordError(verifyPassword, > messages.get("error.verify.password")); > > 2010/10/25 Mark Shead <mark.sh...@xeric.net> > > Once it is submitted you may want to set the user back to null, that way >> you >> can start fresh when the page is submitted. >> >> The required,email and email,required things sounds odd. I'm going to see >> if >> I can reproduce that. What version of tapestry are you using? >> >> Mark >> >> On Mon, Oct 25, 2010 at 2:17 PM, Anton Mezerny <anton.meze...@gmail.com >> >wrote: >> >> > Ok, when i changed order from validation="required,email" to >> > validation="email,required" email validation starts to work properly. >> Looks >> > like some magic :). However, I get sometimes user data lost. I can't >> > reproduce this bug with 100% probability, but it occurs sometimes. I >> tried >> > also to change @Persist(PersistenceConstants.FLASH) to default @Persist. >> > But >> > it gives me behavior I don't want - it renders user data even if I >> refresh >> > the page (I want to show blank form in that case). So FLASH persistance >> is >> > what I want, but sometimes data are lost. >> > >> > My code now looks like this: >> > >> > >> -------------------Registration.java----------------------------------------- >> > public class Registration { >> > >> > @Property >> > @Persist(PersistenceConstants.FLASH) >> > private User user; >> > >> > @Property >> > @Persist(PersistenceConstants.FLASH) >> > private Customer customer; >> > >> > @Property >> > private String verifyPassword; >> > >> > @Inject >> > private CustomerService customerService; >> > >> > @Inject >> > private UserService userService; >> > >> > @Component >> > private Form registerForm; >> > >> > @Inject >> > private Messages messages; >> > >> > @OnEvent(value = EventConstants.SUCCESS, component = "registerForm") >> > Object validateAndSave() { >> > >> > if (errorsDetected()){ >> > return null; >> > } >> > user.setPassword(generateHash(user.getPassword())); >> > customer.addUser(user); >> > customerService.save(customer); >> > >> > // redirect with a message parameter >> > return Index.class; >> > >> > } >> > >> > private boolean errorsDetected(){ >> > boolean errorDetected = false; >> > if (!verifyPassword.equals(user.getPassword())) { >> > registerForm.recordError(verifyPassword, >> > messages.get("error.verify.password")); >> > errorDetected = true; >> > } >> > >> > if (userService.getUserByLogin(user.getLogin()) != null) { >> > >> > registerForm.recordError(messages.get("error.user.already.exists")); >> > errorDetected = true; >> > } >> > >> > if >> > (customerService.getCustomerByBusinessName(customer.getBusinessName()) >> != >> > null) { >> > >> > registerForm.recordError(messages.get("error.customer.already.exists")); >> > errorDetected = true; >> > } >> > return errorDetected; >> > } >> > } >> > >> > >> > >> -------------Registration.tml---------------------------------------------------------------- >> > <html t:type="layout" title="Customer registration" >> > t:sidebarTitle="Current Time" >> > t:pageTitle="Register" >> > xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd" >> > xmlns:p="tapestry:parameter"> >> > >> > <fieldset id="register"> >> > <form class="full-form" t:id="registerForm"> >> > <t:errors/> >> > >> > <fieldset> >> > <legend>Customer registration (company or private >> > person)</legend> >> > >> > <t:beaneditor object="customer" exclude="literal:id,users"> >> > <p:businessName> >> > <t:label for="businessName"/> >> > <t:textfield t:id="businessName" >> > value="customer.businessName" validate="required"/> >> > </p:businessName> >> > <p:contactPhone> >> > <t:label for="customer_contactPhone"/> >> > <t:textfield t:id="customer_contactPhone" >> > value="customer.contactPhone" validate="required"/> >> > </p:contactPhone> >> > <p:contactPerson> >> > <t:label for="contactPerson"/> >> > <t:textfield t:id="contactPerson" >> > value="customer.contactPerson" validate="required"/> >> > </p:contactPerson> >> > <p:businessAddress> >> > <t:label for="businessAddress"/> >> > <t:textfield t:id="businessAddress" >> > value="customer.businessAddress" validate="required"/> >> > </p:businessAddress> >> > <p:email> >> > <t:label for="customer_email"/> >> > <t:textfield t:id="customer_email" >> > value="customer.email" validate="email,required"/> >> > </p:email> >> > </t:beaneditor> >> > </fieldset> >> > >> > <fieldset> >> > <legend>Personal registration</legend> >> > <t:beaneditor object="user" exclude="literal:id,roles" >> > add="verifyPassword"> >> > >> > >> > <p:firstName> >> > <t:label for="firstName"/> >> > <t:textfield t:id="firstName" value="user.firstName" >> > validate="required"/> >> > </p:firstName> >> > >> > >> > <p:middleName> >> > <t:label for="middleName"/> >> > <t:textfield t:id="middleName" >> value="user.middleName" >> > validate="required"/> >> > </p:middleName> >> > >> > >> > <p:lastName> >> > <t:label for="lastName"/> >> > <t:textfield t:id="lastName" value="user.lastName" >> > validate="required"/> >> > </p:lastName> >> > >> > >> > <p:contactPhone> >> > <t:label for="contactPhone"/> >> > <t:textfield t:id="contactPhone" >> > value="user.contactPhone" validate="required"/> >> > </p:contactPhone> >> > >> > >> > <p:mobilePhone> >> > <t:label for="mobilePhone"/> >> > <t:textfield t:id="mobilePhone" >> value="user.mobilePhone" >> > validate="required"/> >> > </p:mobilePhone> >> > >> > >> > <p:address> >> > <t:label for="address"/> >> > <t:textfield t:id="address" value="user.address" >> > validate="required"/> >> > </p:address> >> > >> > >> > <p:email> >> > <t:label for="email"/> >> > <t:textfield t:id="email" value="user.email" >> > validate="required"/> >> > </p:email> >> > >> > >> > <p:nickname> >> > <t:label for="nickname"/> >> > <t:textfield t:id="nickname" value="user.nickname" >> > validate="required"/> >> > </p:nickname> >> > >> > >> > <p:login> >> > <t:label for="login"/> >> > <t:textfield t:id="login" value="user.login" >> > validate="required"/> >> > </p:login> >> > >> > >> > <p:password> >> > <t:label for="password"/> >> > <t:passwordfield t:id="password" >> value="user.password" >> > validate="required"/> >> > </p:password> >> > >> > <p:verifyPassword> >> > <t:label for="verifyPassword"/> >> > <t:passwordfield t:id="verifyPassword" >> > value="verifyPassword" validate="required"/> >> > </p:verifyPassword> >> > >> > </t:beaneditor> >> > >> > </fieldset> >> > >> > >> > <div class="form-submit"> >> > <input type="submit" value="Register"/> >> > </div> >> > <div class="member">Already a member? >> > <t:pagelink page="Login">Login now!</t:pagelink> >> > </div> >> > </form> >> > </fieldset> >> > </html> >> > >> > 2010/10/25 Mark <mark-li...@xeric.net> >> > >> > > So if there is another problem the email validation will show you an >> > error, >> > > but not if the email validation is the only issue? That seems very >> odd. >> > > You might try switching the order from validation="required,email" to >> > > validation="email,required" just to see what happens. >> > > >> > > Mark >> > > >> > > On Mon, Oct 25, 2010 at 10:24 AM, Anton Mezerny < >> anton.meze...@gmail.com >> > > >wrote: >> > > >> > > > Required validation works on client side, so I have not tested it on >> > > > server. >> > > > I can say, that when my custom validation causes error (password and >> > > > password verification don't match), then I have 2 error messages on >> > > > registration page (if email is also not valid) - email error and >> > password >> > > > verification error. >> > > > >> > > > Anton >> > > > >> > > > 2010/10/25 Mark <mark-li...@xeric.net> >> > > > >> > > > > Do all the other validations perform as expected other than email? >> > Does >> > > > the >> > > > > "required" validation on email work correctly and give you an >> error >> > > when >> > > > > you >> > > > > try to submit. Also do you have any types of constraints on the >> email >> > > > field >> > > > > in the database? Is it possible that what you are entering in the >> > email >> > > > > fields is passing the email validation, but getting rejected by >> the >> > > > > database? >> > > > > >> > > > > I don't remember what Tapestry uses to determine whether or not >> > > something >> > > > > is >> > > > > a valid email address, but I do know that the actual spec for >> email >> > > > > addresses is a lot more permissive than you'd think. >> > > > > >> > > > > Mark >> > > > > >> > > > > On Mon, Oct 25, 2010 at 6:35 AM, Anton Mezerny < >> > > anton.meze...@gmail.com >> > > > > >wrote: >> > > > > >> > > > > > So, I removed initializeNewUser() from Registration.java and >> added >> > > > > @Inject >> > > > > > annotation to User.java and Customer.java (I also made user and >> > > > customer >> > > > > > separate, not nested one into another and I nest user into >> customer >> > > > just >> > > > > > before saving to DB). Now page renders well, but when I try to >> save >> > > > user >> > > > > > and >> > > > > > customer (and email is invalid) - email validation does not >> occurs >> > - >> > > I >> > > > > just >> > > > > > have email = null in my customer.email field (even if i set some >> > > > > incorrect >> > > > > > value, for exapmle 'test_email'). There is no redirect to the >> > > > > registration >> > > > > > page with error message - program continues execution and tries >> to >> > > save >> > > > > > data >> > > > > > to DB. >> > > > > > >> > > > > > 2010/10/23 Mark W. Shead <mwsh...@gmail.com> >> > > > > > >> > > > > > > I don't think you want to use flash persistence for this. Try >> > just >> > > > > > > using @Persist. It looks like you are creating a new user >> every >> > > time >> > > > > > > the page renders. >> > > > > > > >> > > > > > > Mark >> > > > > > > >> > > > > > > On Sat, Oct 23, 2010 at 3:08 PM, Jim O'Callaghan < >> > > > > jc1000...@yahoo.co.uk> >> > > > > > > wrote: >> > > > > > > > I'm not sure if this is relevant to your current problem, >> but >> > to >> > > > tell >> > > > > > > > Tapestry which constructor to use for the bean editor, you >> > should >> > > > > > > annotate >> > > > > > > > the default (no args) constructor with @Inject - this will >> > allow >> > > > the >> > > > > > BEF >> > > > > > > to >> > > > > > > > create the relevant entity if none if present. Hope this >> > helps. >> > > > > > > > >> > > > > > > > Regards, >> > > > > > > > Jim. >> > > > > > > > >> > > > > > > > -----Original Message----- >> > > > > > > > From: Anton Mezerny [mailto:anton.meze...@gmail.com] >> > > > > > > > Sent: 23 October 2010 17:02 >> > > > > > > > To: Tapestry users >> > > > > > > > Subject: Objects session persistance and validation >> > > > > > > > >> > > > > > > > Hi all, >> > > > > > > > I'm trying to write simple registration form using >> beaneditor >> > > > > > component. >> > > > > > > > If I fullfill all reqired fields in the form and submit it - >> > > > > everything >> > > > > > > > works fine, but if server validation occurs (for example >> > > passwords >> > > > > > don't >> > > > > > > > match), then all data is lost and Registration page renders >> > with >> > > > > > > validation >> > > > > > > > errors, but without user data (input values). >> > > > > > > > I think the reason for this behaviour is the >> > initializeNewUser() >> > > > > > method, >> > > > > > > > wich rewrites all data if user field is null. But if I >> delete >> > > this >> > > > > > method >> > > > > > > > from code, tapestry throws exception - User can't be >> > instantiated >> > > > > > > (tapestry >> > > > > > > > tries to use constructor with most parameters, which has >> custom >> > > > > > objects, >> > > > > > > not >> > > > > > > > only String, Integer, etc). So how can resolve this problem? >> > > > > > > > Thanks in advance. >> > > > > > > > >> > > > > > > > My code (some code is token from Tapestry5 Hotel Booking >> > > example): >> > > > > > > > >> > > > > > > >> > > > > > >> > > > > >> > > > >> > > >> > >> -----------------Registration.java:----------------------------------------- >> > > > > > > > --- >> > > > > > > > >> > > > > > > > public class Registration { >> > > > > > > > >> > > > > > > > @Property >> > > > > > > > @Persist(PersistenceConstants.FLASH) >> > > > > > > > private User user; >> > > > > > > > >> > > > > > > > @OnEvent(value = EventConstants.PREPARE, component = >> > > > > "registerForm") >> > > > > > > > private void initializeNewUser() { >> > > > > > > > if (this.user == null) { >> > > > > > > > this.user = new User(); >> > > > > > > > this.user.setCustomer(new Customer()); >> > > > > > > > } else { >> > > > > > > > if (this.user.getCustomer() == null) { >> > > > > > > > this.user.setCustomer(new Customer()); >> > > > > > > > } >> > > > > > > > } >> > > > > > > > } >> > > > > > > > >> > > > > > > > >> > > > > > > > @Property >> > > > > > > > private String verifyPassword; >> > > > > > > > >> > > > > > > > @Inject >> > > > > > > > private UserService userService; >> > > > > > > > >> > > > > > > > @Component >> > > > > > > > private Form registerForm; >> > > > > > > > >> > > > > > > > @Inject >> > > > > > > > private Messages messages; >> > > > > > > > >> > > > > > > > public Object onSubmitFromRegisterForm() { >> > > > > > > > >> > > > > > > > if (!verifyPassword.equals(user.getPassword())) { >> > > > > > > > >> > > > > > > >> registerForm.recordError(messages.get("error.verify.password")); >> > > > > > > > >> > > > > > > > return null; >> > > > > > > > } >> > > > > > > > >> > > > > > > > if (userService.getUserByLogin(user.getLogin()) != >> null) >> > { >> > > > > > > > >> > > > > > > > >> > > > registerForm.recordError(messages.get("error.user.already.exists")); >> > > > > > > > >> > > > > > > > return null; >> > > > > > > > } >> > > > > > > > >> > > > > > > > userService.save(user); >> > > > > > > > >> > > > > > > > return Index.class; >> > > > > > > > >> > > > > > > > } >> > > > > > > > } >> > > > > > > > >> > > > > > > > >> > > > > > > > >> > > --------------Registration.tml------------------------------------ >> > > > > > > > >> > > > > > > > >> > > > > > > > <html t:type="layout" title="Customer registration" >> > > > > > > > t:sidebarTitle="Current Time" >> > > > > > > > t:pageTitle="Register" >> > > > > > > > xmlns:t=" >> > > http://tapestry.apache.org/schema/tapestry_5_1_0.xsd >> > > > " >> > > > > > > > xmlns:p="tapestry:parameter"> >> > > > > > > > >> > > > > > > > <fieldset id="register"> >> > > > > > > > <form class="full-form" t:id="registerForm"> >> > > > > > > > <t:errors/> >> > > > > > > > >> > > > > > > > <fieldset> >> > > > > > > > <legend>Customer registration(company or >> > > private >> > > > > > > > person)</legend> >> > > > > > > > >> > > > > > > > <t:beaneditor object="user.customer" >> > > > > > > > exclude="literal:id,users"> >> > > > > > > > <p:businessName> >> > > > > > > > <t:label for="businessName"/> >> > > > > > > > <t:textfield t:id="businessName" >> > > > > > > > value="user.customer.businessName" validate="required"/> >> > > > > > > > </p:businessName> >> > > > > > > > <p:contactPhone> >> > > > > > > > <t:label >> > for="customer_contactPhone"/> >> > > > > > > > <t:textfield >> > > > t:id="customer_contactPhone" >> > > > > > > > value="user.customer.contactPhone" validate="required"/> >> > > > > > > > </p:contactPhone> >> > > > > > > > <p:contactPerson> >> > > > > > > > <t:label for="contactPerson"/> >> > > > > > > > <t:textfield t:id="contactPerson" >> > > > > > > > value="user.customer.contactPerson" validate="required"/> >> > > > > > > > </p:contactPerson> >> > > > > > > > <p:businessAddress> >> > > > > > > > <t:label for="businessAddress"/> >> > > > > > > > <t:textfield >> t:id="businessAddress" >> > > > > > > > value="user.customer.businessAddress" validate="required"/> >> > > > > > > > </p:businessAddress> >> > > > > > > > <p:email> >> > > > > > > > <t:label for="customer_email"/> >> > > > > > > > <t:textfield >> t:id="customer_email" >> > > > > > > > value="user.customer.email" validate="required,email"/> >> > > > > > > > </p:email> >> > > > > > > > </t:beaneditor> >> > > > > > > > </fieldset> >> > > > > > > > >> > > > > > > > <fieldset> >> > > > > > > > <legend>Personal registration</legend> >> > > > > > > > <t:beaneditor object="user" >> exclude="literal:id,roles" >> > > > > > > > add="verifyPassword"> >> > > > > > > > >> > > > > > > > >> > > > > > > > <p:firstName> >> > > > > > > > <t:label for="firstName"/> >> > > > > > > > <t:textfield t:id="firstName" >> > > > > value="user.firstName" >> > > > > > > > validate="required"/> >> > > > > > > > </p:firstName> >> > > > > > > > >> > > > > > > > >> > > > > > > > <p:middleName> >> > > > > > > > <t:label for="middleName"/> >> > > > > > > > <t:textfield t:id="middleName" >> > > > > > value="user.middleName" >> > > > > > > > validate="required"/> >> > > > > > > > </p:middleName> >> > > > > > > > >> > > > > > > > >> > > > > > > > <p:lastName> >> > > > > > > > <t:label for="lastName"/> >> > > > > > > > <t:textfield t:id="lastName" >> > > > value="user.lastName" >> > > > > > > > validate="required"/> >> > > > > > > > </p:lastName> >> > > > > > > > >> > > > > > > > >> > > > > > > > <p:contactPhone> >> > > > > > > > <t:label for="contactPhone"/> >> > > > > > > > <t:textfield t:id="contactPhone" >> > > > > > > > value="user.contactPhone" validate="required"/> >> > > > > > > > </p:contactPhone> >> > > > > > > > >> > > > > > > > >> > > > > > > > <p:mobilePhone> >> > > > > > > > <t:label for="mobilePhone"/> >> > > > > > > > <t:textfield t:id="mobilePhone" >> > > > > > > value="user.mobilePhone" >> > > > > > > > validate="required"/> >> > > > > > > > </p:mobilePhone> >> > > > > > > > >> > > > > > > > >> > > > > > > > <p:address> >> > > > > > > > <t:label for="address"/> >> > > > > > > > <t:textfield t:id="address" >> > > value="user.address" >> > > > > > > > validate="required"/> >> > > > > > > > </p:address> >> > > > > > > > >> > > > > > > > >> > > > > > > > <p:email> >> > > > > > > > <t:label for="email"/> >> > > > > > > > <t:textfield t:id="email" >> value="user.email" >> > > > > > > > validate="required"/> >> > > > > > > > </p:email> >> > > > > > > > >> > > > > > > > >> > > > > > > > <p:nickname> >> > > > > > > > <t:label for="nickname"/> >> > > > > > > > <t:textfield t:id="nickname" >> > > > value="user.nickname" >> > > > > > > > validate="required"/> >> > > > > > > > </p:nickname> >> > > > > > > > >> > > > > > > > >> > > > > > > > <p:login> >> > > > > > > > <t:label for="login"/> >> > > > > > > > <t:textfield t:id="login" >> value="user.login" >> > > > > > > > validate="required"/> >> > > > > > > > </p:login> >> > > > > > > > >> > > > > > > > >> > > > > > > > <p:password> >> > > > > > > > <t:label for="password"/> >> > > > > > > > <t:passwordfield t:id="password" >> > > > > > value="user.password" >> > > > > > > > validate="required"/> >> > > > > > > > </p:password> >> > > > > > > > >> > > > > > > > <p:verifyPassword> >> > > > > > > > <t:label for="verifyPassword"/> >> > > > > > > > <t:passwordfield t:id="verifyPassword" >> > > > > > > > value="verifyPassword" validate="required"/> >> > > > > > > > </p:verifyPassword> >> > > > > > > > >> > > > > > > > </t:beaneditor> >> > > > > > > > >> > > > > > > > </fieldset> >> > > > > > > > >> > > > > > > > <div class="form-submit"> >> > > > > > > > <input type="submit" value="Register"/> >> > > > > > > > </div> >> > > > > > > > <div class="member">Already member? >> > > > > > > > <t:pagelink page="Login">Login now!</t:pagelink> >> > > > > > > > </div> >> > > > > > > > </form> >> > > > > > > > </fieldset> >> > > > > > > > </html> >> > > > > > > > >> > > > > > > > >> > > > > > > > >> > > > >> --------------------------------------------------------------------- >> > > > > > > > To unsubscribe, e-mail: >> users-unsubscr...@tapestry.apache.org >> > > > > > > > For additional commands, e-mail: >> > users-h...@tapestry.apache.org >> > > > > > > > >> > > > > > > > >> > > > > > > >> > > > > > > >> > > --------------------------------------------------------------------- >> > > > > > > To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org >> > > > > > > For additional commands, e-mail: >> users-h...@tapestry.apache.org >> > > > > > > >> > > > > > > >> > > > > > >> > > > > >> > > > >> > > >> > >> > >