8 Replies Latest reply on Feb 28, 2011 4:59 AM by ilya_shaikovsky

    RF 4 Object Validation calling validation method twice.

    flaviohenrique

      Today I made another battery of tests agains RF 4.0 M6 Object Validation, my favourite feature. I came back to the example that Ilya post here: http://in.relation.to/Bloggers/Ilya

       

      The example works fine, but I detected that the method isPasswordsEquals() is called twice every time the object need to be validated. To see this, put a System.out.println("this is a problem?") inside de method to see by yourselves.

       

      Despite de clonning process, I didn´t expected this. Can anyone clarify this to me? Maybe I am missing some tecnical stuff. I am worried about this, because there are some use cases that we need to access some expensive resources during validation.

        • 1. RF 4 Object Validation calling validation method twice.
          flaviohenrique

          I also made a test with CDI beans, and this also happens.

          • 2. RF 4 Object Validation calling validation method twice.
            mp911de

            Hi Flávio,

            do you use your Property passwordsEquals also as Value/Condition? Check the Stack-Trace to find it out or just post both Stack-Traces.

             

            Best regards,

            Mark

            • 3. RF 4 Object Validation calling validation method twice.
              flaviohenrique

              Mark,

               

              I followed and debuged the example that Ilya post here http://in.relation.to/Bloggers/Ilya

              In that example, isPasswordsEquals() is not called from the page, it´s called from Object Validator (Bean Validator) into the cloned object created by the framework. I know that you can call this method throught EL using passwordsEquals, but it´s not the case. I am trying to solve this puzlze (twice callling the method) since my first post, but I am tired now and must take a rest. My hypotesis is that Object Validation is calling isPasswordsEquals() also in the original bean, not the cloned one, but I can´t figure out how to confirm this (maybe I am sleepy). I really liked this feature, then, I need to prove to myself that it´s working properly.

              • 4. RF 4 Object Validation calling validation method twice.
                mp911de

                Hi Flávio,

                you can find it out in two ways:

                 

                1. if you have a native hashCode()-Method (not overwritten by your code), you can log it to Sysout
                2. If you use Eclipse, just look in the Variables-View, there is an id-Information. Each Object-Instance get's an unique id, so you can see, if id is the same or different, on which object the Method is called
                • 5. RF 4 Object Validation calling validation method twice.
                  flaviohenrique

                  Mark,

                   

                  The object is the same during validation. It seems that in this particulary case there isn´t any clonable object. This drivers me nuts, because:

                   

                  1- the object seems to be the same (the model is also updated during a validation failure). As I understood, the creation of the cloned object is to avoid the updade during the update model values phase in the original bean, the, RF 4 creates a copy of the bean to update this model and after the test discarts it. So, So, if any problem occurs during validation, the original bean won´t have it´s model updated.

                  2- the first behavior that I described here: RF 4.0 is calling twice the annotated method isPasswordsEquals().

                   

                  I also override the clone method

                   

                  public UserBean clone(){

                                      System.out.println("calling clone method");

                                      UserBean myClonedObject = new UserBean();

                                      myClonedObject.setConfirm(this.confirm);

                                      myClonedObject.setPassword(this.password);

                                      return myClonedObject;

                            }

                   

                  But it´s never called!

                   

                  I will wait a little more before posting a jira issue for this.

                  • 6. Re: RF 4 Object Validation calling validation method twice.
                    flaviohenrique

                    I forget to implements Clonable: public class UserBean implements Cloneable{

                     

                    Now, RF 4.0 is calling UserBean.clone() method. The validation working, no model update during a failed validation (yeah!), but I am allways getting an exception, and this time, RF 4 calls  isPasswordsEquals()  ONE time on the original bean, and TWO times in the clonable bean!

                     

                    Here is the exception  (even with the exception, the validation works).

                     

                    javax.validation.ValidationException: Call to TraversableResolver.isReachable() threw an exception

                              at org.hibernate.validator.engine.ValidatorImpl.isValidationRequired(ValidatorImpl.java:766)

                              at org.hibernate.validator.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:324)

                              at org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForRedefinedDefaultGroup(ValidatorImpl.java:273)

                              at org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:256)

                              at org.hibernate.validator.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:210)

                              at org.hibernate.validator.engine.ValidatorImpl.validate(ValidatorImpl.java:119)

                              at org.richfaces.validator.BeanValidatorServiceImpl.validateObject(BeanValidatorServiceImpl.java:447)

                              at org.richfaces.validator.FacesBeanValidator.validateGraph(FacesBeanValidator.java:160)

                              at org.richfaces.component.AbstractGraphValidator.validateObject(AbstractGraphValidator.java:214)

                              at org.richfaces.component.AbstractGraphValidator.processValidators(AbstractGraphValidator.java:197)

                              at javax.faces.component.UIForm.processValidators(UIForm.java:244)

                              at org.richfaces.context.PartialViewExecuteVisitCallback.visit(PartialViewExecuteVisitCallback.java:57)

                              at org.richfaces.context.BaseExtendedVisitContext.invokeVisitCallback(BaseExtendedVisitContext.java:337)

                              at javax.faces.component.UIForm.visitTree(UIForm.java:345)

                              at javax.faces.component.UIComponent.visitTree(UIComponent.java:1496)

                              at javax.faces.component.UIComponent.visitTree(UIComponent.java:1496)

                              at org.richfaces.context.ExtendedPartialViewContextImpl.executeComponents(ExtendedPartialViewContextImpl.java:249)

                              at org.richfaces.context.ExtendedPartialViewContextImpl.processPartialExecutePhase(ExtendedPartialViewContextImpl.java:229)

                              at org.richfaces.context.ExtendedPartialViewContextImpl.processPartial(ExtendedPartialViewContextImpl.java:208)

                              at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1163)

                              at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:76)

                              at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)

                              at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)

                              at javax.faces.webapp.FacesServlet.service(FacesServlet.java:312)

                              at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:306)

                              at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)

                              at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)

                              at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)

                              at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)

                              at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)

                              at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:541)

                              at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)

                              at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:383)

                              at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:243)

                              at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)

                              at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:288)

                              at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)

                              at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

                              at java.lang.Thread.run(Unknown Source)

                    Caused by: javax.persistence.PersistenceException: Unable to access field or method: class teste.UserBean#passwordsEquals

                              at org.hibernate.ejb.util.PersistenceUtilHelper.get(PersistenceUtilHelper.java:108)

                              at org.hibernate.ejb.util.PersistenceUtilHelper.isLoadedWithReference(PersistenceUtilHelper.java:83)

                              at org.hibernate.ejb.HibernatePersistence$1.isLoadedWithReference(HibernatePersistence.java:93)

                              at javax.persistence.Persistence$1.isLoaded(Persistence.java:83)

                              at org.hibernate.validator.engine.resolver.JPATraversableResolver.isReachable(JPATraversableResolver.java:62)

                              at org.hibernate.validator.engine.resolver.DefaultTraversableResolver.isReachable(DefaultTraversableResolver.java:94)

                              at org.hibernate.validator.engine.resolver.SingleThreadCachedTraversableResolver.isReachable(SingleThreadCachedTraversableResolver.java:47)

                              at org.hibernate.validator.engine.ValidatorImpl.isValidationRequired(ValidatorImpl.java:757)

                              ... 38 more

                    Caused by: java.lang.reflect.InvocationTargetException

                              at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

                              at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)

                              at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)

                              at java.lang.reflect.Method.invoke(Unknown Source)

                              at org.hibernate.ejb.util.PersistenceUtilHelper.get(PersistenceUtilHelper.java:96)

                              ... 45 more

                    Caused by: java.lang.NullPointerException

                              at teste.UserBean.isPasswordsEquals(UserBean.java:30)

                              ... 50 more

                     

                    Problem summary

                    1 - When ObjectValidation (rich:graphValidator) works in the old way, it calls twice isPasswordsEquals(), but the validation happens without problem;

                    2- When Objectvalidaion (rich:graphValidator) works with a clonable Object in new fashion way, it calls isPasswordsEquals() one time in the original object and to times in the cloned object. It´s also fire an exception, but this exception don´t seems to affect the validation.

                     

                    ps: I made a test with CDI beans, but I can´t figure out how I can create a clonable CDI bean in the clone() method. I can´t go with UserBean userBean = new UseBean(), because the object won´t be managed by the container. Reading CDI specs now...

                    • 7. RF 4 Object Validation calling validation method twice.
                      mp911de

                      umm...you noticed, that your Root-Exception is NullPointer, didn't you?

                      • 8. RF 4 Object Validation calling validation method twice.
                        ilya_shaikovsky

                        about NPE - please initialize the password and confirm fields. Them seems both null and isPasswordsEquals uses password.equals(confirm) which causes that. It's pretty strange but when I checked that demo (and now also) the exception does'n thrown for me but according to code - seems really could be there and sorry for that my mistake. (probably different JSF impl's or settings and in my case them getting set to "" instad of null).

                         

                        About the numerous calls to the method - reviewing now with team and will update the thread with the results.