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
?
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();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With