Hibernate and regular JSF validation and EntityHome prob
hstang Jun 18, 2007 12:47 PMI have a very simple page that edits the "first name" property of a Person entity using an EntityHome object. The page has an input text control and an update button that is only rendered if the "managed" property is true. I want to place two constraints on editting the first name:
(1) minimum length must be at least 2 characters
(2) first name cannot equal to "jsf"
I'm using Hibernate validators to do (1) via @Length(min = 2), and I'm using regular JSF validation to do (2). (2) is enabled by appending f:validator tag in my input text control.
Simple enough, but I'm encountering a couple strange behaviours.
If you enter "jsf" to force regular JSF validation, then the "managed" property of the EntityHome becomes false and the update button disappears, but you'll get the validation error message on the screen. Why does the "managed" property becomes false after a regular JSF validation error?
If you enter the letter 'a' to force a hibernate validation error (because minimum length is less than 2), then I get an exception with message:
"Caused by org.hibernate.validator.InvalidStateException with message: "validation failed for: com.mxnmedia.siteaudit.model.Person". Note at this time I still have the f:validator tag attached to the input text control. Now, if I remove f:validator tag to disable regular JSF validation, then I'll get the expected "length must be between 2 and 2147483647" message AND the update button will still be there.
Below is the minimal code I have to reproduce this. I was using latest Seam-CVS. Edit page is accessed by [whatever_your_context_path_is/test.seam?id=1]
## JsfValidator.java
@Name("jsfValidator") @Validator public class JsfValidator implements javax.faces.validator.Validator, Serializable { public void validate(FacesContext facesContext, UIComponent uiComponent, Object object) throws ValidatorException { if ("jsf".equals((String) object)) throw new ValidatorException(new FacesMessage("Validation failed")); } }
## components.xml
<fwk:entity-home name="personHome" entity-class="Person"/>
## import.sql
INSERT INTO person(id,firstname) VALUES (1,'Joe');
## Person.java
@Entity public class Person { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "generator") @SequenceGenerator(name = "generator", sequenceName = "person_seq") private Long id; @Length(min = 2) private String firstName; // getters and setters for firstName and id
## test.page.xml
<page ..> <begin-conversation join="true"/> <param name="id" value="#{personHome.id}" converterId="javax.faces.Long"/> </page>
## test.xhtml
<h:form> <f:facet name="afterInvalidField"> <s:message/> </f:facet> <s:validateAll> <s:decorate> <h:inputText value="#{personHome.instance.firstName}" required="true"> <f:validator validatorId="jsfValidator"/> </h:inputText> </s:decorate> </s:validateAll> <h:commandButton action="#{personHome.update}" value="Update" rendered="#{personHome.managed}"/> </h:form>