Dimitrios K.
Dimitrios K.

Reputation: 1028

Is there any way to bind a runtime value in @Size?

Is there any way I can do something like:

setValue(@Size(max = Config.getMax()) List<?> aParam);

As far as I remember, the value needs to be provided at compile time. I have a requirement to let customers set the value of this max size.

Can this only be done via a custom validation/constraint?

Upvotes: 1

Views: 132

Answers (2)

frifle
frifle

Reputation: 820

You're right, the constraint parameters need to be specified at compile time. You will need a custom validator.

But I would like to share a solution that is some kind of inbetween and that is quite flexible. You can provide constant EL-expression in your constraints. Therefore your custom constraint and custom validation make use of javax.el-API. For using EL outside of jsp/jsf you find a nice blog entry here.

public class myBean {
    @MySize( max="config.max" )
    private String someData;
}

@Target( {ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = MySizeValidator.class)
@Documented
public @interface MySize {

    String message() default "size is invalid";

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

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

    String max();
}

public class MySizeValidator implements ConstraintValidator<MySize, Object> {
    // See blog entry how to write your own ElContext. Provide a Producer 
    // that binds your referenced beans (e.g. 'config') to the context
    @Inject  
    private ValidationElContext elContext;

    private String maxExpression;

    @Override
    public void initialize(MySize constraintAnnotation) {
        super.initialize();
        this.maxExpression = constraintAnnotation.max();
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        if ( value==null ) return true;
        int max = evalExpression(maxExpression);
        return .... // check size of value and compare.
    }

    protected int evalExpression( String expression ) {
        ExpressionFactory fac = ExpressionFactory.newInstance();
        ValueExpression ve = fac.createValueExpression(elContext, expression, Integer.class);

        return ((Integer)ve.getValue(elContext)).intValue();
    }
}

Upvotes: 0

Hardy
Hardy

Reputation: 19109

As you say, the constraint parameters needs to be specified at compile time. So what you are hinting in your question is not possible.

The way to go is to use XML configuration. The constraint configuration could be configured per customer via a customer specific constraint mapping file. In this case you can leave out the constraint annotations completely or you add reasonable default values in which case in the constraint mapping XML files one would need to set the ignoreAnnotations flag to false.

Upvotes: 1

Related Questions