业务活动 API
使用业务活动应用程序编程接口 (API) 来为应用程序组件创建业务活动和补偿处理程序,并记录在总体业务活动中发生故障的情况下补偿活动所必需的数据。
概述
InitialContext ctx = new InitialContext();
UserBusinessActivity uba = (UserBusinessActivity) ctx.lookup("java:comp/websphere/UserBusinessActivity");
InitialContext initialContext = new InitialContext();
UserBusinessActivity uba = initialContext.lookup("java:comp/websphere/UserBusinessActivity");
…
String activityId = uba.getId();
if (activityId == null)
// No activity on the thread
else
// Output audit message including activity id
- com.ibm.websphere.wsba.serializable.CompensationHandler,它采用可系列化对象的参数
- com.ibm.websphere.wsba.CompensationHandler,它采用服务数据对象 (SDO) 的参数
应用程序必须注册补偿处理程序实现,该实现与该应用程序使用的补偿数据(可系列化对象或 SDO)类型配合使用。如果在该应用程序组件使用的数据类型与补偿处理程序实现之间存在错误匹配,那么将会出现错误。
在正常的应用程序处理期间,应用程序可以一次或多次调用 setCompensationDataImmediate 或 setCompensationDataAtCommit 方法,并传入用来表示所执行的工作的当前状态的 SDO 或可序列化对象。
当完成与根业务活动相关联的底层工作单元 (UOW) 时,所有已注册的补偿器也要相应地完成。在完成期间,对补偿处理程序调用了compensate或close方法,并将应用程序组件记录的最新补偿数据作为一个参数传入。补偿处理程序实现必须能够了解存储在可序列化对象或 SDO DataObject 中的数据;使用此数据时,补偿处理程序必须能够确定企业 Bean 所执行的工作的性质,并且以适当的方式进行补偿或关闭,例如,在业务活动中发生故障的情况下撤销对数据库行所作的更改。通过使用组装工具(如 Rational® Application Developer)将补偿处理程序与应用程序组件相关联。
活动和不活动的补偿处理程序
对于任何执行代码(可能必须在业务活动范围内进行补偿)的应用程序组件实现 serializable.CompensationHandler 或 CompensationHandler 接口。每当应用程序调用 UserBusinessActivity API 来指定补偿数据时,补偿处理程序对象就会隐式地向应用程序运行的业务活动范围注册。补偿处理程序可能处于两种状态:“活动”或“不活动”,这取决于注册它们时所采用的事务 UOW。在落实事务之前,事务 UOW 中注册的补偿处理程序最初可能处于“不活动”状态,而在落实事务之后,补偿处理程序就会变成“活动”状态(请参阅下面的部分)。在事务 UOW 外部注册的补偿处理程序始终会立即变为活动状态。
当业务活动完成时,它将只驱动活动的补偿处理程序。与该业务活动相关联的任何不活动的补偿处理程序都会被 废弃并且不会被驱动。
记录补偿数据
业务活动 API 指定了应用程序可以使用两种方法来记录补偿数据。业务活动完成时,此数据在处理期间就可用于补偿处理程序。应用程序根据它是否期望事务成为业务活动的一部分来调用这些方法中的其中一种方法。
- setCompensationDataAtCommit()
- 当应用程序期望线程上存在全局事务时,调用 setCompensationDataAtCommit 方法。
- 如果线程上存在全局事务,那么 CompensationHandler 对象最初处于不活动状态。如果全局事务失败,那么它会以原子方式回滚在它的事务上下文中完成的任何事务性工作,并驱动业务活动以补偿其他已完成的 UOW。不需要使用补偿处理程序。如果成功落实了全局事务,那么补偿处理程序将变为“活动”状态,这是因为如果总体业务活动失败的话,那么补偿处理程序需要补偿由全局事务完成的持久工作。setCompensationDataAtCommit 方法将配置 CompensationHandler 实例以执行此补偿功能。
- 如果调用 setCompensationDataAtCommit 方法时不存在全局事务,那么补偿处理程序将立即变为活动状态。
DataObject compensationData = doWorkWhichWouldNeedCompensating(); uba.setCompensationDataAtCommit(compensationData);
- setCompensationDataImmediate()
如果应用程序期望线程上不存在全局事务,那么调用 setCompensationDataImmediate 方法。
无论调用 setCompensationDataImmediate 方法时当前 UOW 上下文处于何种状态,该方法都会立即使 CompensationHandler 实例变为活动状态。在完成业务活动期间,补偿处理程序始终都能够参与。
setCompensationDataImmediate 方法的作用是补偿任何非事务性工作(也就是在全局事务内部或外部执行但不受事务管理的工作)。此类工作的一个示例是发送电子邮件。补偿处理程序必须立即变为活动状态,以便在业务活动中发生 故障的情况下,始终对此非事务性工作进行补偿。
例如,对于可序列化对象,并使用上一个示例中的业务活动实例:Serializable compensationData = new MyCompensationData(); uba.setCompensationDataImmediate(compensationData);
在同一企业 Bean 中调用这两种补偿数据记录方法时,尽管这两种方法使用同一个补偿处理程序类,但是它们在运行时将创建补偿处理程序类的两个不同实例。因此,这两种方法的操作是互斥的;调用一种方法时不会覆盖另一种方法所执行的任何工作。
如果已使用其中一个方法将补偿处理程序实例添加到“业务活动”中,然后调用同一方法并传递 null 作为参数,那么将从该业务活动中移除该补偿处理程序实例,并且该实例不会在该业务活动完成期间触发关闭或补偿。
如前面所述,当使用业务活动的企业 Bean 首次调用补偿数据记录方法时,业务活动支持会将补偿处理程序实例添加至该业务活动。同时,将生成企业应用程序上下文的快照并且与补偿数据一起记录。当业务活动完成时,将已添加到业务活动的所有补偿处理程序驱动至 compensate 或 close。将保证在 CompensationHandler 或 serializable.CompensationHandler 类中创建的代码在先前快照中捕获的同一企业应用程序上下文中运行。