users@jersey.java.net

[Jersey] Bean Validation constraint mapping

From: Doyle, Brendan <brendan.doyle_at_ie.verizon.com>
Date: Tue, 10 Jun 2014 15:10:34 +0100

Hi

I am using Bean Validation in my Jersey project and I have my own custom validation Constraints and ConstraintValidators. As I do not want to tie the validation constraint to the constraint validator I specify the mapping in an xml file rather than in the constraint annotation.

So instead of

@Constraint(validatedBy = MyCustomValidator.class)
@Target( {METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface MyCustomConstraint {


I have

@Constraint(validatedBy = {})
@Target( {METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface MyCustomConstraint {


And an xml constraint mapping file

<constraint-mappings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                     xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping validation-mapping-1.0.xsd"
                     xmlns="http://jboss.org/xml/ns/javax/validation/mapping">

    <constraint-definition annotation="com.acme.MyCustomConstraint">
        <validated-by >
            <value>com.acme.MyCustomValidator</value>
        </validated-by>
    </constraint-definition>

To customise the Jersey Validation configuration to load the mapping I use a ValidationConfigurationContextResolver


public class ValidationConfigurationContextResolver implements ContextResolver<ValidationConfig> {
    @Context
    private ResourceContext resourceContext;

    @Override
    public ValidationConfig getContext(Class<?> arg0) {
        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("myconstraintmapping.xml");
        ValidatorFactory factory = Validation.byDefaultProvider().configure()
                .addMapping(resourceAsStream)
                .buildValidatorFactory();
        ValidationConfig config = new ValidationConfig();
        ConstraintValidatorFactory constraintValidatorFactory = factory.getConstraintValidatorFactory();
        return config.constraintValidatorFactory(constraintValidatorFactory);
    }
}


Which I register

public class Application extends ResourceConfig {

    public Application() {
        register(ValidationConfigurationContextResolver.class);

Then my JAX-RS resource methods use @Valid to trigger the validator ( shown below on the interface )

    @PUT()
    @Path("{id}/mypath")
    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    MyEntity updateStatusById(@PathParam("id") long id, @Valid MyEntity update);


However the validator is never called.

It is called if I change my constraint to use @Constraint(validatedBy = MyCustomValidator.class) or explicitly call a validator configured with the xml mappings.


                ValidatorFactory factory = Validation.byDefaultProvider().configure().addMapping(this.getClass().getClassLoader()
                .getResourceAsStream("myconstraintmapping.xml")).buildValidatorFactory();
                Validator validator = factory.getValidator();
                Set<ConstraintViolation<C>> violations = validator.validate(update);


Is my ValidationConfigurationContextResolver implementation incorrect ? Or is specifying the constraint to Validator mapping in xml not supported ?

Thanks in advance

Brendan Doyle




Verizon Ireland Limited - registered in Ireland - registered number 224334 - registered office at Erne Street, Dublin 2, Ireland - VAT number 8224334A