Tuesday, April 14, 2009

Spring.NET Short Circuiting Validators - The Finally

I really like what I do, I love the internet and love hearing other's ideas. After posting part 2 of this topic I noticed someone had actually commented on one of my very few posts. Mark Pollack suggested a great interim solution to the problem of easily configuring short circuiting validators. I say interim because the ability to do something like <v:group fastValidate=true> is planned fro Spring 2.0. Mark's solution allows me to preserve the initial rules layout that was presented in part 1. Here it is a again

    1 <objects xmlns="http://www.springframework.net"

    2         xmlns:v="http://www.springframework.net/validation">

    3   <v:group id="UserValidator">

    4     <v:group id="UserNameValidator">

    5       <v:required id="UserNameRequired" test="UserName">

    6         <v:message id="Errors.UserName.Required"  providers="UserNameError"/>

    7       </v:required>

    8 

    9       <v:regex id="UserNameMinmumComplexity" test="UserName">

   10         <v:property name="Expression" value="^.{5,20}$"/>

   11         <v:message id="Errors.UserName.MinimumComplexity" providers="UserNameError"/>

   12       </v:regex>

   13 

   14       <v:validator id="UserNameIsUnique" test="UserName" type="XXX.Infrastructure.Validation.IsUniqueUserNameValidator, XXX.Infrastructure">

   15         <v:property name="UserRepository" ref="UserRepository"/>

   16         <v:message id="Errors.UserName.IsUnique" providers="UserNameError"/>

   17       </v:validator>

   18     </v:group>

   19 

   20   ....

   21   </v:group

   22 

   23  ....

   24 </objects>



His suggestion is to use IObjectPostProcessor to set the FastValidate property. Since I don't want to set the property on every ValidatorGroup I adopted a naming convention for those groups I do desire the behavior and so I can easily identify them in the post processor. For example, In the configuration above I changed UserNameValidator to UserNameFastValidator. The post processor looks like,

    1     public class FastValidatePostProcessor

    2         : IObjectFactoryPostProcessor

    3     {

    4         public void PostProcessObjectFactory(IConfigurableListableObjectFactory factory)

    5         {

    6             string[] validatorGroupNames = factory.GetObjectNamesForType(typeof(ValidatorGroup));

    7             foreach (string validatorGroupName in validatorGroupNames)

    8             {

    9 

   10                 if (validatorGroupName.EndsWith("FastValidate"))

   11                 {

   12                     IObjectDefinition definition = factory.GetObjectDefinition(validatorGroupName);

   13                     definition.PropertyValues.Add("FastValidate", true);

   14                 }

   15             }

   16         }

   17     }



All that is left is to add the object to the configuration file something like

    1 <object type="XXX.Infrastructure.Validation.FastValidatePostProcessor, XXX.Infrastructure"/>



Thanks Mark!

No comments: