Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Register custom ConstraintValidator for existing Constraint

I use bean-validation in my project and I'd like to write a custom validator for an existing constraint annotation.

For example I have a class that represents a date/time named CustomDateTime. In a class that uses this class as for example a date of birth I'd like to annotate the field with @Past:

public class Person
{
    @Past
    private CustomDateTime dateOfBirth;
}

I then create a custom validator by implementing ConstraintValidator<Past, CustomDateTime>. This however doesn't work, since the validation implementation has no knowledge of the custom validator. It then throws: javax.validation.UnexpectedTypeException: No validator could be found for type: com.example.CustomDateTime.

I know that you usually create a separate annotation like this:

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {CustomDateTimePastValidator.class})
public @interface Past
{
    ....
}

But that seems like double code to me ;-)

How can I register the custom validator to be used with @Past?

like image 287
siebz0r Avatar asked Jan 14 '13 14:01

siebz0r


1 Answers

You can define an XML-based constraint mapping which adds your constraint validator for the existing @Past constraint:

<?xml version="1.0" encoding="UTF-8"?>
<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="javax.validation.constraints.Past">
        <validated-by include-existing-validators="true">
            <value>com.acme.CustomDateTimePastValidator</value>
        </validated-by>
    </constraint-definition>
</constraint-mappings>

Then either reference this mapping in your validation.xml:

<?xml version="1.0" encoding="UTF-8"?>
<validation-config
    xmlns="http://jboss.org/xml/ns/javax/validation/configuration"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/configuration">

    <constraint-mapping>/path/to/constraint-mapping.xml</constraint-mapping>
</validation-config>

Or you add it during bootstrapping your validator:

InputStream mappingStream = ...;

Validator validator = Validation
    .byDefaultProvider()
    .configure()
    .addMapping( mappingStream )
    .buildValidatorFactory()
    .getValidator();
like image 66
Gunnar Avatar answered Nov 01 '22 15:11

Gunnar