9 Replies Latest reply on Aug 26, 2007 6:30 PM by fabmars

    a4j:support and custom validator tag error

    fernando_jmt

      Hi everyone.

      I'm using Seam 1.2 + Facelets + Ajax4JSF 1.1.0.

      I have a custom validator and a facelet tag for it in order to define a property in the validator. But it seems the setter of the validator tag property is never invoked when I use a4j:support, because the attribute is always null, even whether I define a value for the attribute.

      JSF Code:

      <h:outputLabel for="confirmPassword" value="#{messages['User.confirmPassword']}"/>
      <s:decorate id="confirmPasswordDecorate">
       <h:inputSecret id="confirmPassword" value="#{user.confirmPassword}" required="true" maxlength="40" redisplay="true" tabindex="3" styleClass="input">
       <app:validateEqual for="password"/>
       <a4j:support event="onblur" reRender="confirmPasswordDecorate"/>
       </h:inputSecret>
       <br/>
       <s:message/>
      </s:decorate>
      



      My validator class:
      public class EqualValidator implements Validator {
       private String foreignId;
      
       public void validate(FacesContext facesContext, UIComponent uiComponent, Object value) throws ValidatorException {
       //here foreignId is always null causing a NPE...
       UIComponent foreignComp = uiComponent.getParent().findComponent(foreignId);
      ...
      }
       public String getFor() {
       return foreignId;
       }
      
       public void setFor(String string) {
       foreignId = string;
       }
      
      }
      



      My app.taglib.xml:
      <tag>
       <tag-name>validateEqual</tag-name>
       <validator>
       <validator-id>com.jatun.myapp.validator.validateEqual</validator-id>
       </validator>
       </tag>
      


      And my faces-config:
      <validator>
       <validator-id>com.jatun.myapp.validator.validateEqual</validator-id>
       <validator-class>com.jatun.myapp.validator.EqualValidator</validator-class>
       </validator>
      
      


      The validator is invoked, but the problem is the foreignId attribute (defined by the tag atribute "for") is always null.

      This same validator was working for me when I didn't use Ajax4JSF, now when I change to Ajax4JSF I'm getting this problem.

      I have other fields with no custom validators working well using Ajax4JSF.

      What am I doing wrong?

      Is there something I am missing?


      Please point me out.

      Thanks in advance.








        • 1. Re: a4j:support and custom validator tag error

          What object uiComponent.getParent() returns?

          • 2. Re: a4j:support and custom validator tag error
            fernando_jmt

             

            "SergeySmirnov" wrote:
            What object uiComponent.getParent() returns?


            It returns org.jboss.seam.ui.UIDecorate object.

            BTW, printing this:
             System.out.println("foreignId: " + foreignId);
            


            I get in the console (when the validator is invoked):

            foreignId: null
            



            And the stacktrace I got:

            
            09:49:38,484 ERROR [ExceptionFilter] uncaught exception
            javax.servlet.ServletException: expr
             at javax.faces.webapp.FacesServlet.service(FacesServlet.java:154)
             at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
             at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
             at org.ajax4jsf.framework.ajax.xmlfilter.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:96)
             at org.ajax4jsf.framework.ajax.xmlfilter.BaseFilter.doFilter(BaseFilter.java:220)
             at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
             at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
             at org.jboss.seam.web.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:63)
             at org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:45)
             at org.jboss.seam.web.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:49)
             at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:57)
             at org.jboss.seam.web.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:49)
             at org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:79)
             at org.jboss.seam.web.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:49)
             at org.jboss.seam.web.SeamFilter.doFilter(SeamFilter.java:84)
             at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
             at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
             at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
             at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
             at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:432)
             at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
             at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
             at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
             at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
             at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
             at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtoco
            l.java:664)
             at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
             at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:80)
             at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
             at java.lang.Thread.run(Thread.java:595)
            09:49:38,500 ERROR [ExceptionFilter] exception root cause
            java.lang.NullPointerException: expr
             at javax.faces.component.UIComponentBase.findComponent(UIComponentBase.java:390)
             at com.jatun.myapp.validator.EqualValidator.validate(EqualValidator.java:44)
             at javax.faces.component._ComponentUtils.callValidators(_ComponentUtils.java:160)
             at javax.faces.component.UIInput.validateValue(UIInput.java:313)
             at javax.faces.component.UIInput.validate(UIInput.java:354)
             at javax.faces.component.UIInput.processValidators(UIInput.java:184)
             at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:627)
             at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:627)
             at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:627)
             at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:627)
             at javax.faces.component.UIForm.processValidators(UIForm.java:73)
             at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:627)
             at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:149)
             at org.ajax4jsf.framework.ajax.AjaxViewRoot.access$201(AjaxViewRoot.java:53)
             at org.ajax4jsf.framework.ajax.AjaxViewRoot$3.invokeRoot(AjaxViewRoot.java:302)
             at org.ajax4jsf.framework.ajax.JsfOneOneInvoker.invokeOnRegionOrRoot(JsfOneOneInvoker.java:54)
             at org.ajax4jsf.framework.ajax.AjaxContext.invokeOnRegionOrRoot(AjaxContext.java:176)
             at org.ajax4jsf.framework.ajax.AjaxViewRoot.processValidators(AjaxViewRoot.java:315)
             at org.apache.myfaces.lifecycle.ProcessValidationsExecutor.execute(ProcessValidationsExecutor.java:32)
             at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:95)
             at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:70)
             at javax.faces.webapp.FacesServlet.service(FacesServlet.java:139)
             at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
             at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
             at org.ajax4jsf.framework.ajax.xmlfilter.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:96)
             at org.ajax4jsf.framework.ajax.xmlfilter.BaseFilter.doFilter(BaseFilter.java:220)
             at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
             at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
             at org.jboss.seam.web.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:63)
             at org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:45)
             at org.jboss.seam.web.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:49)
             at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:57)
             at org.jboss.seam.web.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:49)
             at org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:79)
             at org.jboss.seam.web.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:49)
             at org.jboss.seam.web.SeamFilter.doFilter(SeamFilter.java:84)
             at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
             at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
             at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
             at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
             at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:432)
             at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
             at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
             at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
             at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
             at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
             at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtoco
            l.java:664)
             at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
             at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:80)
             at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
             at java.lang.Thread.run(Thread.java:595)
            09:49:38,515 INFO [Exceptions] reading exception mappings from /WEB-INF/pages.xml
            09:49:38,546 ERROR [DebugPageHandler] redirecting to debug page
            java.lang.NullPointerException: expr
             at javax.faces.component.UIComponentBase.findComponent(UIComponentBase.java:390)
             at com.jatun.myapp.validator.EqualValidator.validate(EqualValidator.java:44)
             at javax.faces.component._ComponentUtils.callValidators(_ComponentUtils.java:160)
             at javax.faces.component.UIInput.validateValue(UIInput.java:313)
             at javax.faces.component.UIInput.validate(UIInput.java:354)
             at javax.faces.component.UIInput.processValidators(UIInput.java:184)
             at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:627)
             at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:627)
             at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:627)
             at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:627)
             at javax.faces.component.UIForm.processValidators(UIForm.java:73)
             at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:627)
             at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:149)
             at org.ajax4jsf.framework.ajax.AjaxViewRoot.access$201(AjaxViewRoot.java:53)
             at org.ajax4jsf.framework.ajax.AjaxViewRoot$3.invokeRoot(AjaxViewRoot.java:302)
             at org.ajax4jsf.framework.ajax.JsfOneOneInvoker.invokeOnRegionOrRoot(JsfOneOneInvoker.java:54)
             at org.ajax4jsf.framework.ajax.AjaxContext.invokeOnRegionOrRoot(AjaxContext.java:176)
             at org.ajax4jsf.framework.ajax.AjaxViewRoot.processValidators(AjaxViewRoot.java:315)
             at org.apache.myfaces.lifecycle.ProcessValidationsExecutor.execute(ProcessValidationsExecutor.java:32)
             at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:95)
             at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:70)
             at javax.faces.webapp.FacesServlet.service(FacesServlet.java:139)
             at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
             at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
             at org.ajax4jsf.framework.ajax.xmlfilter.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:96)
             at org.ajax4jsf.framework.ajax.xmlfilter.BaseFilter.doFilter(BaseFilter.java:220)
             at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
             at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
             at org.jboss.seam.web.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:63)
             at org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:45)
             at org.jboss.seam.web.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:49)
             at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:57)
             at org.jboss.seam.web.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:49)
             at org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:79)
             at org.jboss.seam.web.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:49)
             at org.jboss.seam.web.SeamFilter.doFilter(SeamFilter.java:84)
             at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
             at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
             at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
             at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
             at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:432)
             at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
             at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
             at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
             at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
             at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
             at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtoco
            l.java:664)
             at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
             at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:80)
             at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
             at java.lang.Thread.run(Thread.java:595)
            



            Thanks for your response.

            • 3. Re: a4j:support and custom validator tag error

              Hmm. So, I am lost. You are looking for component with id "password" between the children of the local s:decorate. However, there is no child with such id there according to the code snippet you provided above. Could you explain this?

              • 4. Re: a4j:support and custom validator tag error
                fernando_jmt

                 

                "SergeySmirnov" wrote:
                Hmm. So, I am lost. You are looking for component with id "password" between the children of the local s:decorate. However, there is no child with such id there according to the code snippet you provided above. Could you explain this?



                Ok, What I can't explain is how this works if I remove a4j:support from the inputText.

                But beyond than whether the component is found or not, the problem is the "for" attribute value defined in my custom tag never calls the setter in the validator, I mean even I define
                <app:validateEqual for="whatever"/>
                


                the attribute of the validator:
                ..
                private String foreignId;
                
                public String getFor() {
                 return foreignId;
                 }
                
                 public void setFor(String string) {
                 foreignId = string;
                 }
                ...
                


                is always null.



                Only for a simple test I did the following:

                private String foreignId = "password";
                


                Doing this all works fine, the validator shows the respective message.


                I'm not sure what is going on here, but it seems the problem is related with the definition of the attributes of the custom validator tag using facelets and a4j:support.


                Any ideas?


                Thanks in advance

                • 5. Re: a4j:support and custom validator tag error

                  you speak about the custom validator. Could you try to put there one of the standard validator for the testing purpose and see where is the point when the problem is gone.

                  • 6. Re: a4j:support and custom validator tag error
                    fernando_jmt

                     

                    "SergeySmirnov" wrote:
                    you speak about the custom validator. Could you try to put there one of the standard validator for the testing purpose and see where is the point when the problem is gone.



                    I registered the standard f:validateLength instead of my custom validator, as follows:


                    <s:decorate id="confirmPasswordDecorate">
                     <h:inputSecret id="confirmPassword" value="#{user.confirmPassword}" required="true"
                     maxlength="40" redisplay="true" tabindex="3" styleClass="input">
                     <f:validateLength minimum="5"/>
                     <a4j:support event="onblur" reRender="confirmPasswordDecorate"/>
                     </h:inputSecret>
                     <br/>
                     <s:message/>
                    </s:decorate>
                    
                    


                    and with that standard validator all works fine.

                    I test again changing the booking seam example adding it a custom validator using facelets and using the a4j:support (same as in my application) and I got the same problem: the attributes of the custom validator are never setted.

                    It really seems a bug because if I remove the a4j:support the custom validator works like a charm.

                    What do I suppose to do now?

                    Please help...








                    • 7. Re: a4j:support and custom validator tag error
                      ashina

                      I'm not sure my advice will help you, but I had similar problems while writing custom renderers, and this is how I have solved them.
                      JSF API documentation tells that if you assign any properties to validator (such as "for" in your validator), your EqualValidator class must implement StateHolder interface, and you have to properly implement saveState/restoreState methods.
                      I think the role of A4J here is that ajax4jsf during a4j requests forces components and validators to save/restore their state - but your validator cannot save himself.

                      So implementing EqualValidator as StateHolder seems to solve your problems.

                      • 8. Re: a4j:support and custom validator tag error
                        fernando_jmt

                        And do you know why it works as it is when I don't uses a4j:support?

                        Nevertheless, I will try what you suggest me, and I'll post back my results.

                        Thanks.

                        • 9. Re: a4j:support and custom validator tag error
                          fabmars

                          Better late than never, I have an answer for that. I made some custom components and got the same issue as fernando : the attributes of my custom validators/converters wouldn't get set.

                          After some debugging I found out they are actually set, once, when the page is rendered the first time. However, using a4j:support, you have several requests for one full view rendered. Thus, from the first Ajax request in your page, Converters and Validators are reinstanciated, but their properties are not.

                          All this is because, as ashina says, your component cannot saveState and restoreState.

                          This would never bug you in a non-ajax environment since there is one request for one full page rendered and your Converters/Validators are set correctly the only time the view is generated.