一尘不染

Spring Boot 2 War文件尝试在tomcat 7(el-api 2.2)上加载el-apiv3.0类(NoClassDefFoundError:javax / el / ELManager)

spring-boot

我有一个Spring boot 2 gradle项目,希望将它作为(不可执行的)war文件部署到tomcat 7实例(RHEL)。

NoClassDefFoundError在服务器上向tomcat部署战争时,我收到一条消息:

...
Caused by: org.hibernate.cfg.beanvalidation.IntegrationException: Error activating Bean Validation integration
        at org.hibernate.cfg.beanvalidation.BeanValidationIntegrator.integrate(BeanValidationIntegrator.java:138)
        at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:281)
        at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:462)
        at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:892)
        at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:57)
        at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365)
        at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:390)
        ... 34 more
Caused by: java.lang.NoClassDefFoundError: javax/el/ELManager
        at org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator.buildExpressionFactory(ResourceBundleMessageInterpolator.java:88)
        at org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator.<init>(ResourceBundleMessageInterpolator.java:47)
        at org.hibernate.validator.internal.engine.ConfigurationImpl.getDefaultMessageInterpolator(ConfigurationImpl.java:474)
        at org.hibernate.validator.internal.engine.ConfigurationImpl.getDefaultMessageInterpolatorConfiguredWithClassLoader(ConfigurationImpl.java:650)
        at org.hibernate.validator.internal.engine.ConfigurationImpl.getMessageInterpolator(ConfigurationImpl.java:397)
        at org.hibernate.validator.internal.engine.ValidatorFactoryImpl.<init>(ValidatorFactoryImpl.java:183)
        at org.hibernate.validator.HibernateValidator.buildValidatorFactory(HibernateValidator.java:38)
        at org.hibernate.validator.internal.engine.ConfigurationImpl.buildValidatorFactory(ConfigurationImpl.java:364)
        at javax.validation.Validation.buildDefaultValidatorFactory(Validation.java:103)
        at org.hibernate.cfg.beanvalidation.TypeSafeActivator.getValidatorFactory(TypeSafeActivator.java:501)
        at org.hibernate.cfg.beanvalidation.TypeSafeActivator.activate(TypeSafeActivator.java:84)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.hibernate.cfg.beanvalidation.BeanValidationIntegrator.integrate(BeanValidationIntegrator.java:132)
        ... 40 more

经过检查,我发现hibernatebean验证库javax.el.ElManager在初始化期间未能找到此特定类()。

这里的解决方案建议向运行时添加正确的el-apiv3.0依赖关系,但是我不确定这是一个明智的解决方案,因为el-api v2.2已存在providedRuntime于Tomcat的共享(在gradle本地)库中。ClassLoader如果我有2个版本的相同API,我会担心(这是否合理?)。

不能升级到tomcat 8,因为我们在当前仅支持tomcat 7的RHEL上运行tomcat7。

如何告诉Spring使用javax el-api v2.2?

补充笔记

tomcat.version取决于spring-boot-starter-tomcat时的默认值似乎是8.5.31根据以下gradlew dependencies命令进行的:

+--- org.springframework.boot:spring-boot-starter-tomcat:2.0.2.RELEASE
|    +--- javax.annotation:javax.annotation-api:1.3.2
|    +--- org.apache.tomcat.embed:tomcat-embed-core:8.5.31
|    +--- org.apache.tomcat.embed:tomcat-embed-el:8.5.31
|    \--- org.apache.tomcat.embed:tomcat-embed-websocket:8.5.31

将gradleext['tomcat.version']属性设置为7.0.76(我们服务器的版本)可以正确解决以下依赖关系:

+--- org.springframework.boot:spring-boot-starter-tomcat:2.0.2.RELEASE
|    +--- javax.annotation:javax.annotation-api:1.3.2
|    +--- org.apache.tomcat.embed:tomcat-embed-core:8.5.31 -> 7.0.76
|    +--- org.apache.tomcat.embed:tomcat-embed-el:8.5.31 -> 7.0.76
|    \--- org.apache.tomcat.embed:tomcat-embed-websocket:8.5.31 -> 7.0.76
|         \--- org.apache.tomcat.embed:tomcat-embed-core:7.0.76

但是我仍然碰到这个NoClassDefFoundError。在我看来,Spring无法识别正确的api版本,并继续假设ElManager存在。

感谢您的时间。


阅读 650

收藏
2020-05-30

共1个答案

一尘不染

Spring Boot 2.X仅支持Tomcat> = 8.5.X

在尝试修改默认spring配置的可传递依赖关系(即hibernate-validator)之后,我遇到了有关Spring Boot 2
最低服务器要求的文档: Tomcat 8.5.X
。除此之外,仅支持 3.1+的servlet
API。

我要解决的根本问题(如果我更改了依赖项,无疑会在生产线上产生问题) 是Spring Boot 2不支持Tomcat 7
。我降级的所有传递库都可能破坏其他依赖关系,这需要其更新的功能。

Spring Boot 1.5.X 确实支持Tomcat 7和Servlet 3.0应用服务器。因此,
解决方案是降级到Spring Boot 1.5.X (在撰写本文时,当前版本为1.5.13)。

另外,我将与工作场所的系统团队一起寻求解决方案, 而改为使用嵌入式servlet容器 (即,tomcat 8.5 /
9嵌入式)。对我来说不幸的是,这意味着需要对采用部署机制的现有企业流程进行长时间的讨论。但这不是重点:P

2020-05-30