Java Bean Validation 2.0 Hibernate Validator - Executable JAR with external XML-Configuration

681 views Asked by At

Context

I'm developing a stand-alone application that reads input-data from a csv-file.
Until now I've used a self-written class to perform input validation, and the method used for validating a single record from the input file was triggered immediately after reading a single line. The method was called in the methode for reading the csv-file.

Since the input data will be retrieved by using RESTful Web Services in the future and we'll forfeit using csv-files, I want to decouple the validation from the csv-reading.

I stumpled upon Bean Validation (JSR 380) and used Hibernate Validator to refactor the validation procedure.

I tried both, adding validation-annotations directly to the Bean class, and using a validation.xml file for configuration.
Both ways work when I run the application from Eclipse.

Problem

The application will be deployed as an executable JAR.
I would like to keep the option to change the validation constraints without the need to repack and redeploy the JAR.
So I'm trying to figure out, if there is a way to exclude the validation.xml (+ further configuration files) from the JAR and put it in some directory "close" to the JAR.
Something like this:

myApp/
 |-- JAR
 |-- conf/
     |-- ValidationMessages.properties
     |-- META-INF/
          |-- validation.xml
          |-- validation/
               |-- constraints-myBean.xml

What I tried

  1. Placing the META-INF/-folder in the same directory as the JAR

    The JAR runs, but the validation doesn't work.

  2. Referencing the absolute path to constraints-myBean.xml in validation.xml, specifically changing
    <constraint-mapping>META-INF/validation/constraints-pbpRecord.xml</constraint-mapping>
    to
    <constraint-mapping>C:/path/to/myApp/META-INF/validation/constraints-pbpRecord.xml</constraint-mapping>
    and including validation.xml in my JAR.

    A ValidationException cancels the execution:

Exception in thread "main" javax.validation.ValidationException: HV000096: Unable to open input stream for mapping file C:/Users/wsteffler/Desktop/pbp_import_tool/pbp_orgunit_import/META-INF/validation/constraints-pbpRecord.xml.  
        at org.hibernate.validator.internal.xml.config.ValidationBootstrapParameters.setMappingStreams(ValidationBootstrapParameters.java:291)
        at org.hibernate.validator.internal.xml.config.ValidationBootstrapParameters.<init>(ValidationBootstrapParameters.java:67)
        at org.hibernate.validator.internal.engine.AbstractConfigurationImpl.parseValidationXml(AbstractConfigurationImpl.java:595)
        at org.hibernate.validator.internal.engine.AbstractConfigurationImpl.buildValidatorFactory(AbstractConfigurationImpl.java:376)
        at javax.validation.Validation.buildDefaultValidatorFactory(Validation.java:103)
        at de.uniwuppertal.hisinone.orgunitimport.pbp.Main.main(Main.java:220)
  1. Adding the parent-directory of META-INF/ to the classpath (with -classpath argument)

    The JAR runs, but the validation doesn't work.

I've read the Bean Validation specification (6.5. Bootstrapping & 9. XML deployment descriptor) and the Hibernate Validator 6.1.0 Reference Guide (8. Configuring via XML), especially looking for solutions in the chapters in parentheses, and searched on StackOverflow and Google for solutions. Unfortunately I haven't found anything that would lead me to a solution so far.

Is it even possible to achieve bootstrapping an external validation.xml when executing a JAR?
If it is, how can I achieve this?

If you'll need more information or parts from my code, I'll update the question with the required information.

1

There are 1 answers

1
Guillaume Smet On BEST ANSWER

Hibernate Validator clearly doesn't support that. For sure the validation.xml needs to be in the jar. We could maybe support having the file: prefix to point to external constraint mappings. I would accept a patch if you were willing to work on that.

Not sure about the resource bundles though so that would be an half baked solution for you.

I wonder if you could just pass a carefully crafted class loader that can load resources from your external location (and delegate everything else to the standard class loader) and use externalClassLoader(ClassLoader) to pass it to HV when configuring the ValidatorFactory.