Spring启动创建keyManagementResource Bean失败缺失ELManager排查
问题现象
项目启动时抛出上下文初始化监听器异常,对应子模块未成功加载,Postman调用接口返回404状态码,完整错误日志如下:
SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'keyManagementResource': Unsatisfied dependency expressed through field 'keyValidatorFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'keyValidatorFactory' defined in class path resource [key-mgmt-context.xml]: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: javax/el/ELManager at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588) at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1257) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:551) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:756) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542) at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:443) at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:325) at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107) at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4939) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5434) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:750) Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'keyValidatorFactory' defined in class path resource [key-mgmt-context.xml]: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: javax/el/ELManager at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1619) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:211) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1134) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1062) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585) ... 24 more Caused by: java.lang.NoClassDefFoundError: javax/el/ELManager at org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator.buildExpressionFactory(ResourceBundleMessageInterpolator.java:171) at org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator.<init>(ResourceBundleMessageInterpolator.java:94) at org.hibernate.validator.internal.engine.AbstractConfigurationImpl.getDefaultMessageInterpolator(AbstractConfigurationImpl.java:573) at org.springframework.validation.beanvalidation.LocalValidatorFactoryBean.afterPropertiesSet(LocalValidatorFactoryBean.java:271) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1677) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1615) ... 34 more Caused by: java.lang.ClassNotFoundException: javax.el.ELManager at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1702) at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1547) ... 40 more Jul 06, 2022 4:48:22 PM org.apache.catalina.core.StandardContext startInternal SEVERE: Error listenerStart Jul 06, 2022 4:48:22 PM org.apache.catalina.core.StandardContext startInternal
项目背景
- 整体项目基于Vert.x框架开发
- 故障出现在单个子模块,启动时抛出上述错误
- 模块启动失败后所有接口无法访问,请求返回404
核心根因
顺着错误栈逐层定位:
- 最底层报错为
java.lang.ClassNotFoundException: javax.el.ELManager,即类路径下找不到ELManager类 - 该类是Hibernate Validator初始化消息插值器时必须依赖的类,缺失直接导致
keyValidatorFactoryBean的初始化方法执行失败 keyValidatorFactory初始化失败进一步导致keyManagementResource的依赖注入失败,最终Spring Web上下文启动中断,整个Web模块未完成加载,这也是接口返回404的直接原因
本质是依赖版本不匹配:javax.el.ELManager是EL 3.0及以上版本才提供的类,当前运行环境的EL包版本低于3.0,或者类路径下缺失对应版本的EL依赖。从日志中的Tomcat类加载器路径判断,当前使用的是Tomcat 7,其默认自带的el-api版本为2.2,本身就不包含ELManager类,是最高发的触发场景。
需要补充的排查信息
- 当前使用的Tomcat具体版本,以及子模块的部署方式(war包部署到外部Tomcat/使用内嵌容器启动)
- 项目中Spring、Hibernate Validator的具体版本号
- 依赖配置文件(pom.xml/build.gradle)中和validation、javax.el相关的依赖片段
- 执行依赖树命令输出的javax.el相关依赖结果:
- Maven项目执行:
mvn dependency:tree -Dincludes=javax.el - Gradle项目执行:
gradle dependencies | grep javax.el
- Maven项目执行:
可直接执行的解决方案
场景1:使用外部Tomcat 7部署(匹配当前日志的类加载器特征)
两种方案二选一即可:
- 方案1(推荐):升级Tomcat版本到8.5及以上,Tomcat 8+默认集成EL 3.0+版本,自带
javax.el.ELManager类,无需调整项目代码即可解决问题 - 方案2:不升级Tomcat,在项目依赖中引入EL 3.0的API和实现,注意设置scope为provided,避免和容器自带包冲突:
<!-- Maven依赖示例 --> <dependency> <groupId>javax.el</groupId> <artifactId>javax.el-api</artifactId> <version>3.0.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.glassfish</groupId> <artifactId>javax.el</artifactId> <version>3.0.0</version> <scope>provided</scope> </dependency>
场景2:存在依赖冲突
如果依赖树排查发现存在多个版本的javax.el依赖,低版本被优先级加载,直接在引入低版本EL的依赖项中添加exclusion排除低版本,统一引入3.0+版本即可。
额外注意
由于项目整体基于Vert.x开发,需要确认故障子模块是否不必要地引入了Spring Web的ContextLoaderListener配置,如果该子模块不需要启动Spring Web上下文,直接移除web.xml中对应的监听器配置和相关Spring依赖,也可以从根源避免该问题。
内容的提问来源于stack exchange,提问作者Sandeep Negi
相关产品推荐
相关产品推荐

