-
1. Re: Multiple UIInputContainer lose values ?
ssachtleben.ssachtleben.gmail.com May 20, 2011 9:58 AM (in response to craig)I have also the same problem and just put all validation stuff into my bean then it works fine but if I use jsf components as UIInputContainer in combination with jsf validators the error message comes up but all input fields are empty. If I dont use that jsf validator and do the validation in my bean the error message comes up and the input fields are still filled.
Well I think its not a seam problem sounds more like an jsf problem.
-
-
3. Re: Multiple UIInputContainer lose values ?
spinner.joserodolfo.freitas.gawab.com May 20, 2011 1:29 PM (in response to craig)Yeap, it's seems to be a JSF bug.
we might create a temporaty component as a workaround, but it'd be nice if you vote for the JSF issues:http://java.net/jira/browse/JAVASERVERFACES-1991
-
4. Re: Multiple UIInputContainer lose values ?
craig May 22, 2011 4:09 PM (in response to craig)That would be great if you could, else it's pretty useless!
I'll vote for the issues
BTW I changed the template to be
<h:panelGroup> <cc:insertChildren /> </h:panelGroup>
but still cant get it to work?
Any ideas?
Cheers
Craig
-
5. Re: Multiple UIInputContainer lose values ?
ssachtleben.ssachtleben.gmail.com May 23, 2011 2:20 AM (in response to craig)Well I prefer to keep all validation stuff in the main action instead of split the action and validation. It works fine the fields still contains input. Once the fix it out you can put the validation stuff back in the validator action.
-
6. Re: Multiple UIInputContainer lose values ?
craig May 23, 2011 4:06 AM (in response to craig)Hi Sebastian,
My validation is annotations either on the model objects or the bean methods. Is this where yours is, or do you validate in the action method then manually add the messages to an id in the facesContext ?
Thanks for your help
Craig
-
7. Re: Multiple UIInputContainer lose values ?
ssachtleben.ssachtleben.gmail.com May 23, 2011 4:48 AM (in response to craig)I had also annotation based validation and these validation jsf beans but I removed all that for now and worked it out in the good old way:
/** * @author Sebastian Sachtleben */ @Named("registerAction") @Stateful @RequestScoped @MessureCalls @URLMapping(id = "login", pattern = "/login.html", viewId = "/pages/login/login.seam") public class RegisterActionImpl implements RegisterAction, Serializable { private static final long serialVersionUID = -1662395892339047313L; private Logger log = Logger.getLogger(RegisterActionImpl.class); @PersistenceContext private EntityManager em; @Inject private List<DateTimeZone> timeZones; @Inject private Credentials credentials; @Inject private Identity identity; @Inject private Registrar registrar; @Inject private Messages messages; @Inject private Event<UserCreatedEvent> createEvent; ///////// METHODS ///////// public String register() { log.debug("register()"); if (isValid()) { return saveUser(); } return null; } public List<DateTimeZone> getTimeZones() { return timeZones; } private boolean isValid() { log.debug("Validate register form"); if (registrar.getUsername() == null || registrar.getUsername().length() < 3 || registrar.getUsername().length() > 30) { messages.error(new BundleKey("messages", "login.error.InvalidUsername")).defaults("The username must be between 3 and 30 characters.").targets("register_usernameDec_rusername"); } if (registrar.getPassword() == null || registrar.getPassword().length() < 5 || registrar.getPassword().length() > 30) { messages.error(new BundleKey("messages", "login.error.InvalidPassword")).defaults("The password must be between 5 and 30 characters.").targets("register_passwordDec_rpassword"); } if (registrar.getPassword2() == null || registrar.getPassword2().length() < 5 || registrar.getPassword2().length() > 30) { messages.error(new BundleKey("messages", "login.error.InvalidPassword2")).defaults("The re-enter password must be between 5 and 30 characters.").targets("register_password2Dec_rpassword2"); } if (registrar.getEmail() == null || registrar.getEmail().length() < 1 || registrar.getEmail().length() > 50) { messages.error(new BundleKey("messages", "login.error.InvalidEmail")).defaults("The email must be between 1 and 50 characters.").targets("register_emailDec_remail"); } else { Pattern p = Pattern.compile("[a-zA-Z0-9]+@[a-zA-Z0-9]+\\.[a-zA-Z0-9]+"); Matcher m = p.matcher(registrar.getEmail()); if (!m.matches()) { messages.error(new BundleKey("messages", "login.error.InvalidEmailFormat")).defaults("The email address has invalid format.").targets("register_emailDec_remail"); } } if (registrar.getEmail2() == null || registrar.getEmail2().length() < 1 || registrar.getEmail2().length() > 50) { messages.error(new BundleKey("messages", "login.error.InvalidEmail2")).defaults("The re-enter email must be between 1 and 50 characters.").targets("register_email2Dec_remail2"); } else { Pattern p = Pattern.compile("[a-zA-Z0-9]+@[a-zA-Z0-9]+\\.[a-zA-Z0-9]+"); Matcher m = p.matcher(registrar.getEmail2()); if (!m.matches()) { messages.error(new BundleKey("messages", "login.error.InvalidEmailFormat2")).defaults("The re-enter email address has invalid format.").targets("register_email2Dec_remail2"); } } if (!registrar.getTerms()) { messages.error(new BundleKey("messages", "login.error.AcceptTerms")).defaults("Please accept our terms of sevices.").targets("register_termsDec_rterms"); } if (messages.isEmpty()) { if (!registrar.getPassword().equals(registrar.getPassword2())) { messages.error(new BundleKey("messages", "login.error.PasswordMatch")).defaults("Password doesnt match with re-enter.").targets("register_passwordDec_rpassword"); } if (!registrar.getEmail().equals(registrar.getEmail2())) { messages.error(new BundleKey("messages", "login.error.EmailMatch")).defaults("Email doesnt match with re-enter.").targets("register_emailDec_remail"); } } if (messages.isEmpty()) { return true; } return false; } private String saveUser() { log.debug("saveUser()"); // Create new user User regUser = new User(); regUser.setUsername(registrar.getUsername()); regUser.setEmail(registrar.getEmail()); regUser.setTimezone(registrar.getTimezone()); regUser.setNewsletter(registrar.getNewsletter()); // Set new hashed password String hashedPass = Sha256Hash.hash(registrar.getPassword()); log.debug(String.format("Generated password hash = {0}", hashedPass)); regUser.setPassword(hashedPass); // Persist new user em.persist(regUser); log.debug(String.format("Persisted new {0}", regUser.toString())); createEvent.fire(new UserCreatedEvent(regUser)); // Login with created user return loginUser(); } private String loginUser() { log.debug("loginUser()"); // Set login data credentials.setUsername(registrar.getUsername()); credentials.setCredential(new PasswordCredential(registrar.getPassword())); // Reset register form registrar.reset(); // Login new user return identity.login(); } }
/** * The registrar implementation allows for a username, password, re-enter password, * email, re-enter email, timezone and terms of service to be set. * * @author Sebastian Sachtleben */ @Named("registrar") @SessionScoped public class RegistrarImpl implements Registrar, Serializable { private static final long serialVersionUID = -367086888739234148L; private String username; private String password; private String password2; private String email; private String email2; private String timezone; private Boolean newsletter; private Boolean terms; ///////// METHODS ///////// @PostConstruct public void initalize() { reset(); } @Override public void reset() { username = ""; password = ""; password2 = ""; email = ""; email2 = ""; timezone = DateTimeZone.getDefault().getID(); newsletter = false; terms = false; } ///////// GETTER & SETTER ///////// public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getPassword2() { return password2; } public void setPassword2(String password2) { this.password2 = password2; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getEmail2() { return email2; } public void setEmail2(String email2) { this.email2 = email2; } public String getTimezone() { return timezone; } public void setTimezone(String timezone) { this.timezone = timezone; } public Boolean getNewsletter() { return newsletter; } public void setNewsletter(Boolean newsletter) { this.newsletter = newsletter; } public Boolean getTerms() { return terms; } public void setTerms(Boolean terms) { this.terms = terms; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((email == null) ? 0 : email.hashCode()); result = prime * result + ((email2 == null) ? 0 : email2.hashCode()); result = prime * result + ((newsletter == null) ? 0 : newsletter.hashCode()); result = prime * result + ((password == null) ? 0 : password.hashCode()); result = prime * result + ((password2 == null) ? 0 : password2.hashCode()); result = prime * result + ((terms == null) ? 0 : terms.hashCode()); result = prime * result + ((timezone == null) ? 0 : timezone.hashCode()); result = prime * result + ((username == null) ? 0 : username.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; RegistrarImpl other = (RegistrarImpl) obj; if (email == null) { if (other.email != null) return false; } else if (!email.equals(other.email)) return false; if (email2 == null) { if (other.email2 != null) return false; } else if (!email2.equals(other.email2)) return false; if (newsletter == null) { if (other.newsletter != null) return false; } else if (!newsletter.equals(other.newsletter)) return false; if (password == null) { if (other.password != null) return false; } else if (!password.equals(other.password)) return false; if (password2 == null) { if (other.password2 != null) return false; } else if (!password2.equals(other.password2)) return false; if (terms == null) { if (other.terms != null) return false; } else if (!terms.equals(other.terms)) return false; if (timezone == null) { if (other.timezone != null) return false; } else if (!timezone.equals(other.timezone)) return false; if (username == null) { if (other.username != null) return false; } else if (!username.equals(other.username)) return false; return true; } @Override public String toString() { return "Registrar [username=" + username + ", password=" + password + ", password2=" + password2 + ", email=" + email + ", email2=" + email2 + ", timezone=" + timezone + ", newsletter=" + newsletter + ", terms=" + terms + "]"; } }
Dont get confused because of the login.html mapping, I have login and register on the same page :)
I know validation and action bean should be split but currently there is no other way to have input values which stay on error.
Good luck :)
-
8. Re: Multiple UIInputContainer lose values ?
craig May 23, 2011 6:09 AM (in response to craig)I have created a work around for now....
I have new UIInputContainer (which is a copy of the seam version) called FacetUIInputContainer.
The difference being in the encodeBegin method:
| InputContainerElements elements = scan(getFacet(UIComponent.COMPOSITE_FACET_NAME), null, context); scan(getFacet("inputs"), elements, context); // assignIds(elements, context); wire(elements, context); getAttributes().put(getElementsAttributeName(), elements); if (elements.hasValidationError()) { getAttributes().put(getInvalidAttributeName(), true); } else { getAttributes().put(getInvalidAttributeName(), false); } |
Then the component template looks like :
<cc:interface componentType="org.jboss.seam.faces.FacetInputContainer" > <cc:facet name="inputs"/> <cc:attribute name="label"/> </cc:interface> <cc:implementation> <div id="#{cc.clientId}" class="#{cc.attrs.invalid ? 'invalid' : ''} wrapper" > <h:outputLabel id="label" value="#{cc.attrs.label}:" styleClass="#{cc.attrs.invalid ? 'invalid' : ''}" for="#{cc.attrs.for}"> <h:outputText styleClass="required" rendered="#{cc.attrs.required}" value="*" /> </h:outputLabel> <span class="value"> <h:panelGroup> <cc:renderFacet name="inputs"/> </h:panelGroup> </span> <h:message id="wrapperMessage" errorClass="invalid message" rendered="#{cc.attrs.invalid}" showSummary="true" showDetail="false" /> </div> </cc:implementation>
Referenced as:
<components:wrapper id="messageWrapper" label="Message"> <f:facet name="inputs"> <p:inputTextarea id="message" value="#{feedbackBean.message}" styleClass="feedback"/> </f:facet> </components:wrapper>
Hope this helps someone!
Cheers
Craig