Question

Let's say I have a Model Bean "Vendor" with the mandatory property "name" and an optional property "email".

class Vendor {

    @Email
    private String email;

    @NotNull
    private String name;

}

@Email allows Null!

I want to use hibernate-validation in my @Controller and in my flows as well. I have in both scenarios the problem that a posted form with an empty field for email binds with "" and not NULL.

StringTrimmerEditor seems to solve my problem by converting "" into NULL. For my @Controller I found SPR-7077 which suggests implementing StringTrimmerEditor globally with @ControllerAdvice. But this doesn't work for my flows.

How do I achieve that globally empty Strings ("") are converted into NULL for JSR-303 validation in spring webflow?

Was it helpful?

Solution

I seem to have found a configuration which supports Null values for empty Strings. For my @Controller I stick with the StringTrimmerEditor in my @ControllerAdvice. Nothing new here.

For SWF ConversionService seems to do the trick: First I create a Converter which converts "" into Null:

public class StringToNullConverter implements Converter<String, String> {

    @Override
    public String convert(String source) {
        if (StringUtils.isEmpty(source)) {
            return null;

        }
        return source;
    }

}

Now I have to register this in Spring:

import org.springframework.core.convert.*;

@Configuration
public class SpringConfiguration {

    @Bean public ConversionService conversionService() {
        DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();        
        conversionService.addConverter(new StringToNullConverter());
        return conversionService;
    }

}

Until now nothing new happens and we're talking about the org.springframework.core.convert package. Now comes the SWF glue into the org.springframework.binding.convert package:

import org.springframework.binding.convert.*;

@Bean public ConversionService flowConversionService(org.springframework.core.convert.ConversionService conversionService) {
    DefaultConversionService service = new DefaultConversionService(conversionService);
    return service;
}

Wire this into SWF with <webflow:flow-builder-services [..] conversion-service="flowConversionService" />.

This looks a bit too much, but it does the job. I'm sure there must be a better way, as I have two different implementations (StringTrimmerEditor and StringToNullConverter) to achieve the same thing. For me it looks like ConversionService seems to be the one and only way to go. But I didn't figure out how to get it done for a Spring @Controller.

OTHER TIPS

you can create annotation contains @ConstraintComposition if you want to using optional field. For example:

import org.hibernate.validator.constraints.ConstraintComposition;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotBlank;
@ConstraintComposition
@Target({METHOD, FIELD, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = {})
@Documented

@NotBlank
@Length(min = 1, max = 5)
@Pattern(regexp = "[A-Z]*")
public @interface SpecialField {
    String message() default "{}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

and

@ConstraintComposition(OR)
@Target({METHOD, FIELD, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = {})
@Documented

@Null
@SpecialField
public @interface OptionalSpecialField {

    String message() default "{}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

and after that mark optional filed that:

class NewUser {

    @OptionalSpecialField
    private String firstName;

    @SpecialField
    private String lastName;

    @Min(18)
    private Integer age;
}

First name is not required but if is not null then have to be not blank, match pattern, etc.

All example is on here: https://github.com/lukaszguz/optional-field-validation/tree/master/src/main/java/pl/guz/domain/validation

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top