Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional validations in Spring

I have a form which contain some radio button and check-boxes. Whenever user selects/deselects a radio button or check-box few other input fields are enabled/disabled.
I want to add validation only for fields which are enabled when user submits the form. Fields which are disabled at the time of submission should not be considered for validation.

I don't want to add this in client side validation.Is there any better /easy way to implement conditional validation in Spring 3.0 instead of adding multiple if in validator ?

Thanks!

like image 800
Ajinkya Avatar asked Feb 13 '12 08:02

Ajinkya


2 Answers

If you use JSR 303 Bean validation then you can use validation groups (groups) for this.

Assume you have this user input, containing two sections. The two booleans indicating if the sections are enabled or disabled. (Of course you can use more useful annotations than @NotNull)

public class UserInput {
   boolean sectionAEnabled;
   boolean sectionBEnabled;

   @NotNull(groups=SectionA.class)
   String someSectionAInput;

   @NotNull(groups=SectionA.class)
   String someOtherSectionAInput;

   @NotNull(groups=SectionB.class)
   String someSectionBInput;

   Getter and Setter
}

You need two Interfaces for the groups. They work only as marker.

public interface SectionA{}

public interface SectionB{}

Since Spring 3.1 you can use the Spring @Validated annotation (instead of @Validate) in your controller method to trigger the validation:

@RequestMapping...
public void controllerMethod(
         @Validated({SectionGroupA.class}) UserInput userInput, 
         BindingResult binding, ...){...}

Before Spring 3.1 there was no way to specify the validation group that should been used for validation (because @Validated does not exist and @Validate does not have a group attribute), so you need to start the validation by hand written code: This an an example how to trigger the validation in dependence to witch section is enabled in Spring 3.0.

@RequestMapping...
public void controllerMethod(UserInput userInput,...){

  ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
  Validator validator = factory.getValidator();

  List<Class<?>> groups = new ArrayList<Class<?>>();
  groups.add(javax.validation.groups.Default.class); //Always validate default
  if (userInput.isSectionAEnabled) {
     groups.add(SectionA.class);
  }
  if (userInput.isSectionBEnabled) {
     groups.add(SectionB.class);
  }
  Set<ConstraintViolation<UserInput>> validationResult =
     validator.validate(userInput,  groups.toArray(new Class[0]));

  if(validationResult.isEmpty()) {
     ...
  } else {
     ...
  }
}

(BTW: For the Spring 3.0 solution, it is also possible to let Spring inject the validator:

@Inject javax.validation.Validator validator

<mvc:annotation-driven validator="validator"/>

<bean id="validator"
      class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
       <property name="validationMessageSource" ref="messageSource" />
</bean>

)

like image 125
Ralph Avatar answered Oct 23 '22 07:10

Ralph


When fields are disabled they are transferred to controller as null. I wanted to add a validation which will allow either null i.e disabled field or not blank field i.e. enabled but empty field.
So I created a custom annotation NotBlankOrNull which will allow null and non empty strings also it takes care of blank spaces.
Here is my Annotation

@Documented
@Constraint(validatedBy = { NotBlankOrNullValidator.class })
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
public @interface NotBlankOrNull {
    String message() default "{org.hibernate.validator.constraints.NotBlankOrNull.message}";

    Class<?>[] groups() default { };

    Class<? extends Payload>[] payload() default { };
}

Validator class

public class NotBlankOrNullValidator implements ConstraintValidator<NotBlankOrNull, String> {

    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
        if ( s == null ) {
            return true;
        }
        return s.trim().length() > 0;
    }

    @Override
    public void initialize(NotBlankOrNull constraint) {

    }
} 

I have also updated more details on my site.

like image 30
Ajinkya Avatar answered Oct 23 '22 07:10

Ajinkya