WebSphere7迁移至8.5.5.18时JSF1.2+Seam2.0.2报NullPointerException求助
WebSphere 8.5.5.18迁移Seam 2.0.2组件启动NPE问题排查与解决
问题概述
将原WebSphere 7上的JSF 1.2 + Seam 2.0.2应用迁移至WebSphere 8.5.5.18(沿用SunRI 1.2配置)后,启动阶段出现以下异常:
- 带有
@Startup、@Name("myComponentName")、@Scope(ScopeType.APPLICATION)注解的组件抛出org.jboss.seam.InstantiationException,根源为代理类com.test.MyComponentName_$$_javassist_1.init处的NullPointerException - 会话作用域下调用
ConversationIdGenerator时也触发同类NPE - 给组件添加
@BypassInterceptors注解后可正常运行,推测问题出在Javassist代理实例化环节
已尝试无效方案
- 引入WebSphere 7的
javassist.jar - 配置隔离类加载器,调整
applicationClassLoadingMode为PARENT_FIRST/PARENT_LAST - 对比WebSphere 7与8.5.5生成的Javassist类文件,未发现差异
- 将Seam框架库复制到应用
lib目录 - 开启
-Dibm.cl.verbose类加载日志排查
根因分析
- 类加载冲突:WebSphere 8.5.5自带的Javassist版本与Seam 2.0.2依赖的版本不兼容,类加载器优先加载容器自带的类,导致代理生成逻辑异常
- 上下文初始化时序差异:WebSphere 8.5.5的Servlet容器启动时序与WebSphere 7不同,Seam的
@Startup组件在Seam上下文未完全初始化时就触发实例化,代理创建时无法获取必要的上下文对象 - 拦截器链上下文缺失:WebSphere 8.5.5的安全或容器拦截器在Seam代理实例化时干扰了上下文传递,导致
getProxyFactory().newInstance()调用时依赖对象为空
解决方案
1. 强制隔离Javassist类加载
- 将与Seam 2.0.2兼容的Javassist包(推荐
javassist-3.9.0.GA,Seam 2.0.2默认依赖版本)放入应用WEB-INF/lib - 在WebSphere管理控制台中配置应用类加载器:
- 设置
applicationClassLoadingMode为PARENT_LAST - 添加类加载过滤规则,排除容器自带的Javassist类:在“类加载器”设置中新增“过滤类”,输入
com.javassist.*,选择“排除”
- 设置
2. 调整Seam组件启动时机
- 移除问题组件的
@Startup注解,改用ServletContextListener手动初始化:public class SeamComponentInitializer implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { // 通过Seam上下文获取组件并初始化 Component.getInstance("myComponentName", true); } @Override public void contextDestroyed(ServletContextEvent sce) {} } - 在
web.xml中注册该监听器,确保在Seam的SeamListener之后执行:<listener> <listener-class>org.jboss.seam.servlet.SeamListener</listener-class> </listener> <listener> <listener-class>com.test.SeamComponentInitializer</listener-class> </listener>
3. 修复Seam上下文JNDI绑定
- 在
components.xml中添加Seam初始化配置,适配WebSphere 8.5.5的JNDI规则:<core:init jndi-pattern="java:comp/env/#{ejbName}" /> <core:manager conversation-id-parameter="cid" parent-conversation-id-parameter="pid" /> - 确保WebSphere应用的JNDI名称空间配置正确,允许Seam绑定上下文对象
4. 禁用WebSphere动态代理干扰
- 在WebSphere管理控制台中进入应用的“类加载器”设置,勾选“禁用动态类加载”选项
- 或调整容器代理生成参数:在“服务器”->“应用程序服务器”->“你的服务器”->“容器设置”->“应用程序容器设置”->“Web容器设置”->“Web容器”中,修改“代理生成”相关配置,避免与Seam的Javassist代理冲突
5. 升级Seam版本(推荐长期方案)
- 将Seam版本升级至
2.2.0.GA,该版本对WebSphere 8.x有官方兼容支持,修复了大量类加载与代理相关的兼容性问题 - 升级时需注意:
- 调整
components.xml中的命名空间(从http://jboss.com/products/seam/core改为http://jboss.org/schema/seam/core) - 替换Seam相关依赖包,移除旧版本冲突类
- 调整
内容的提问来源于stack exchange,提问作者Aarav Olson
相关产品推荐
相关产品推荐

