5 Replies Latest reply on Dec 15, 2006 5:20 AM by ccurban

    @IfInvalid is out, so?

    smokingapipe

      @IfInvalid is deprecated, with the notation that it's very broken and can't be fixed. I don't understand what that means but I'll take the Seam team's word for it. Anyway, so it looks like the replacement is to use the <s:validateAll> tag around all the elements in the form that are to be validated.

      I did this, and when the form is OK, everything works fine, but when the form is not OK, I get an exception. It should just redisplay the form with error messages, instead of throwing the org.hibernate.validator.InvalidStateException. I must be making some small mistake here. Any ideas?

        • 1. Re: @IfInvalid is out, so?
          pmuir

          What validation is causing the problem - @NotNull/@Length?

          • 2. Re: @IfInvalid is out, so?
            smokingapipe

            What's happening is that the action is being called even though the input is not valid. My thought was that if the object is not valid, the page should re-display, without calling the action, right?

            Here's some code:

            In test.jsp:

            <h:form id="createTestBean">
             <s:validateAll>
             <h:panelGrid columns="3" border="3" >
            
             <h:outputLabel for="foo">
             <h:outputText value="Foo:"/>
             </h:outputLabel>
             <h:inputText id="foo" value="#{testBean.foo}"/>
             <h:message for="foo"/>
            
            
             <h:outputLabel for="bar">
             <h:outputText value="Bar:"/>
             </h:outputLabel>
             <h:inputText id="bar" value="#{testBean.bar}"/>
             <h:message for="bar"/>
            
             </h:panelGrid>
            
             <h:messages globalOnly="false"/>
            
             <h:commandButton value="Create new test bean" action="#{testManager.persist}"/>
             <h:commandButton value="Reset" type="reset"/>
             </s:validateAll>
             </h:form>


            And the action:

            @Stateful
            @Name("testManager")
            public class TestManagerAction implements TestManager {
             private static final Logger logger =
             Logger.getLogger("TESTMANAGER");
            
            
             /** Creates a new instance of TestAction */
             public TestManagerAction() {
             }
            
             /** This thing is just injected, not created! */
             @In(create=true) EntityManager smpc;
            
             /** This is one to persist */
             @In(create=true) @Out TestBean testBean;
            
             @DataModel
             List<TestBean> testBeans;
            
             @DataModelSelection
             TestBean selectedTestBean;
            
             @Factory("testBeans")
             public void testBeansFactory() {
             if(smpc == null) {
             logger.severe("OH NO! there was no entity manager");
             return;
             }
            
             final Query query = smpc.createQuery("from TestBean t " +
             "order by foo");
             testBeans = query.getResultList();
            
             }
            
             public String persist() {
             if(smpc == null) {
             logger.severe("OH NO! there was no entity manager");
             return null;
             }
            
             smpc.persist(testBean);
             testBean = new TestBean();
            
             return null;
             }
            
             @In(create=true)
             private transient FacesMessages facesMessages;
            
             @Remove @Destroy
             public void destroy() { }
            
            }
            


            and the bean itself, boilerplate removed:

            @Entity
            @Name("testBean")
            public class TestBean {
            
             private int id;
             @Id @GeneratedValue public int getId() { return id; }
             public void setId(int id) { this.id = id; }
            
             private String foo;
             private String bar;
            
             @Length(min=5,max=8,message="Length must be from 5 to 8 chars bozo")
             public String getFoo() {
             return foo;
             }
            
             public void setFoo(String foo) {
             this.foo = foo;
             }
            
             public String getBar() {
             return bar;
             }
            
             public void setBar(String bar) {
             this.bar = bar;
             }
            
             public String toString() {
             return "TestBean " + id + "; foo= " + foo + ", bar = " + bar;
             }
            
            }
            


            Whenever I use the form, if I enter an invalid field, it attempts to do the persist and then throws an exception. What it should do is redisplay the page with the validation message, and not even attempt to persist it. I don't get it.

            This is all with Seam 1.1.0 GA and JBoss 4.0.5 GA.

            Any ideas on this? It must be something simple I'm missing.


            • 3. Re: @IfInvalid is out, so?
              pmuir

              @Length doesn't work on its own, you need to use the required attribute in the JSF. See the problems FAQ.

              • 4. Re: @IfInvalid is out, so?
                smokingapipe

                AYE SANTA MARIA that was painful. I spent about a day going over examples etc to figure out why that wasn't working. That fixed it. If you have a @Length validation on the bean, put a required="true" attribute into the inputText JSF component, and it works as expected.

                Here's the URL for the Seam Problems Faq:

                http://wiki.jboss.org/wiki/Wiki.jsp?page=SeamProblemsFAQ

                It's the last item. The explanation there is terse. It should say in big letters, "If you use Hibernate validations on your bean, you must also put required="true" in your JSF code."

                • 5. Re: @IfInvalid is out, so?
                  ccurban

                  Propably this is more of a JSF question, but is there any chance to avoid the jsf error message, which will be shown when the input field is emtpy and required="true" ?

                  With s:validate and required="true" you actually get a "two-step" validation:
                  First all fields with required="true" are checked and standard jsf error messages are shown.
                  Second the hibernate validations are checked.

                  What I would like to see is that only the error messages from the hibernate validations are shown, which was the behaviour with the @IfInvalid annotation.