I try to run Hibernate validator in osgi container.
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>org.apache.servicemix.bundles</groupId>
<artifactId>org.apache.servicemix.bundles.hibernate-validator</artifactId>
<version>5.0.2.Final_1</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.8.1</version>
</dependency>
public class HibernateValidationProviderResolver implements ValidationProviderResolver {
@Override
public List<ValidationProvider<?>> getValidationProviders() {
List<ValidationProvider<?>> list = new ArrayList<>(1);
list.add(new HibernateValidator());
return list;
}
}
Configuration<?> configuration = Validation.byDefaultProvider().providerResolver(
new HibernateValidationProviderResolver()
).configure();
ValidatorFactory validatorFactory = configuration.buildValidatorFactory();
Validator validator = validatorFactory.getValidator();
Set<ConstraintViolation<Group>> constraintViolations = validator.validate(group);
public class Group {
@NotNull
@Size(min=2)
private String title;
}
Try to run, equinox console is okay:
10 RESOLVED org.glassfish.web.javax.el_2.2.4
39 RESOLVED org.apache.servicemix.bundles.hibernate-validator_5.0.2.Final_1
47 RESOLVED javax.validation.api_1.1.0.Final
49 RESOLVED javax.el-api_2.2.4
If I pass Group class instance with title = null
, then validation is okay and constraintViolations contains one violation "not null".
If I pass Group class instance with title = "A"
(one character against minimal length = 2), then it throws an exception
Caused by: javax.el.ELException: Provider com.sun.el.ExpressionFactoryImpl not found
Caused by: java.lang.ClassNotFoundException: com.sun.el.ExpressionFactoryImpl
It 100% caused by osgi, but how I should setup hibernate-validator in osgi? All articles what I can found describes creating of HibernateValidationProviderResolver
and that's all.
UPDATE 1
Maven: javax.el:javax.el-api:2.2.4
Export-Package: javax.el;version="2.2.4"
Import-Package: javax.el;version="2.2.4"
Maven: org.glassfish.web:javax.el:2.2.4 MANIFEST.MF
Export-Package: com.sun.el;uses:="javax.el";version="2.2.4"
Private-Package: com.sun.el.lang;version="2.2.4",com.sun.el.parser;version="2.2.4",com.sun.el.util;version="2.2.4"
Import-Package: com.sun.el;version="2.2.4",javax.el;version="2.2"
Maven: org.apache.servicemix.bundles:org.apache.servicemix.bundles.hibernate-validator:5.0.2.Final_1
Implementation-Version: 5.0.2.Final
Import-Package: javax.el,javax.persistence;resolution:=optional, ...
Export-Package: org.hibernate.validator.internal.engine.messageinterpola
tion.el;uses:="javax.el,javax.validation,org.hibernate.validator.intern
al.engine.messageinterpolation";version="5.0.2.Final",org.hibernate.val
idator.internal.engine.messageinterpolation;uses:="javax.validation.met
adata,org.hibernate.validator.internal.engine.messageinterpolation.el,j
avax.el,javax.validation,org.hibernate.validator.internal.util.logging"
;version="5.0.2.Final", ...
Any version for import in hibernate bundle, 2.2.4 in export of el-api and el-impl and el-impl imports el-api as 2.2, not a 2.2.4. All bundles are resolved.
Update 2
Decision 1
my implementation of @hwellmann's idea. @hwellmann, is it correct?
public void createGroup(Group group) {
ClassLoader prevClassLoader = Thread.currentThread().getContextClassLoader();
try {
ClassLoader[] classLoaders = new ClassLoader[] {
prevClassLoader,
ExpressionFactoryImpl.class.getClassLoader()
};
// build composite classloader
Thread.currentThread().setContextClassLoader(compositeClassLoader);
Set<ConstraintViolation<Group>> constraintViolations = validator.validate(group);
} finally {
Thread.currentThread().setContextClassLoader(prevClassLoader);
}
}
It works but looks strange. And change TCCL on each validation processing looks as some overhead.
Decision 2
The error has gone when I add my own message attribute to each validation annotation, for example for Group:
public class Group {
@NotNull
@Size(min=2, message="field.too_short")
private String title;
}
It seems in this case hibernate interpolator is not started so ExpressionFactoryImpl
is not retrieved from TCCL (previously we read min=2 value, now we don't). If it is okay for us, this decision is simplest.
I will investigate this area futhermore and share my observations there.