简体   繁体   English

在 osgi-container 中找不到 hibernate-validator 的 El 实现

[英]El implementation is not found for hibernate-validator in osgi-container

I try to run Hibernate validator in osgi container.我尝试在 osgi 容器中运行 Hibernate 验证器。

<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:尝试运行,equinox控制台没问题:

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".如果我通过title = null Group 类实例,则验证没问题,并且constraintViolations 包含一个“非空”违规。 If I pass Group class instance with title = "A" (one character against minimal length = 2), then it throws an exception如果我通过title = "A" (一个字符与最小长度 = 2)的 Group 类实例,则它会引发异常

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?它 100% 是由 osgi 引起的,但是我应该如何在 osgi 中设置 hibernate-validator 呢? All articles what I can found describes creating of HibernateValidationProviderResolver and that's all.我能找到的所有文章都描述了HibernateValidationProviderResolver创建,仅此HibernateValidationProviderResolver

UPDATE 1更新 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.在休眠包中导入的任何版本,el-api 和 el-impl 导出中的 2.2.4 和 el-impl 将 el-api 导入为 2.2,而不是 2.2.4。 All bundles are resolved.所有捆绑包都已解决。

Update 2更新 2

Decision 1决定 1

my implementation of @hwellmann's idea.我对@hwellmann 想法的实现。 @hwellmann, is it correct? @hwellmann,正确吗?

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.并且在每个验证处理上更改 TCCL 看起来是一些开销。

Decision 2决定 2

The error has gone when I add my own message attribute to each validation annotation, for example for Group:当我将自己的消息属性添加到每个验证注释时,错误就消失了,例如对于 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).看来,在这种情况下,休眠插值没有开始,所以ExpressionFactoryImpl不是从TCCL检索(以前我们读分钟= 2的值,现在却没有了)。 If it is okay for us, this decision is simplest.如果对我们来说没问题,这个决定是最简单的。 I will investigate this area futhermore and share my observations there.我将进一步调查这个领域,并在那里分享我的观察。

There is a related issue in JBoss Fuse: https://access.redhat.com/solutions/1479723 JBoss Fuse中存在一个相关问题: https//access.redhat.com/solutions/1479723

They recommend a downgrade to 4.3.1.Final : 他们建议降级到4.3.1.Final

<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-validator</artifactId>
   <version>4.3.1.Final</version>
</dependency>

The full stack trace might give some more insight than just the exception messages. 完整堆栈跟踪可能提供比仅仅异常消息更多的洞察力。

My guess is that you're seeing the results of a failed service lookup via META-INF/service/javax.el.ExpressionFactory . 我的猜测是你通过META-INF/service/javax.el.ExpressionFactory看到了服务查找失败的结果。 The bundle that's doing the lookup apparently can't see com.sun.el . 正在进行查找的包显然无法看到com.sun.el

Importing this package into your application bundle and setting the thread context classloader to your bundle classloader might help. 将此包导入应用程序包并将线程上下文类加载器设置为bundle类加载器可能会有所帮助。

I had a similar issue with Hibernate 5.2.5 and Jetty 9.x. 我在Hibernate 5.2.5和Jetty 9.x上遇到了类似的问题。 Basically, it looked like Hibernate didn't check if there was already an EL implementation on the classpath and tried to use javax.el-api instead of Jetty 9's apache-el. 基本上,看起来Hibernate没有检查类路径上是否已经有EL实现,并尝试使用javax.el-api而不是Jetty 9的apache-el。 An upgrade to Hibernate 5.2.10 solved the issue for me. 升级到Hibernate 5.2.10为我解决了这个问题。 No conflicting el-api on the classpath any more. 不再在类路径上有冲突的el-api。

Background背景

I use hibernate validator version 5.4.3.Final.我使用休眠验证器版本 5.4.3.Final。

Starting from 5.3.1.Final , it mentions that ExpressionFactoryImpl is a hard requirement.5.3.1.Final开始,它提到 ExpressionFactoryImpl 是一个硬性要求。

there is OSGi issue in 5.3.1.Final,issue is ClassLoader issues in modularized environments . 5.3.1.Final 中存在 OSGi 问题,问题是模块化环境中的 ClassLoader 问题 It has been fixed in 5.3.3.Final.它已在 5.3.3.Final 中修复。 Ticket number is HV-1155票号是HV-1155

Fix使固定

Based on the above information, there is no need to use Update 2 -> Decision 1 .根据以上信息,无需使用Update 2 -> Decision 1 I found out that you could simply change the code posted by OP from我发现您可以简单地将 OP 发布的代码从

Configuration<?> configuration = Validation.byDefaultProvider().providerResolver(
    new HibernateValidationProviderResolver()
).configure();

to

Configuration<?> configuration = Validation.byProvider(HibernateValidator.class).providerResolver(
    new HibernateValidationProviderResolver()
).externalClassLoader(getClass().getClassLoader()).configure();

11.15. 11.15. Customizing class-loading mentions this trick. 自定义类加载提到了这个技巧。

In addition, if you are using hibernate validator version 6.0.0.CR3 above, you don't need to apply the trick above.此外,如果您使用上面的 hibernate 验证器版本 6.0.0.CR3,则不需要应用上面的技巧。 HV-1426 covers it. HV-1426涵盖了它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM