views:

23

answers:

2

I'm new to Spring, and I'm curious as to how to approach validating form input against a data source. I'm using Spring 3.0.3, by the way. So lets say I have the following form:

public class MyForm {

     private String format;

     public String getFormat() {
         return format;
     }

     public void setFormat( value:String ) {
         format = value;
     }
}

Now lets say the format property is a string representation of a file format: "jpg", "png", "gif", "bmp", etc. Naturally I thought to write a validator for the form. It looks something like this:

public class MyFormvalidator implements Validator
{
    @Override
    public boolean supports( Class<?> clazz ) {
        return MyForm.class.equals( clazz );
    }

    @Override
    public void validate( Object obj, Errors errors ) {

        MyForm myForm = (MyForm) obj;
        ValidationUtils.rejectIfEmptyOrWhitespace( errors, "format", "error.required" );

        if( !myForm.getFormat().equals( "jpg" ) &&
            !myForm.getFormat().equals( "png" ) &&
            .... etc .... ) {
           errors.rejectValue( "format", "error.invalid" );
        }
    }
}

So thats all fine and dandy, but lets say I want to add new supported formats without having to adjust my validator, recompile, and deploy it. Rather than get into database 'n what not, lets keep it simple go with a little XML file that could be modified. It would look something like this:

<?xml version="1.0" encoding="UTF-8"?>
<fileformats>
    <item>jpg</item>
    <item>png</item>
    .... etc ....
</fileformats>

And finally, the real point of all this...what should my approach be to making this data available during the validation of the form input?

+2  A: 

The easiest way to do this is to make the Validator a Spring bean, and put the list of formats in your Spring configuration:

public class MyFormvalidator implements Validator
{
    private List<String> fileFormats;

    public MyFormValidator(List<String> fileFormats) {
        this.fileFormats = fileFormats;
    }

... //the rest of your validator, including checks for fileFormats.contains(myForm.getFormat())

Now, in your Spring configuration, you have

<bean name="myFormValidator" class="something.something.MyFormValidator">
    <constructor-arg>
         <list>
             <value>jpg</value>
             <value>png</value>
             ... etc ...
         </list>
    </constructor-arg>
</bean>
JacobM
Thanks Jacob, I really like this approach. I'm not much of a Java dev yet but this seems to make the most sense to me right now.
Matt W
+1  A: 

Do you consider changes to the application context source changes? You can create a list in your bean definition and inject it right into the validator.

  <beans
      xmlns="http://www.springframework.org/schema/beans"
      xmlns:util="http://www.springframework.org/schema/util"
      xsi:schemaLocation="
          http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
          http://www.springframework.org/schema/util
  http://www.springframework.org/schema/util/spring-util-3.0.xsd"&gt;

  <bean id="myValidator"
  class="MyValidator>
      <property name="acceptedExtensions"/>
          <util:set>
              <value>jpg</value>
              <value>png</value>
          </util:set>
      </property> 
  </bean> 
  </beans>


  public class MyFormvalidator
  implements Validator {
      private Set<String> acceptedExtensions;
      public void setAcceptExtensions(Set<String> extensions) {//etc}

      @Override
      public void validate( Object obj, Errors errors ) {

          MyForm myForm = (MyForm) obj;
          ValidationUtils.rejectIfEmptyOrWhitespace(
              errors, "format", "error.required" );

          if( !acceptedExtensions.contains(myForm.getFormat){
             errors.rejectValue( "format", "error.invalid" );
          }
      }
Affe
And of course if you do consider the application context version controller, you can always put the bean definition in a separate file in a 'config' tree and import it in web.xml
Affe