10 Replies Latest reply on Aug 7, 2007 6:30 PM by pmuir

    Trinidad: Validation still not working

    stephen.friedrich

      I haven't been able to get s:validateAll to work with tr:inputText
      (JBoss Seam CVS, Trinidad 1.2.1, JBOss AS 4.2.1)
      The bug can be reproduced with seamdiscs example, when adding @Length(min=3, max=32) to Disc.name declaration.

      When trying to add a short or longer name the following exception occurs:

      Additionally the error handling fails: A 404 is displayed with this URL: http://127.0.0.1:8080/seam-discs/disc.seam/error.xhtml?cid=6

      I noticed that http://jira.jboss.com/jira/browse/JBSEAM-501 is fixed and indeed when I debug I see that in ValidateAllRendererBase.addValidators() in fact there is a validator added to the trinidad input component.

      Any idea why this is not working?

      23:48:05,281 FATAL [application] org.hibernate.validator.InvalidStateException: validation failed for: org.jboss.seam.example.seamdiscs.model.Disc
      javax.faces.el.EvaluationException: org.hibernate.validator.InvalidStateException: validation failed for: org.jboss.seam.example.seamdiscs.model.Disc
       at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:91)
       at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:91)
       at javax.faces.component.UICommand.broadcast(UICommand.java:383)
       at org.ajax4jsf.framework.ajax.AjaxViewRoot.processEvents(AjaxViewRoot.java:180)
       at org.ajax4jsf.framework.ajax.AjaxViewRoot.broadcastEvents(AjaxViewRoot.java:158)
       at org.ajax4jsf.framework.ajax.AjaxViewRoot.processApplication(AjaxViewRoot.java:346)
       at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:97)
       at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:251)
       at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:117)
       at javax.faces.webapp.FacesServlet.service(FacesServlet.java:244)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
       at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl._invokeDoFilter(TrinidadFilterImpl.java:208)
       at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl._doFilterImpl(TrinidadFilterImpl.java:165)
       at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl.doFilter(TrinidadFilterImpl.java:138)
       at org.apache.myfaces.trinidad.webapp.TrinidadFilter.doFilter(TrinidadFilter.java:92)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:82)
       at org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:85)
       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:68)
       at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64)
       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:68)
       at org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:44)
       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:68)
       at org.ajax4jsf.framework.ajax.xmlfilter.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:127)
       at org.ajax4jsf.framework.ajax.xmlfilter.BaseFilter.doFilter(BaseFilter.java:277)
       at org.jboss.seam.web.Ajax4jsfFilter.doFilter(Ajax4jsfFilter.java:60)
       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:68)
       at org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:58)
       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:68)
       at org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:149)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
       at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
       at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
       at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
       at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:179)
       at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)
       at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
       at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
       at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)
       at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
       at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:241)
       at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
       at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:580)
       at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
       at java.lang.Thread.run(Thread.java:619)
      Caused by: org.hibernate.validator.InvalidStateException: validation failed for: org.jboss.seam.example.seamdiscs.model.Disc
       at org.hibernate.validator.event.ValidateEventListener.validate(ValidateEventListener.java:143)
       at org.hibernate.validator.event.ValidateEventListener.onPreUpdate(ValidateEventListener.java:172)
       at org.hibernate.action.EntityUpdateAction.preUpdate(EntityUpdateAction.java:217)
       at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:65)
       at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:250)
       at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:234)
       at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:142)
       at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
       at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
       at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
       at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:296)
       at org.jboss.seam.persistence.EntityManagerProxy.flush(EntityManagerProxy.java:90)
       at org.jboss.seam.framework.EntityHome.update(EntityHome.java:41)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:597)
       at org.jboss.seam.util.Reflections.invoke(Reflections.java:21)
       at org.jboss.seam.intercept.RootInvocationContext.proceed(RootInvocationContext.java:31)
       at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:56)
       at org.jboss.seam.persistence.ManagedEntityIdentityInterceptor.aroundInvoke(ManagedEntityIdentityInterceptor.java:45)
       at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
       at org.jboss.seam.transaction.RollbackInterceptor.aroundInvoke(RollbackInterceptor.java:31)
       at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
       at org.jboss.seam.transaction.TransactionInterceptor$1.work(TransactionInterceptor.java:38)
       at org.jboss.seam.util.Work.workInTransaction(Work.java:39)
       at org.jboss.seam.transaction.TransactionInterceptor.aroundInvoke(TransactionInterceptor.java:32)
       at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
       at org.jboss.seam.core.MethodContextInterceptor.aroundInvoke(MethodContextInterceptor.java:42)
       at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
       at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:106)
       at org.jboss.seam.intercept.JavaBeanInterceptor.interceptInvocation(JavaBeanInterceptor.java:151)
       at org.jboss.seam.intercept.JavaBeanInterceptor.invoke(JavaBeanInterceptor.java:87)
       at org.jboss.seam.framework.EntityHome_$$_javassist_2.update(EntityHome_$$_javassist_2.java)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:597)
       at org.jboss.el.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:328)
       at org.jboss.el.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:341)
       at org.jboss.el.parser.AstPropertySuffix.invoke(AstPropertySuffix.java:58)
       at org.jboss.el.parser.AstValue.invoke(AstValue.java:96)
       at org.jboss.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:276)
       at com.sun.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:68)
       at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:77)
       ... 49 more
      


        • 1. Re: Trinidad: Validation still not working
          stephen.friedrich

          Did some debugging and research and found that this was already reported as JBSEAM-1667 but seems to be an issue with Trinidad.

          I'll try and test with a newer Trinidad version.

          • 2. Re: Trinidad: Validation still not working
            wschwendt

            A big thank you for posting this! Incidentally, I already spent the entire day on this trinidad validation mess.

            Backdrop: I had problems getting the Hibernate validator to work with the CVS-based Seam (solved in the meantime thanks to Pete Muir's helpful response): http://www.jboss.com/index.html?module=bb&op=viewtopic&t=115318

            So I thought: Why not use the JSF validators as temporary workaround? And then I noticed that the JSF validators fail to work correctly when Trinidad is involved. What's more, the Hibernate validator annotations don't work either in combination with s:validate all and Trinidad (one can test this by modifying Seam-discs).


            Any idea why this is not working?


            no real idea, but I debugged it and it looked to me as if it could be a state restoration issue.

            When the view tree is constructed during the first RENDER RESPONSE phase, the validator properties (attributes such as minimum or maximum) are stored. On a subsequent faces request, this state is supposed to be restored during the RESTORE VIEW phase. But it appears that this isn't working correctly.

            The culprit could possibly be org.apache.myfaces.trinidad.bean.util.StateUtils.restoreState() or a related method.

            StateUtils.restoreState() is called from org.apache.myfaces.trinidad.bean.util.FlaggedPropertyMap.

            // org.apache.myfaces.trinidad.bean.util.FlaggedPropertyMap
             public void restoreState(
             FacesContext context,
             FacesBean.Type type,
             Object state)
             {
             StateUtils.restoreState(this, context, type, state, getUseStateHolder());
             }
            
            



            Until FlaggedPropertyMap.restoreState() is called, the restoration process looks ok to me (at least the argument named "state" correctly contained the validator properties).

            A Trinidad expert would need to look at this, where exactly the state restoration fails.




            • 3. Re: Trinidad: Validation still not working
              wschwendt

               

              "wschwendt" wrote:
              it looked to me as if it could be a state restoration issue.

              When the view tree is constructed during the first RENDER RESPONSE phase, the validator properties (attributes such as minimum or maximum) are stored. On a subsequent faces request, this state is supposed to be restored during the RESTORE VIEW phase. But it appears that this isn't working correctly.


              the debugging clearly revealed that validator properties are not correctly restored.

              So it's absolutely no surprise that validation in turn doesn't work.

              For example, if f:validateLongRange is applied to a component and its "minimum" and "maximum" properties are not restored correctly during RESTORE VIEW, the validator does nothing.

              Further note that trinidad-impl-1.2.1.jar contains a faces-config.xml in META-INF, which replaces the standard JSF RI validators with a Trinidad implementation of these validators.


              • 4. Re: Trinidad: Validation still not working
                wschwendt

                workaround to get JSF RI validators to work with Trinidad:

                trinidad-impl-1.2.1.jar contains a faces-config.xml file in its META-INF directory.

                Edit this faces-config.xml file and remove all validator elements in this file.

                Then the standard JSF RI validators are not replaced by a Trinidad implementation, and in turn validations works also with Trinidad components such as tr:inputText.

                However, the Hibernate annotations validator with s:validateAll and constraints placed on the domain model doesn't appear to work yet. I need to test this more thoroughly, for the time being I focused on the standard JSF validators.

                Regards,

                Wolfgang Schwendt

                • 5. Re: Trinidad: Validation still not working
                  pmuir

                  This needs to be reported as an issue with Trinidad, linking to the issue in our JIRA. I haven't got around to this yet, so feel free to add it there. Please post a link for tracking here :)

                  • 6. Re: Trinidad: Validation still not working
                    stephen.friedrich

                    I had some help from the trinidad mailing list and did some more debugging.
                    Ultimately it seems the bug is in facelets. They try to determine a component's JSF version by checking if it subclasses UIComponentBase, which fails for Trinidad (which has its own UIXComponentBase).
                    This makes facelets use JSF 1.1 style ValueBindings instead of 1.2's ValueExpressions, which in turn makes Trinidad ignore the ELContext that Seam passes.

                    I created an issue in facelets' issue tracker:
                    https://facelets.dev.java.net/issues/show_bug.cgi?id=239

                    What could be a better way to check for the version?

                    • 7. Re: Trinidad: Validation still not working
                      pmuir

                      Thank you :) Another way is to check for a method on the FacesContext which only exists in 1.2 e.g. getELContext() (this is much safer).

                      • 8. Re: Trinidad: Validation still not working
                        pmuir

                        I can't comment on issues there, perhaps you could?

                        • 9. Re: Trinidad: Validation still not working
                          stephen.friedrich

                          Hm, to check for the global version of the JSF implementation they already check for existence of Application.getExpressionFactory()

                          That still does not answer the question if a particular component class is JSF 1.1 or 1.2. (Is it really possible at all to run a 1.1 component library on a 1.2 implementation?)
                          Unfortunately UIComponent has default implementations for the new 1.2 methods that try to supply reasonable behaviour, e.g. getValueExpression() instantiates a ValueExpressionValueBindingAdapter.
                          So one cannot check for methods in the component's class.

                          • 10. Re: Trinidad: Validation still not working
                            pmuir

                            Ah. Yes, you can easily run a 1.1 component library on 1.2 (e.g. Trinidad trunk, ajax4jsf). I'm not entirely sure *why* they are checking for UIComponentBase (this certainly isn't a requirement for the component to be a 1.2 component), but I guess its to ensure that 1.1 components have those reasonably behaved implementations of 1.2 methods. Let's see what they say :)