1 2 Previous Next 18 Replies Latest reply on Mar 3, 2006 10:07 AM by gnulp

    validation problems

    gnulp

      I have created a page with two forms. Both form buttons are calling two actionMethods in the same statefull session bean on the server. The stateful session bean injects two entities with the @In and @Valid statement for childbeanvalidation.

      Here I try to reduce my case for simplicity ...

      @Stateful
      @Name("myController")
      @Interceptors(SeamInterceptor.class)
      public class MyController {
      
       // this entity will be set from form-1
       @In(value="user",create=true)
       @Valid
       protected User user;
      
       // this entity will be set from form-2
       @In(value="address",create=true)
       @Valid
       protected Address address;
      
       // this should handle form one
       public String pressButtonOneHandlingUsers() {
       ... do something ...
       }
      
       // this should handle form two
       public String pressButtonTwoHandlingAddress() {
       ... do something ...
       }
      }


      Now to the problem: If I press button-1 both entities are injected ! The user-entity-properties which are filled from form-1 are set correctly with no errors, but the address-entity-properties beeing set from form-2 complains about validation errors - what is of course true, because form-2 is empty and not used, yet.
      Is there a way to do the validation for a specific entity when a method is called ?

      Thx for help ...

        • 1. Re: validation problems
          gnulp

          sorry - simplified too much - I lost the @IfInvalid-annotations ;-)
          here is the code again ...

          @Stateful
          @Name("myController")
          @Interceptors(SeamInterceptor.class)
          public class MyController {
          
           // this entity will be set from form-1
           @In(value="user",create=true)
           @Valid
           protected User user;
          
           // this entity will be set from form-2
           @In(value="address",create=true)
           @Valid
           protected Address address;
          
           // this should handle form one
           @IfInvalid(outcome=Outcome.REDISPLAY)
           public String pressButtonOneHandlingUsers() {
           ... do something ...
           }
          
           // this should handle form two
           @IfInvalid(outcome=Outcome.REDISPLAY)
           public String pressButtonTwoHandlingAddress() {
           ... do something ...
           }
          }
          


          • 2. Re: validation problems
            patrick_ibg

            You're example won't work, because validation is applied to all the fields marked @Valid.

            You might be able to trick it out by setting the field value to null if you don't want it validated. However, you have to do this *before* the pressButtonXXX methods are invoked by SEAM, which is tricky.

            It's much easier (and better design) to have two controller classes, one for each "button".

            • 3. Re: validation problems
              gnulp

              you are right - sometimes its better and easier to have a controller for each button, but sometimes not !
              What if you want the actions to interact on shared variables ? So you would have to introduce a number of interfaces and classes for a simple interaction of two business-actions ...

              I believe, that for generosity, a framework should offer all possible variations and not force an architect/developer into a specific direction.

              thx for your "tricky" advice - maybe I can find another solution - I will let you know ...

              • 4. Re: validation problems
                sunfire

                Not a solution to your problem but a feature request:
                wouldn't it be nice to add more granularity to the @Valid and @IfInvalid annotations so that you would be able to exactly specify what @Valid annotation should be validated with a call to a specific @IfInvalid annotation.

                Example:

                @Stateful
                @Name("myController")
                @Interceptors(SeamInterceptor.class)
                public class MyController {
                
                 // this entity will be set from form-1
                 @In(value="user",create=true)
                 @Valid(targets={"Objects, "moreObjects"})
                 protected User user;
                
                 // this entity will be set from form-2
                 @In(value="address",create=true)
                 @Valid(targets={"moreObjects"})
                 protected Address address;
                
                 // this should validate user
                 @IfInvalid(validate="Objects",outcome=Outcome.REDISPLAY)
                 public String pressButtonOneHandlingUsers() {
                 ... do something ...
                 }
                
                 // this should validate user and address
                 @IfInvalid(validate="moreObjects",outcome=Outcome.REDISPLAY)
                 public String pressButtonTwoHandlingAddress() {
                 ... do something ...
                 }
                }
                

                I at least would love to see this feature since it opens up a quite flexible way for validation in multiple-step-wizzard like applications. :)

                Cheers, Thorsten

                • 5. Re: validation problems
                  gnulp

                  cheers - great idea - i would also love to have this flexibility ...

                  what you suggest is to setup validation-groups that can individually be triggerd with the @IfInvalid annotation.

                  I had a look at the sources, and what I saw is, that this change would not only be part of seam but also reflect into the ClassValidator-Implementation of hibernate-annotations ... (at least I think so, but I am not an expert in this area !!!)

                  Any ideas/help ???

                  • 6. Re: validation problems
                    patrick_ibg

                    The way I understand it, this can be handled completely within SEAM. The @Valid annotation is specific to the Hibernate validator. However, the @IfInvalid is all SEAM. My variation on the idea is to change @IfInvalid as follows

                    @Stateful
                    @Name("myController")
                    @Interceptors(SeamInterceptor.class)
                    public class MyController {
                    
                     // this entity will be set from form-1
                     @In (value="user",create=true)
                     protected User user;
                    
                     // this entity will be set from form-2
                     @In (value="address",create=true)
                     protected Address address;
                    
                     // this should validate user
                     @IfInvalid (name="user", outcome=Outcome.REDISPLAY)
                     public String pressButtonOneHandlingUsers() {
                     ... do something ...
                     }
                    
                     // this should validate user and address
                     @IfInvalid (name="address", outcome=Outcome.REDISPLAY)
                     public String pressButtonTwoHandlingAddress() {
                     ... do something ...
                     }
                    }
                    


                    IfInvalid could also take a "names" parameter:
                    @IfInvalid (names={"address","user"}, outcome= ...)


                    • 7. Re: validation problems

                      but obviously default to all @Valid annotated fields, when nothing is defined.

                      James

                      • 8. Re: validation problems
                        gnulp

                        yes, looks nice but regarding sources - seam is just using the @IfInvalid annotation to trigger the hibernate-validation. Unfortunatelly all the loops take place in the hibernate-code where all @Valid flags are processed - there our new nice @IfInvalid-syntax is not known ;-)

                        Gavin - you are the king of validations/annotations as I saw you wrote both classes - do you see a simple solution without touching both sources (seam and hibernate-annotation) ?

                        thx for help ...

                        • 9. Re: validation problems
                          gavin.king

                          Emmanuel is now king of validations ;-)

                          I must say I don't love the proposed solution (kinda complex).


                          Is there a better way?

                          • 10. Re: validation problems
                            gnulp

                            any idea is welcome - currently i don't see a simpler solution, but I think functionality like that is needed as the example shows ...

                            consider we have 100 buttons in the frontend - do we really need 100 Controllers in the serverside - just for validation ?

                            As I said - any better idea than this is welcome, because I need a solution. The only thing I don't like is that this influences both libraries ...

                            Maybe I can write a patch deriving from the original ClassValidator - I will have a look - any help is appriciated ...

                            thx

                            • 11. Re: validation problems
                              gnulp

                              well it's done - I made a patch now using jira-135 patch from Marvin van Schalkwyk who implemented a plugabble factory for custom validations ...

                              I tried to derive from hibernates ClassValidator but without success - too many private variables and procedures ...

                              Thus created a SeamClassValidator of my own (nearly a copy of hibernate ClassValidator with small changes ...) and plugged it into Marvins patch (nice work ;-) ...

                              the syntax now is as follows ...

                              @Stateful
                              @Name("myController")
                              @Interceptors(SeamInterceptor.class)
                              public class MyController {
                              
                               // this entity will be set from form-1
                               @In (value="user",create=true)
                               @Valid
                               protected User user;
                              
                               // this entity will be set from form-2
                               @In (value="address",create=true)
                               @Valid
                               protected Address address;
                              
                               /**
                               * this only validates user in contrast to the original implementation
                               * where user and address was validated
                               **/
                               @IfInvalid (validate={"user"}, outcome=Outcome.REDISPLAY)
                               public String pressButtonOneHandlingUsers() {
                               ... do something ...
                               }
                              
                               // this should validate user and address
                               @IfInvalid (validate={"address","user"}, outcome=Outcome.REDISPLAY)
                               public String pressButtonTwoHandlingAddressAndUser() {
                               ... do something ...
                               }
                              
                               /**
                               * this should also validate user and address, because the default
                               * is the same as it was without the patch ...
                               */
                               @IfInvalid (outcome=Outcome.REDISPLAY)
                               public String pressButtonThreeHandlingAddressAndUser() {
                               ... do something ...
                               }
                              }
                              



                              If anybody is interested in the patch I can deliver it - I would suggest to add the patch to jira-135, beause I had to make minor changes to the this patch, too

                              give me a short notice please ...

                              thx


                              • 12. Re: validation problems
                                sunfire

                                I'd be very interested to take a look at it. Is there a download link?

                                Thanks, Thorsten

                                • 13. Re: validation problems
                                  gnulp

                                  ahh - forgot to update the forum - i added the patch to jira-135, give me feedback if the patch itself works ... you need the latest cvs and can then use the @IfInvalid-patch, that also includes the validate-patch ... at least it worked for me ;-)

                                  • 14. Re: validation problems
                                    epbernard

                                    I don't want to put that in Hibernate Validator because it mixes invariant constraints and GUI "partial" validation concerns.

                                    Plus these static definitions does not allow you to do:
                                    Valid a if button 1 is pressed
                                    Valid b if button 2 is pressed
                                    Valid a and b is button 3 is pressed
                                    If you have 1 controller for both that's because they are correlated and my use case will arise at some point.

                                    1 2 Previous Next