Read more: 从 Traditional WebSphere Application Server 到 Liberty:解决 EJB 远程事务传播的实战方法当你的 EJB 应用从传统 WebSphere 迁移到 Liberty 时,迁移工具可能会提示:”不支持 EJB 远程接口的事务传播”。这到底意味着什么?是否需要大规模重构?本文为你解答。
背景故事
你有一个运行在 WebSphere Application Server 上的企业应用,使用了 EJB(Enterprise JavaBeans)。现在你想要迁移到更轻量、更现代的 WebSphere Liberty。
你运行了 IBM 的迁移工具(如 Migration Toolkit for Application Binaries 或 Application Modernization Accelerator),工具报告了一个警告:
⚠️ Transaction propagation is not supported for Enterprise JavaBeans (EJB) remote interfaces
这看起来很严重——难道需要重写大量代码吗?
好消息:大多数情况下,你不需要做任何修改。
先搞清楚两个概念
在深入之前,我们需要区分两个经常被混淆的概念:
1. EJB 远程调用 (Remote Call)
指的是一个 EJB 调用位于另一个 JVM 中的 EJB。这是一种通信方式。
flowchart LR
subgraph A[应用服务器 A]
EJB1[EJB1<br/>客户端]
end
subgraph B[应用服务器 B]
EJB2[EJB2<br/>服务端]
end
EJB1 -->|远程调用| EJB22. 事务传播 (Transaction Propagation)
指的是在调用过程中,当前事务上下文是否传递到被调用的 EJB。
flowchart TB
subgraph Prop[有事务传播]
TX1[事务1]
EJB1A[EJB1<br/>开启事务] --> TX1
TX1 --> EJB2A[EJB2<br/>继续同一事务]
end
subgraph NoProp[无事务传播]
TX2[事务1]
EJB1B[EJB1<br/>开启事务] --> TX2
TX2 -.X.- EJB2B[EJB2<br/>创建新事务<br/>或无事务]
endLiberty 的支持情况
✅ 完全支持的场景
| 场景 | Liberty 是否支持 |
|---|---|
| 同一 JVM 内的 EJB 调用 | ✅ 支持 |
不同 JVM 的 EJB 调用,但事务属性为 NotSupported | ✅ 支持 |
不同 JVM 的 EJB 调用,但事务属性为 Never | ✅ 支持 |
| 不同 JVM 的 EJB 调用,但使用 Bean-Managed 事务 | ✅ 支持 |
不同 JVM 的 EJB 调用,事务属性为 Required 但未启动事务 | ✅ 支持(前提:调用方未在调用前启动事务) |
❌ 不支持的场景
| 场景 | 问题 |
|---|---|
不同 JVM 的 EJB 调用 + 事务属性为 Mandatory | ❌ 必须修改 |
不同 JVM 的 EJB 调用 + 事务属性为 Required 且已启动事务 | ❌ 必须修改 |
不同 JVM 的 EJB 调用 + 事务属性为 Supports 且已启动事务 | ❌ 必须修改 |
关键问题:如何判断我的应用是否受影响?
很多开发者看到迁移工具的警告就慌了,但实际上:
大多数配置了远程 EJB 接口的应用,并没有真正使用远程事务传播。
常见的”误报”原因:
- EJB 2.x 的默认行为:EJB 2.x 的
ejb-jar.xml默认会启用远程接口,即使从未使用 - 检测到 CORBA 配置:工具发现了
iiop://URL,但这可能只是历史遗留配置
如何确认是否真的使用了远程事务传播?
文章提供了一个使用 Trace 日志的方法:
步骤 1: 启用跟踪
在 WebSphere Application Server 中启用:
*=info:EJBContainer=all
步骤 2: 运行应用场景
执行各种应用操作以生成日志。
步骤 3: 分析日志
使用正则表达式过滤 trace.log:
EJBpreInvoke|preInvoke : p|Required |RequiresNew |NotSupported |Mandatory |Never |Supports |Began TX|Began LTC
提示:该正则用于快速筛选日志条目;建议在支持正则的日志查看器中使用,或在正则中增加单词边界以减少误匹配,例如使用 \bEJBpreInvoke\b|\bpreInvoke : p\b|\bRequired\b|...。
步骤 4: 判断依据
| 日志特征 | 含义 |
|---|---|
EJBpreInvoke + WrapperManager preInvoke | 远程调用 |
只有 EJBpreInvoke | 本地调用 ✅ 无问题 |
Mandatory 属性 + 远程调用 | 需要修改 ⚠️ |
Required 或 Supports 属性 + 远程调用 且日志中未出现 Began TX | 这通常表明事务由调用方传递(即发生远程事务传播),需要修改 ⚠️ |
Required 或 Supports 属性 + 远程调用 且日志中出现 Began TX | 这表明目标 EJB 为自身创建了本地事务(未发生远程传播),无需修改 ✅ |
如果真的需要修改,有哪些解决方案?
如果你的应用确实使用了跨 JVM 的事务传播,有两个解决方案:
方案一:合并到同一 JVM(推荐)
将原本分布在不同 JVM 中的 EJB 部署到同一个 Liberty 服务器。
优点:
- 最简单
- 性能更好
- 代码改动最小
适用场景:大多数企业应用
原来:
┌─────────────┐ ┌─────────────┐
│ EJB1 │ ──▶ │ EJB2 │
│ JVM A │ │ JVM B │
└─────────────┘ └─────────────┘
改为:
┌─────────────────────────────┐
│ Liberty Server │
│ ┌───────┐ ┌───────┐ │
│ │ EJB1 │ ──▶ │ EJB2 │ │
│ └───────┘ └───────┘ │
└─────────────────────────────┘
方案二:使用 Web Service + WS-AT
如果必须保持分布式架构,可以将 EJB 包装成 JAX-WS Web Service,然后使用 WS-AT (Web Services Atomic Transaction) 协议。
实现步骤:
1. 为 EJB添加 @WebService 注解
import javax.jws.WebService;
@WebService(
name = "HelloService",
serviceName = "HelloService",
targetNamespace = "http://hello/",
endpointInterface = "hello.HelloIF"
)
public class HelloEJBImpl implements SessionBean, HelloIF {
// EJB 实现
}
2. 修改客户端为 JAX-WS 客户端
使用生成的 WSDL 创建 Web Service 客户端。
3. Liberty 配置 WS-AT
启用 wsAtomicTransaction-1.2 feature。
优点:
- 支持真正的分布式事务
- 符合 Web 服务标准
缺点:
- 代码改动较大
- 性能开销更高
最佳实践建议
1. 优先使用本地接口
如果 EJB 在同一 JVM 内调用,应该使用 @Local 而不是 @Remote:
// 推荐
@Local
public interface MyLocalInterface {
// ...
}
// 避免(除非必要)
@Remote
public interface MyRemoteInterface {
// ...
}
2. 理解事务属性
| 属性 | 行为 |
|---|---|
REQUIRED | 如果有事务则加入,否则创建新事务 |
REQUIRES_NEW | 总是创建新事务 |
MANDATORY | 必须在已有事务中调用,否则抛异常 |
SUPPORTS | 如果有事务则加入,否则无事务执行 |
NOT_SUPPORTED | 挂起当前事务,无事务执行 |
NEVER | 不能在事务中调用,否则抛异常 |
BEAN_MANAGED | 应用程序自己管理事务 |
3. 迁移前做好验证
- 使用 Trace 日志确认实际行为
- 在测试环境中充分验证
- 不要仅依赖迁移工具的报告
总结
| 要点 | 说明 |
|---|---|
| 🎯 核心问题 | Liberty 不支持传统 EJB 的跨 JVM 事务传播 |
| ✅ 好消息 | 大多数应用实际上不使用这个功能 |
| 🔍 验证方法 | 使用 EJB Trace 日志分析实际行为 |
| 💡 解决方案1 | 合并到同一 JVM(推荐) |
| 💡 解决方案2 | 使用 Web Service + WS-AT |
| 📚 参考文档 | IBM Documentation |
参考资源
本文基于 IBM 社区博客 “Transaction Propagation on Liberty” 编写,作者 Laura Cowen 和 Tracy Burroughs。