MWE(minimal working example): https://github.com/alfonz19/validator-fail-mwe
TLDR: only xml-based configuration of validation does not work in multimodule project where annotation to ConstraintViolation
implementation is paired using ServiceLoader. Annotation-based config works always, xml-based does also work when all is put into one module. Please any hints/idea/suggestions what to debug.
Update, famous breakthrough:
if app starts fresh, and first request is served by REST (annotation-based configuration), something missing is probably initialized and all works, including xml-based configuration validation. All good! If app starts fresh, and first request is served via kafka (probably not important) which leads into xml-based configuration logic, something is destroyed(missing initialization finished unsuccessfully) and from that point on nothing works, including rest.
If annotation and implementation is in same module, we can trivially bind them together using:
@Constraint(validatedBy = HasClassTypeValidator.class)
or we can(and must in case of multi-module layout) put there:
@Constraint(validatedBy = {})
and define the pairing in ServiceLoader configuration file. So far all good. But I'd like to add validation to auto-generated sources, where I cannot influence them in any way. Easy! You just specify META-INF/validation.xml
:
<validation-config
xmlns="http://xmlns.jcp.org/xml/ns/validation/configuration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://xmlns.jcp.org/xml/ns/validation/configuration
http://xmlns.jcp.org/xml/ns/validation/configuration/validation-configuration-2.0.xsd"
version="2.0">
<constraint-mapping>/META-INF/validation-constraints.xml</constraint-mapping>
</validation-config>
and related validation-constraints.xml
file:
<constraint-mappings
xmlns="http://xmlns.jcp.org/xml/ns/validation/mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/validation/mapping
http://xmlns.jcp.org/xml/ns/validation/mapping/validation-mapping-2.0.xsd"
version="2.0">
<bean class="Whatever">
<class ignore-annotations="false"/>
<getter name="whatever" ignore-annotations="false">
<constraint annotation="javax.validation.constraints.NotNull"/>
<constraint annotation="whatever.CustomValidation"/>
</getter>
</bean>
</constraint-mappings>
The only problem is, that it kinda does not work. In spring, with it's default autoconfigured Validator via LocalValidatorFactoryBean.
Validation with custom constraints declared via service loader works everywhere if constraint is specified via annotation. This xml-baxed stuff also works, but ONLY for built-in constraints, custom one are not found.
If I put breakpoint into ServiceLoader
, then every call to it WILL discover mine custom validators. If it go through LocalValidatorFactoryBean
initialization, I eventually got into org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper#registerCustomConstraintValidators
, where I can see my ConstraintValidator
s discovered as well! But when it comes to validation itself, they are allegedly not declared. BUT! If I have annotation, ConstraintValidators
, xml declarations, and ServiceLoader
config file in 1 module, it all works! If I take just annotation, ConstraintValidators
to another module, ONLY the xml-based annotation is broken. Location of ServiceLoader
config file is irrelevant. No java 9 modules in action, afaik, but it would be weird, that it would affect just xml config based logic.
QUESTION:
Hibernate Validator internals are exceptionally complex. Can someone advice where to look what could go wrong why ConstraintValidators
are not available even though they were discovered during LocalValidatorFactoryBean
initialization?
It was confirmed as a Hibernate Validator bug.