技术开发 频道

JCA 1.5: 消息输入流

  MDB 和事务

  如果资源适配器支持 XA (全局) 事务,而且 isDeliveryTransacted 表明 MDB 期望容器启动一个事务,那么资源适配器就应当在调用 createEndpoint 时传入一个 XAResource 接口的实现。XA 事务是个复杂的主题,与 JCA 无关的问题超出本文的范围。对于更多细节,请参考 Java 事务 API 规范 。

  对于如何进行处理,资源适配器有两个选项。它可以选择把要执行的事务性工作直接与它的 XAResource 对象关联起来。资源适配器就可以使用 Option A 消息传递。当调用代理时,容器会调用 start,列举出事务中的 XAResource。这个时候,资源适配器可以把指定的 Xid 与要执行的工作关联起来。代理继续调用端点实例。在端点方法返回之后,容器就完成了事务。当 XAResource 接收到对 prepare 的调用时,它应当保证自己能够在返回 XA_OK 之前成功完成要求的工作。最后,XAResource 接收 commit 或 rollback,这时它应当提交或取消已经执行的工作。

  或者,资源适配器也可以使用 Option B 消息传递,在这种情况下,事务是作为 beforeDelivery 的一部分启动的。这样就允许资源适配器在调用 MDB 的方法之前从 XAResource 检索 Xid。例如,如果在自己能够构建传递给方法的参数之前,资源需要把 Xid 传递给后端系统,那么这可能是必需的。可以想像,在这种情况下,事务是在调用 afterDelivery 的时候完成的。

  如果应用服务器在调用 prepare 和 commit、rollback 之间失败,那么在服务器重启时需要进行事务恢复。为了执行恢复,应用程序服务器需要为每个资源管理器获取一个 XAResource。应用服务器实现这一目标的方式是:在调用 prepare 之前,把与端点关联的 ActivationSpec 写入永久性存储器。在恢复的时候,服务器读出表示每个资源适配器的 ActivationSpec 对象列表,这些适配器对应着它认为没有完成的事务。这个对象数组将传递给 ResourceAdapter 接口上的 getXAResources 方法,如清单 12 所示:

  清单 12. ResourceAdapter 接口上的事务恢复方法

1 public interface ResourceAdapter {
2     XAResource[] getXAResources(ActivationSpec[] specs)
3             throws ResourceException;
4     ...
5 }

  应用服务器调用每个 XAResource 对象上的 recover 方法来确定资源管理器准备好的事务。然后根据情况为每个事务调用 commit 或 rollback。

  在前文中,介绍了 ExecutionContext 如何与 WorkManager 结合,把事务导入应用服务器。如果用导入的事务调用具有事务属性 Required 的端点方法,那么这个方法将继承该事务。在这种情况下,任何 XAResource passed on createEndpoint 上传递的方法都不会列在该事务中。

  托管对象

  在最后一节中,我将介绍的一个主题是:可以平等地用于输入和输出 资源适配器,虽然这一主题在 JCA 规范的消息输入流一章中层介绍过。规范的 1.5 版本的目标之一就是允许 JMS 提供者作为 JCA 资源适配器实现。如果了解 JMS,那么就会注意到它包含两类可以管理的对象:连接工厂和目标。通过托管连接工厂和它们在资源适配器的部署描述符中定义的属性,JCA 提供了一种机制,使管理员可以定义连接工厂,以便部署的程序能够通过 Java 名称与目录服务接口(JNDI)查找它们。但是 JMS 目标不是工厂,而是拥有不同属性(描述它们表示的队列或主题)的对象。如果这样,那么怎么才能创建 JMS 目标呢?

  JCA 1.5 规范定义了托管对象 来弥补这个空白。资源适配器的部署描述符可以包含一个或多个 adminobject 元素,如清单 13 所示:

  清单 13. 显示托管对象的部署描述符代码段

1 <adminobject>
2    <adminobject-interface>example.ExampleAdminObject</adminobject-interface>
3    <adminobject-class>example.ExampleAdminObjectImpl</adminobject-class>
4    <config-property>
5     <config-property-name>Color</config-property-name>
6     <config-property-type>java.lang.String</config-property-type>
7      <config-property-value>Red</config-property-value>        
8    </config-property>
9    <config-property>
10     <config-property-name>Depth</config-property-name>
11     <config-property-type>java.lang.Integer</config-property-type>
12    </config-property>
13   </adminobject>
14

  在这种情况下,应用程序期望从 JNDI (通过资源环境引用)查找实现了 example.ExampleAdminObject 接口的对象。部署描述符提供了能提供这个对象实现的 JavaBean 类的名称。它还提供了许多命名属性,每个属性都有一个类型和一个可选的默认值,这种方式非常类似于托管连接工厂。当管理员希望定义一个对象时,应用程序服务器的工具应当允许管理员选择资源适配器和托管对象接口,然后提示管理员输入每个属性的值。应用服务器随后将包含这个信息的引用绑定到 JNDI。当应用程序执行查找时,就创建一个托管对象的实例,而且在把对象返回应用程序之前设置好属性。

  现在应当能够看出 JCA 资源适配器如何通过使用托管对象来提供 JMS 目标对象了。但是请不要忘记,您可以对任何想让管理员能够配置的 JavaBean(不仅仅是连接工厂)使用托管对象,这些 JavaBean 可以通过 JNDI 访问。

  结束语

  在本文中,我解释了消息驱动 bean 在 J2EE 1.3 和 J2EE 1.4 之间的变化,特别是目前如何实现任何接口。您已经看到如何用 JCA 消息输入流合约来配置资源适配器,以便用它来检索 MDB 实例以及调用 MDB 上的方法。我还详细介绍了调用 bean 方法的选项,以及调用事务性方法的意义。最后,我介绍了托管对象如何使用资源适配器定义将要配置的 JavaBean,并使其能够通过 JNDI 访问。

  这一文章系列介绍了 JCA 1.5 的一些新特性,从优化和生命周期管理开始,到工作管理和事务,最后以消息输入流合约告终。像过去一样,规范提供了信息的确定来源,而且肯定会在未来的版本中继续发展。我希望您觉得这个系列有用,不管您是打算升级现有的资源适配器,还是打算从头编写一个新的资源适配器,或者仅仅把资源适配器用作应用程序的一部分。

0
相关文章