【发布时间】:2018-11-03 02:31:36
【问题描述】:
我有一个 Spring boot 2 gradle 项目,我希望将其作为(不可执行的)war 文件部署到 tomcat 7 实例 (RHEL)。
在将战争部署到服务器上的 tomcat 时,我收到了 NoClassDefFoundError:
...
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
经过检查,我发现休眠 bean 验证库在初始化期间未能找到这个特定的类 (javax.el.ElManager)。
解决方案here 建议将正确的 el-api v3.0 依赖项添加到运行时,但我不确定这是一个明智的解决方案,因为 el-api v2.2 已经存在于共享 (providedRuntime Tomcat 中的 gradle 白话)库。如果我有相同 API 的 2 个版本,我会担心 ClassLoader 问题(这是一个合理的担忧吗?)。
升级到 tomcat 8 是不行的,因为我们在 RHEL 上运行 tomcat7,而目前只支持 tomcat 7。
如何让 Spring 使用 javax el-api v2.2?
补充说明
根据gradlew dependencies命令,依赖spring-boot-starter-tomcat时默认的tomcat.version似乎是8.5.31:
+--- 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
据我从another post 了解到,将 gradle ext['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。
感谢您的宝贵时间。
【问题讨论】:
标签: spring-boot gradle tomcat7