Uploaded image for project: 'Seam Faces'
  1. Seam Faces
  2. SEAMFACES-186

<s:validateForm>: injection of nested component values fails

    Details

    • Type: Bug
    • Status: Pull Request Sent (View Workflow)
    • Priority: Minor
    • Resolution: Unresolved
    • Affects Version/s: 3.0.2
    • Fix Version/s: None
    • Labels:
      None
    • Environment:
      JBAS 7
      Mojarra 2.0.4

      Description

      This valitator:

      @FacesValidator("passwordRepeatValidator")
      @RequestScoped
      @Named
      public class PasswordRepeatValidator implements Validator {
          @Inject @InputField private String password;
          @Inject @InputField private String passwordRepeat;
       
          @Override
          public void validate(FacesContext facesContext, UIComponent uiComponent, Object o) throws ValidatorException {
              if (!passwordRepeat.equals(password)) {
                  throw new ValidatorException(new FacesMessage("Passwords don't match."));
              }
          }
      }
      

      used like this:

      <h:form id="f">
          <s:validateForm validatorId="passwordRepeatValidator"/>
          <h:dataTable id="t" value="1" var="x">
              <h:column id="c">
                  <h:inputSecret id="password"/>
                  <h:message for="password"/>
                  <h:inputSecret id="passwordRepeat"/>
                  <h:message for="passwordRepeat"/>
              </h:column>
          </h:dataTable>
          <h:commandButton value="Submit"/>
      </h:form>
      

      fails with:

      10:57:13,407 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[ppay-web].[/].[Faces Servlet]] (http--127.0.0.1-8080-2) Servlet.service() for servlet Faces Servlet threw exception: java.lang.IllegalArgumentException: org.jboss.seam.component.UIValidateForm-- Could not locate component [f:password]
      	at org.jboss.seam.faces.component.FormValidationFieldProducer.findComponent(FormValidationFieldProducer.java:160) [seam-faces-impl-3.0.2.Final.jar:]
      	at org.jboss.seam.faces.component.FormValidationFieldProducer.getInputFieldValue(FormValidationFieldProducer.java:76) [seam-faces-impl-3.0.2.Final.jar:]
      	at sun.reflect.GeneratedMethodAccessor446.invoke(Unknown Source) [:1.6.0_24]
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [:1.6.0_24]
      	at java.lang.reflect.Method.invoke(Method.java:597) [:1.6.0_24]
      	at org.jboss.weld.util.reflection.SecureReflections$13.work(SecureReflections.java:305) [weld-core-1.1.2.AS7.jar:2011-07-06 12:26]
      	at org.jboss.weld.util.reflection.SecureReflectionAccess.run(SecureReflectionAccess.java:54) [weld-core-1.1.2.AS7.jar:2011-07-06 12:26]
      	at org.jboss.weld.util.reflection.SecureReflectionAccess.runAsInvocation(SecureReflectionAccess.java:163) [weld-core-1.1.2.AS7.jar:2011-07-06 12:26]
      	at org.jboss.weld.util.reflection.SecureReflections.invoke(SecureReflections.java:299) [weld-core-1.1.2.AS7.jar:2011-07-06 12:26]
      	at org.jboss.weld.introspector.jlr.WeldMethodImpl.invokeOnInstance(WeldMethodImpl.java:188) [weld-core-1.1.2.AS7.jar:2011-07-06 12:26]
      	at org.jboss.weld.injection.MethodInjectionPoint.invokeOnInstance(MethodInjectionPoint.java:169) [weld-core-1.1.2.AS7.jar:2011-07-06 12:26]
      	at org.jboss.weld.bean.ProducerMethod$1.produce(ProducerMethod.java:149) [weld-core-1.1.2.AS7.jar:2011-07-06 12:26]
      	at org.jboss.weld.bean.AbstractProducerBean.create(AbstractProducerBean.java:361) [weld-core-1.1.2.AS7.jar:2011-07-06 12:26]
      	at org.jboss.weld.context.unbound.DependentContextImpl.get(DependentContextImpl.java:67) [weld-core-1.1.2.AS7.jar:2011-07-06 12:26]
      	at org.jboss.weld.manager.BeanManagerImpl.getReference(BeanManagerImpl.java:693) [weld-core-1.1.2.AS7.jar:2011-07-06 12:26]
      	at org.jboss.weld.manager.BeanManagerImpl.getReference(BeanManagerImpl.java:775) [weld-core-1.1.2.AS7.jar:2011-07-06 12:26]
      	at org.jboss.weld.injection.FieldInjectionPoint.inject(FieldInjectionPoint.java:138) [weld-core-1.1.2.AS7.jar:2011-07-06 12:26]
      	at org.jboss.weld.util.Beans.injectBoundFields(Beans.java:875) [weld-core-1.1.2.AS7.jar:2011-07-06 12:26]
      	at org.jboss.weld.util.Beans.injectFieldsAndInitializers(Beans.java:887) [weld-core-1.1.2.AS7.jar:2011-07-06 12:26]
      	at org.jboss.weld.bean.ManagedBean$ManagedBeanInjectionTarget$1$1.proceed(ManagedBean.java:182) [weld-core-1.1.2.AS7.jar:2011-07-06 12:26]
      	at org.jboss.weld.injection.InjectionContextImpl.run(InjectionContextImpl.java:54) [weld-core-1.1.2.AS7.jar:2011-07-06 12:26]
      	at org.jboss.weld.bean.ManagedBean$ManagedBeanInjectionTarget$1.work(ManagedBean.java:176) [weld-core-1.1.2.AS7.jar:2011-07-06 12:26]
      	at org.jboss.weld.bean.ManagedBean$FixInjectionPoint.run(ManagedBean.java:142) [weld-core-1.1.2.AS7.jar:2011-07-06 12:26]
      	at org.jboss.weld.bean.ManagedBean$ManagedBeanInjectionTarget.inject(ManagedBean.java:170) [weld-core-1.1.2.AS7.jar:2011-07-06 12:26]
      	at org.jboss.weld.bean.ManagedBean.create(ManagedBean.java:339) [weld-core-1.1.2.AS7.jar:2011-07-06 12:26]
      	at org.jboss.weld.context.AbstractContext.get(AbstractContext.java:122) [weld-core-1.1.2.AS7.jar:2011-07-06 12:26]
      	at org.jboss.weld.bean.proxy.ContextBeanInstance.getInstance(ContextBeanInstance.java:99) [weld-core-1.1.2.AS7.jar:2011-07-06 12:26]
      	at org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:87) [weld-core-1.1.2.AS7.jar:2011-07-06 12:26]
      	at com.example.PasswordRepeatValidator$Proxy$_$$_WeldClientProxy.validate(PasswordRepeatValidator$Proxy$_$$_WeldClientProxy.java) [backend-1.0.0-SNAPSHOT.jar:]
      	at org.jboss.seam.faces.component.UIValidateForm.validate(UIValidateForm.java:96) [seam-faces-api-3.0.2.Final.jar:]
      	at javax.faces.component.UIInput.executeValidate(UIInput.java:1209) [jboss-jsf-api_2.0_spec-1.0.0.Final.jar:1.0.0.Final]
      	at javax.faces.component.UIInput.processValidators(UIInput.java:698) [jboss-jsf-api_2.0_spec-1.0.0.Final.jar:1.0.0.Final]
      	at javax.faces.component.UIForm.processValidators(UIForm.java:244) [jboss-jsf-api_2.0_spec-1.0.0.Final.jar:1.0.0.Final]
      	at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1085) [jboss-jsf-api_2.0_spec-1.0.0.Final.jar:1.0.0.Final]
      	at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1165) [jboss-jsf-api_2.0_spec-1.0.0.Final.jar:1.0.0.Final]
      	at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:76) [jsf-impl-2.0.4-b09-jbossorg-4.jar:2.0.4-b09-jbossorg-4]
      	at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) [jsf-impl-2.0.4-b09-jbossorg-4.jar:2.0.4-b09-jbossorg-4]
      	at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118) [jsf-impl-2.0.4-b09-jbossorg-4.jar:2.0.4-b09-jbossorg-4]
      	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:312) [jboss-jsf-api_2.0_spec-1.0.0.Final.jar:1.0.0.Final]
      	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329) [jbossweb-7.0.0.CR4.jar:7.0.0.Final]
      

      If the <h:dataTable><h:column> code is removed, it works as expected. It seems FormValidationFieldProducer is not able to locate the input components (password, passwordRepeat) if they are nested inside a NamingContainer (it this case a data table).

        Gliffy Diagrams

          Activity

          Hide
          mazi Matija Mazi added a comment -

          The client id of the input is not "f:password" but "f:t:0:password":

          <form id="f" name="f" method="post" action="/validate.ps" enctype="application/x-www-form-urlencoded"> 
          <input type="hidden" name="f" value="f" /> 
          <table id="f:t"> 
          <tbody> 
          <tr> 
          <td><input id="f:t:0:password" type="password" name="f:t:0:password" value="" /><input id="f:t:0:passwordRepeat" type="password" name="f:t:0:passwordRepeat" value="" /></td> 
          </tr> 
          </tbody> 
          </table> 
          <input type="submit" name="f:j_idt6" value="Submit" /><input type="hidden" name="javax.faces.ViewState" id="javax.faces.ViewState" value="-8956563578389240320:-2151205532426547112" autocomplete="off" /> 
          </form> 
          

          Show
          mazi Matija Mazi added a comment - The client id of the input is not "f:password" but "f:t:0:password": < form id = "f" name = "f" method = "post" action = "/validate.ps" enctype = "application/x-www-form-urlencoded" > < input type = "hidden" name = "f" value = "f" /> < table id = "f:t" > < tbody > < tr > < td >< input id = "f:t:0:password" type = "password" name = "f:t:0:password" value = "" />< input id = "f:t:0:passwordRepeat" type = "password" name = "f:t:0:passwordRepeat" value = "" /></ td > </ tr > </ tbody > </ table > < input type = "submit" name = "f:j_idt6" value = "Submit" />< input type = "hidden" name = "javax.faces.ViewState" id = "javax.faces.ViewState" value = "-8956563578389240320:-2151205532426547112" autocomplete = "off" /> </ form >
          Hide
          oranheim Ove Ranheim added a comment -

          I tried to use s:validateForm in a nested composite component and it breaks there too.

          Show
          oranheim Ove Ranheim added a comment - I tried to use s:validateForm in a nested composite component and it breaks there too.
          Hide
          mazi Matija Mazi added a comment -

          I can confirm the problem also occurs with a composite component. (Actually, this was my original problem that I then simplified to using a DataTable.)

          Show
          mazi Matija Mazi added a comment - I can confirm the problem also occurs with a composite component. (Actually, this was my original problem that I then simplified to using a DataTable.)
          Hide
          kchenga Jack Cheng added a comment -

          I added one method to call the findComponent method of the descendent NamingContainers to find the component matching the id.

          the method finds the nested components, but the getSubmittedValue() method of the nested components returns null. I don't think this has to do with Seam Faces but an issue with the underlying JSF implementation. the workaround is for s:validateForm to be in the same NamingContainer as the nested components.

          <h:form id="f">

          <h:dataTable id="t" value="1" var="x">
          <h:column id="c">
          <h:inputSecret id="password"/>
          <h:message for="password" />
          <h:inputSecret id="passwordRepeat"/>
          <h:message for="passwordRepeat"/>

          <s:validateForm validatorId="passwordInputElementValidator"/>
          </h:column>
          </h:dataTable>
          <h:commandButton value="Submit"/>

          </h:form>

          Show
          kchenga Jack Cheng added a comment - I added one method to call the findComponent method of the descendent NamingContainers to find the component matching the id. the method finds the nested components, but the getSubmittedValue() method of the nested components returns null. I don't think this has to do with Seam Faces but an issue with the underlying JSF implementation. the workaround is for s:validateForm to be in the same NamingContainer as the nested components. <h:form id="f"> <h:dataTable id="t" value="1" var="x"> <h:column id="c"> <h:inputSecret id="password"/> <h:message for="password" /> <h:inputSecret id="passwordRepeat"/> <h:message for="passwordRepeat"/> <s:validateForm validatorId="passwordInputElementValidator"/> </h:column> </h:dataTable> <h:commandButton value="Submit"/> </h:form>

            People

            • Assignee:
              Unassigned
              Reporter:
              mazi Matija Mazi
            • Votes:
              1 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

              • Created:
                Updated:

                Development