问题:太过于关注 SOA 中的会话和实体
署名:Feeling Disconnected
对松耦合有许 多方面要考虑
亲爱的 Disconnected:EJB 倡导者关注的是应用程序的服务层,而对客户端介绍得很少, 因为我对古谚语形式追随功能 (form follows function) 深信不疑。
其原因在于,许多进行 SOA 的项目之所以失败,是因为 它们没有首先建立定义服务的良好模型就开始着手实现细节。
这种倾向相当正常,因为我在 SOA 项目中接触到的大多数人都是架构师 和编程人员,他们知道棘手的始终是在细节上,想要尽快解决它们。所以,一旦我们认同好服务的特征是粗粒度、无状态、可通过中介传递和 适应的(请参阅 Is it ever best to use EJB components without facades in service oriented architectures?),很明显带有数据传输对象的会话 Bean 就会在实现 中扮演重要角色。
图 1. 用有待使用的会话和实体 EJB 实现的服务
图 1 显示了当使用传递过去的会话 Bean 时,纯实体方法(自 EJB 2 开始可用)如何才能有更少的组件和更短的路径长度。其中使用绿色框表示 客户端,蓝色框表示各种接口和 Facade 类。橙色框是最常访问的实体 Bean.框和框之间使用双向箭头连接,箭头标有在组件之间通信所使用 的协议;蓝色箭头表示相同 JVM 中的 Java 调用,红色箭头表示远程连接(在本例中使用 RMI/IIOP)。为了表示端到端的流向,对流程箭头 进行编号,其中 A1-A10 表示从 Java 客户端经过会话 Bean 到实体和返回的流程,B1-B4 表示从客户端直接到实体 Bean 和返回的流程。
客户端用于检索服务接口的编程模型也很简单,虽然在图中没有表示出来。检索会话 Bean 接口需要在 JNDI 上下文中查找会话 Home 并用它创建一个会话;实体 Home 仅仅需要一次查找,其方法可以直接调用而不需要创建对 EJB Object 的引用。以下两段代码示例显示了它 们之间的区别。
清单 1. 定位和调用远程会话 EJB 方法
Context initCtx = new InitialContext();
Object obj = initCtx.lookup("java:comp/env/ejb/OrderEntry");
OrderEntryHome home = (OrderEntryHome)PortableObjectRemote(obj,
OrderEntryHome.class);
OrderEntry ref = home.create();
// Method must be invoked on
a session referenceCustomerData data =
ref.getOpenOrderForCustomercID);
清单 2. 定位和调用等效远程实体 EJB Home 方法
Context initCtx = new InitialContext();
Object obj = initCtx.lookup("java:comp/env/Customer");
CustomerHome ref = (CustomerHome)
PortableObjectRemote(obj, CustomerHome.class);
// Note how the method is invoked directly
CustomerData data = ref.getOpenOrder(cID);