当你的 EJB 应用从传统 WebSphere 迁移到 Liberty 时,迁移工具可能会提示:”不支持 EJB 远程接口的事务传播”。这到底意味着什么?是否需要大规模重构?本文为你解答。

Read more: 从 Traditional WebSphere Application Server 到 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 -->|远程调用| EJB2

2. 事务传播 (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/>或无事务]
    end

Liberty 的支持情况

✅ 完全支持的场景

场景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 接口的应用,并没有真正使用远程事务传播。

常见的”误报”原因:

  1. EJB 2.x 的默认行为:EJB 2.x 的 ejb-jar.xml 默认会启用远程接口,即使从未使用
  2. 检测到 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 属性 + 远程调用需要修改 ⚠️
RequiredSupports 属性 + 远程调用 且日志中未出现 Began TX这通常表明事务由调用方传递(即发生远程事务传播),需要修改 ⚠️
RequiredSupports 属性 + 远程调用 且日志中出现 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。