信息系统的间的事务处理
整理者: freshlll@126.com
时间:05年7月7月7日月7日7日日
我尝试把这文章做了一个翻译,请大家多多指教,多多交流。
原文:
Importing Java Transactions from an External EIS Using JCA 1.5 Transaction InflowDate: Jul 1, 2005 By Madhusudhan Konda .
The introduction of inbound transactions in the Java Connector Architecture (JCA) 1.5 specification is a great step toward seamless integration of heterogeneous systems. Madhusudhan Konda explains the simple theory behind the transaction inflow contract and shows how easy it is to implement a resource adapter to import a transaction from an external enterprise.
Transactions are the backbone of enterprise systems, and the introduction of inbound transactions in the Java Connector Architecture (JCA) 1.5 specification is a great step toward seamless integration of heterogeneous systems. Transaction inflow contracts provide a mechanism for importing external transactional contexts, for transaction completion, and for crash recovery. But implementing these contracts is a complex and challenging task. This article explores the process of implementing contracts, explaining the contract in detail and designing a resource adapter capable of importing transacted messages originating from an external enterprise information system (EIS).This article has attempted to explain the transaction inflow, discussing the theory behind the inflow contract and implementing a resource adapter to import a transaction.
IntroductionLet's consider a travel company called MoonTravel, which has an in-house application called the Flight Reservation System (FRS). This system provides travel agencies with the capability of creating flight reservations, allowing travel agents to access MoonTravel's flight inventory in real time. MoonTravel doesn't intend to port this legacy application to the J2EE platform.
Recently, MoonTravel's Operations and Research departments have developed a revenue management system (RMS) that can vary ticket prices based on booking patterns coupled with geographic, seasonal, and other factors. The RMS is a semi-automated J2EE application that can add supplements to flight prices based on recommendations from the application's intelligence process. These recommendations are executed on a nightly basis. The RMS depends on the FRS for real-time booking feeds. Whenever a booking is confirmed, the FRS should update the RMS systems so that pointers to the booking patterns can be added to the RMS databases.
Integration of these two systems is a challenging task for MoonTravel's developers. A major requirement is to include external workflow in current transactions.
Whenever a travel agent confirms a booking, the FRS has a finite workflow:
Add the order.
Update the customer database and the order status.
Update the agency revenue database.
Update the flight inventory database.
Bill the customer.
Send a message to the RMS and update the operational database.
Send a confirmation to the parties involved.
All of these tasks must be performed in a transaction. Step 6, sending a message to the RMS and updating the operational database, is the point where the two heterogeneous systems interact. That is, a legacy EIS stretches its transaction boundaries to the application server.
Until the advent of the Java Connector Architecture, there weren't any standards to transactionalize the workflow between disparate systems. Connector architecture has come a long way in developing standards for integrating the enterprise.
Sharing TransactionsTransaction inflow serves the purpose of injecting transactions from an EIS into the J2EE world. These transactions are initiated by the EIS. If a message arrived from the EIS in a transaction, the J2EE application should import the transaction context and perform the business process on that message in the same transaction. In MoonTravel's use case, the FRS asks the RMS to act on the booking message before it confirms the parties involved. If the RMS is unable to update its database for some reason, the transaction can be rolled back and retried later. In other words, each transaction is shared between the EIS and the J2EE worlds.
Importing the TransactionsIt's easy to understand the procedures involved in importing transactions from an EIS. This is the task list:
The EIS creates a transaction.
The EIS sends a message along with a transactional context to the resource adapter. The transactional context can be specific to the EIS.
The resource adapter extracts the EIS-specific transactional context into a standard javax.transaction.xa.Xid.
The resource adapter creates an ExecutionContext with Xid and probably with an attribute to indicate the transaction timeout.
The resource adapter submits the Work instance, coupled with the newly created ExecutionContext, to the application server.
The application server reads the message and understands that the work is to be performed in a transaction. It enlists the Work instance in this imported transaction.
Upon the return of the Work instance, the EIS can commit the transaction either in a one-phase (1PC) manner or a two-phase (2PC) manner, the fundamental difference being that the 1PC doesn't need to call prepare before committing.
Following are the steps in a 2PC transaction:
The EIS sends a prepare message to the resource adapter for the given transaction.
The resource adapter calls prepare on an XATerminator obtained from BootstrapContext with Xid. It returns the result of the prepare call.
Depending on the result, the EIS sends a commit or a rollback to the resource adapter.
The resource adapter performs the commit or rollback.
The EIS can coordinate transactions with the resource adapter in many ways. For example, the transactional context, along with completion and recovery calls, can be published via a common messaging scheme between the EIS and the resource adapter. In a simple implementation, a business message produced by the EIS may contain Xid transaction-timeout attributes as message headers or properties. The resource adapter understands how to retrieve the transactional context from these properties. When a transaction is prepared for completion, the EIS sends a prepare message and the commit message for committing the transaction.
Now that we've explored the theory, let's delve into implementation details.
The Resource AdapterThe MoonTravel developers built an FRSResourceAdapter that acts a bridge between the RMS and the FRS, as shown in Listing 1. This resource adapter is bound to the J2EE application server's address space and acts on behalf of the FRS. The major requirement is to import the transaction that has been initialized by the EIS.
Listing 1 FRSResourceAdapter.javapublic class FRSResourceAdapter implements ResourceAdapter {
private XATerminator _xaTerminator = null;
private WorkManager _workManager = null;
public void start(BootstrapContext ctx){
// get a reference to XATerminator and WorkManager
xaTerminator = ctx.getXATerminator();
_workManager = ctx.getWorkManager();
....
}
public void endpointActivation(MessageEndpointFactory endpointFactory,
ActivationSpec spec) throws ResourceException {
try {
// Create a worker and submit for execution
FRSWork worker = new FRSWork(spec, endpointFactory, _workManager, _xaTerminator);
// Now schedule this worker
_workManager.scheduleWork(worker);
} catch (UnavailableException e) { .. }
}
...
}
References to WorkManager and XATerminator are provided by the application server via BootstrapContext during the start method invocation. These objects are used to submit the work instances and complete the imported transactions, respectively. The XATerminator methods are invoked by the resource adapter, depending on the transactional attributes obtained from the EIS messages.
The Work InstanceA Work object is essentially a thread managed by the application server. The FRSWork shown in Listing 2 is instantiated and submitted to the application server for execution during the endpointActivation call.
Listing 2 FRSWork.javapublic void FRSWork extends javax.resource.spi.Work {
...
public FRSWork(ActivationSpec spec, MessageEndpointFactory listener,
WorkManager workManager) throws UnavailableException{
// Hold these references for the lifetime
_xaSpec = (FRSActivationSpec) spec;
_endpointFactory = endpointFactory;
_workManager = workManager;}
}
...
public void run() {
while(ok){
// This recv method consumes the messages incessantly
msg = connection.recv();
// Do the processing if a message is received
try {
//Check what kind of message it is
if (msg instanceof PrepareSignal) {
// EIS making a prepare call
System.out.println(" PrepareSignal message");
PrepareSignal psMsg = (PrepareSignal)msg;
// We should convert EIS call to
// our XATerminator's call
int XA_RESULT = _xaTerminator.prepare((Xid)psMsg.getObjectProperty(FRS_XID));
// Now that we have the result of prepare, we have to notify
// EIS by sending a message from our RA
notifyPrepareResultToEIS(psMsg, XA_RESULT);
} else if (msg instanceof CommitSignal) {
// EIS making a commit call
System.out.println(" Commit Signal message");
// The Boolean argument stands for
// one-phase or two-phase commit
CommitSignal commitMsg = (CommitSignal)msg;
_xaTerminator.commit((Xid) commitMsg.getObjectProperty(FRS_XID), false);
} else if (msg instanceof FRSMessage){
// Business message, possibly in a transaction
FRSMessage frsMsg = (FRSMessage) msg;
// Create ExecutionContext from EIS Message. We are
// expecting a transaction Xid and timeout if this
// work is to be performed under a transaction
execCtx = createExecutionContext(frsMsg);
// Schedule for work with this ExecutionContext
_workManager.scheduleWork(new TxWork(_endpointFactory, frsMsg),
WorkManager.IMMEDIATE, execCtx, null);
}
} catch (Exception e) { .. }
...
}
Pay attention to the FRSWork object's run method. When the application server executes FRSWork, it calls the run method, which checks for a message from the EIS by calling the recv method on FRSConnection. The recv method works incessantly to retrieve any messages via the Connection interface. In our simple implementation, the EIS can produce three kinds of messages, as shown in the following table.
Message
Description
PrepareSignal
Indicates that the transaction(n) with the Xid is ready to prepare. Upon receiving this message, the resource adapter calls the prepare call on XATerminator.
CommitSignal
Indicates that the transaction(n) with the Xid is to be committed. The resource adapter will now commit the transaction using XATerminator.
FRSMessage
Business message with a transaction Xid. The EIS expects to execute the message under the given transaction.
The ExecutionContext ObjectThe ExecutionContext provides a context in which the Work instance is to be executed. The resource adapter creates the ExecutionContext by extracting the transaction information from the FRSMessage, as shown in Listing 3.
Listing 3 Creating an ExecutionContextpublic ExecutionContext createExecutionContext(FRSMessage msg)
throws JMSException, NotSupportedException {
// Get Xid and transaction timeout from message
// FRS_XID and FRS_TX_TIMEOUT are the properties
// set on this message by EIS
Xid xid = (Xid) msg.getObjectProperty("FRS_XID");
long txTimeOut = msg.getLongProperty("FRS_TX_TIMEOUT");
// Create an ExecutionContext object with these values
ExecutionContext execCtx = new ExecutionContext();
execCtx.setXid(xid);
execCtx.setTransactionTimeout(10000);
return execCtx;
}
Whenever a Work instance is executed by the application server, an optional ExecutionContext can be provided. By default, a null ExecutionContext is provided, which indicates that the Work is not in a transaction. The transactional work is performed in the TxWork object, as shown in Listing 4.
Listing 4 The TxWork run Methodpublic void run() {
try {
// Create an endpoint listener. You can implement a
// sophisticated MDBs pool here. For example, before creating
// an endpoint, check whether one is available. If not available,
// check the pool to grab one, etc.
_endpointListener = (FRSListener)_endpointFactory.createEndpoint(null);
// Now that we have the EIS message,
// process it under the transaction
_endpointListener.onMessage(_frsMsg);
} catch (UnavailableException e) {
...
}
...
}
All the work performed in this run method is executed under the imported EIS transaction. From here on, the usual J2EE transaction concepts apply.
Transaction CompletionThe EIS must send prepare/commit messages depending on the one-phase or two-phase commit criteria. The resource adapter calls prepare on the XATerminator instance by passing the transaction's Xid when it receives a prepare call. The result of the prepare call is passed back to the EIS via the notifyPrepareResultToEIS method, as shown in Listing 5.
Listing 5 Notifying the Prepare Result to EISprivate void notifyPrepareResultToEIS(EISMessage psSignal, int xa_result) {
// Logic to inform the EIS about the prepare call
// This uses the outbound connectivity for connecting to the EIS
FRSConnection connection = FRSConnectionFactory.createConnection();
PrepareSignalResult PREPARE_MESSAGE = new PrepareSignalResult(psSignal, xa_result);
connection.sendPrepareMessage(PREPARE_MESSAGE);
}
}
To send the prepare outcome, the resource adapter should get a connection to post a message to the EIS's inbound channel.
Once the outcome of the prepare call is received, the EIS decides whether to commit or roll back the transaction. The procedure is the same as that for prepare:
The EIS sends a commit/rollback message with a transaction Xid.
The resource adapter calls commit/rollback on the XATerminator object.
XATerminator commits/rolls back the transaction marked with the Xid.
Crash RecoveryAny topic on transactions is incomplete without at least a mention of crash recovery, though implementation is beyond the scope of this article. The Java Connector Architecture allows room for implementation of recovery should your EIS or application server crash:
If an application server crashes during an active transaction (the transaction is not yet prepared), the EIS aborts the transaction. Similarly, if an EIS crashes with active transactions, the resource adapter aborts them.
If the application server goes down during an in-doubt transaction (the transaction is prepared but not yet committed), the EIS tries to reestablish communications with the application server and complete the transaction. If the EIS crashes during an in-doubt transaction, the resource adapter waits until the EIS is back online and tries to complete the transaction. The application server invokes the getXAResource(..) method when it's back from a crash, retrieving the XAResources allocated for the respective ActivationSpecs. It then calls recover for each XAResource obtained.
SummaryImporting external transactions from a different world into the J2EE platform can be difficult, but before the advent of JCA 1.5, this task was almost unthinkable. Transaction inflow has paved a way for injecting transactions from legacy systems such as CICS, SAP, and so on into a modern application hosted on a J2EE platform.
ReferencesJava Transaction API (JTA)
Java 2 Platform, Enterprise Edition (J2EE)
Java Connector Architecture (JCA)
© 2004 Pearson Education, Inc. InformIT. All rights reserved.
800 East 96th Street Indianapolis, Indiana 46240
译文
译者:freshlll@126.com
整理:
用JCA 1.5事务流(JCA 1.5 Transaction Inflow) ,从外部EIS(enterprise information system)引入java 事务
Date: Jul 1, 2005 By Madhusudhan Konda .
Java Connector Architecture (JCA) 1.5 说明书中的外部进入内的事务的介绍,这对无缝的异构系统的集成是一个巨大进步。Madhusudhan Konda阐述:在事务流契约下一个简单的理论,并且怎样简单的实现一个适用于要从外部企业引入事务的资源。
事务是一个企业系统的枢纽,而Java Connector Architecture (JCA) 1.5 说明书中的外部进入内的事务的介绍,这对无缝的异构系统的集成是一个巨大进步。对事务完成,紧急故障恢复,引入外部事务,事务流契约提供了一个的机制。但是实现这些契约是一项复杂和挑战性的工作。这篇文章阐述了实现契约的过程,详细的解释了契约,并且设计 一个资源的实现,其能够传递来自外部企业信息系统消息。这篇文章也试着解释事务流,谈论在事务流下的理论和适应于引入事务流的资源的实现。
说明
让我们考虑一个叫(MoonTravel)的旅行公司,它有一个机票预定系统。这个系统为航空代理提供机票预定能力。它允许航空代理实时访问它的航班清单。 MoonTravel不打算吧这个应用程序布局到j2ee平台。
查:MoonTravel doesn't intend to port this legacy application to the J2EE platform.
最近 MoonTravel的运筹部开发了一个收入管理系统,它的订票模型能根据地理,季节和其它因素而改变票价。RMS是一个半自动的j2ee应用,它能基于智能程序的建议增补航班价格。这些建议被一个夜行平台执行。RMS依靠实时订票信息。无论什么时候订单确定,那么就会指示订票模型更新RMS数据库。
查:1.have developed a revenue management system (RMS)
2.These recommendations are executed on a nightly basis.
3.Whenever a booking is confirmed, the FRS should update the RMS systems so that pointers to the booking patterns can be added to the RMS databases.
对moonTravel的开发者来说,集成这两个系统是一项挑战性的工作。一下主要的需要就是在当前事务中增加一个流程。
查:1.A major requirement is to include external workflow in current transactions.
无论什么时候一个航空代理确认了一个订单,FRS有一个固定流程。
1.添加订单
2.更新客户的数据库和订单状态。
3.更新代理的收入数据库。
4.更新航班清单数据库。
5.给客户帐单
6.法一个消息给RMS并且更新操作数据库。
7.发送信息给相关人员。
所以的工作都必须用事务来处理。第六步,发送一个消息给RMS并且更新操作数据库
,这是两个异构系统的交互点。这就是EIS把它的事务边界延伸到了应用服务器。
查:legacy 我看到有些经常用到这个词,比如legacy application,legacy EIS等。
还没有在不同的系统之间的事务流程处理标准,直到Java Connector Architecture的降临。Connector Architecture为企业集成带来了一个开发标准。
共享事务
事务流是为把事务从EIS注入到j2ee平台服务。这些事务由EIS发起,如果一个来自EIS的消息到来,j2ee应用就引入事务相关内容,并利用这个事务中消息处理相关的业务。
在确认相关的工作前FRS需要问RMS相关的订票的消息。这样如果RMS由于某些原因不能更新相关的数据库,相关的事务就能回滚或重做。换句话来说,每一个事务都是在EIS和j2ee平台之间共享的。
引入事务
从EIS引入事务的处理过程是非常容易明白的。下面是工作列表:
1.EIS产生一个事务。
2.EIS发送一个带由事务内容的消息给资源适配器。事务内容对是EIS性质的。
查:The transactional context can be specific to the EIS.
3.资源适配器把EIS性质的事务内容转化为标准的javax.transaction.xa.Xid.
查:extract ......into ... extract :提取,摘录
4.资源适配器Xid产生一个ExecutionContext并且大概用一个属性指示事务超时。
5.资源适配器把附加上新的ExecutionContext的工作实例交给应用程序服务器。
6.应用程序服务器读取消息并且知道这个实例应是作为一个事务来处理。它运行这个引入进来的事务的实例。
在这个返回的实例下,EIS能够 用 one-phase manner(1PC)或two-phase manner(2PC)的方式来提交事务,这两方式的不同之处在于(1PC)在提交前不用预编译。
2PC事务遵循以下步骤:
1.EIS为相关事务发出一个预编译的消息给资源适配器。
2.资源适配器调用预编译产生一个于使用Xid的BootstrapContext的XATerminator.它返回调用预编译结果。
3.依据这个结果,EIS发出提交或回退给资源适配器。
4.资源适配器处理这个提交或回退。
EIS有许多方式协同资源适配器处理处理事务。例如:完成或恢复的事务操作能够通过一个EIS和资源适配器的消息机制来处理。一个简单实现,由EIS产生的业务消息把包含Xid 事务超时属性作为消息头或属性。资源适配器知道怎样从事务中检索这些属性。当一个事务完成时,EIS发送一个预编译消息,为了提交事务的消息。
现在已经阐述了这个理论,让我们深入到实现细节。
资源适配器
MoonTravel 的开发者开发了一个作为RMS和FES之间桥梁的FRSResourceAdapter,如下面的Listing 1.这个资源适配器被绑定到j2ee应用的地址空间并作为FRS的代理。一个主要的需求就是引入被EIS初始化的事务。
Listing 1 FRSResourceAdapter.javapublic class FRSResourceAdapter implements ResourceAdapter {
private XATerminator _xaTerminator = null;
private WorkManager _workManager = null;
public void start(BootstrapContext ctx){
// get a reference to XATerminator and WorkManager
xaTerminator = ctx.getXATerminator();
_workManager = ctx.getWorkManager();
....
}
public void endpointActivation(MessageEndpointFactory endpointFactory,
ActivationSpec spec) throws ResourceException {
try {
// Create a worker and submit for execution
FRSWork worker = new FRSWork(spec, endpointFactory, _workManager, _xaTerminator);
// Now schedule this worker
_workManager.scheduleWork(worker);
} catch (UnavailableException e) { .. }
}
...
}
涉及到的WorkManager和 XATerminator是由应用服务器通过BootstrapContext,通过调用startf方法提供的,这些对象分别用于提交工作实例和完成引入的事务。资源适配器调,依据EIS消息上得到的事务属性,调用XATerminator方法。
工作实例
工作实例一个被应用服务器管理的必须的线程。在Listing2中展示的FRSWork,提交给应用程序服务器在endpointActivation 调用 中执行。
Listing 2 FRSWork.javapublic void FRSWork extends javax.resource.spi.Work {
...
public FRSWork(ActivationSpec spec, MessageEndpointFactory listener,
WorkManager workManager) throws UnavailableException{
// Hold these references for the lifetime
_xaSpec = (FRSActivationSpec) spec;
_endpointFactory = endpointFactory;
_workManager = workManager;}
}
...
public void run() {
while(ok){
// This recv method consumes the messages incessantly
msg = connection.recv();
// Do the processing if a message is received
try {
//Check what kind of message it is
if (msg instanceof PrepareSignal) {
// EIS making a prepare call
System.out.println(" PrepareSignal message");
PrepareSignal psMsg = (PrepareSignal)msg;
// We should convert EIS call to
// our XATerminator's call
int XA_RESULT = _xaTerminator.prepare((Xid)psMsg.getObjectProperty(FRS_XID));
// Now that we have the result of prepare, we have to notify
// EIS by sending a message from our RA
notifyPrepareResultToEIS(psMsg, XA_RESULT);
} else if (msg instanceof CommitSignal) {
// EIS making a commit call
System.out.println(" Commit Signal message");
// The Boolean argument stands for
// one-phase or two-phase commit
CommitSignal commitMsg = (CommitSignal)msg;
_xaTerminator.commit((Xid) commitMsg.getObjectProperty(FRS_XID), false);
} else if (msg instanceof FRSMessage){
// Business message, possibly in a transaction
FRSMessage frsMsg = (FRSMessage) msg;
// Create ExecutionContext from EIS Message. We are
// expecting a transaction Xid and timeout if this
// work is to be performed under a transaction
execCtx = createExecutionContext(frsMsg);
// Schedule for work with this ExecutionContext
_workManager.scheduleWork(new TxWork(_endpointFactory, frsMsg),
WorkManager.IMMEDIATE, execCtx, null);
}
} catch (Exception e) { .. }
...
}
注意FRSWork的run 方法,当应用服务器执行FRSWork,它调用run方法,这个方法检查EIS在FRSConnection上 调用recv 方法而得到的消息。Recv方法通过连接接口不间断的回收任何消息。在我们简单实现中,EIS能产生三种消息,在下面的表中可以看到。
Message
Description
PrepareSignal
指的是Xid事务已经准备,利用接受的消息, 资源适配器调用基于XATerminator的预编译的调用。
CommitSignal
指的是Xid事务被提交,资源适配器将用XATerminator提交事务。
FRSMessage
带有Xid事务的业务消息,EIS期望执行在给出的事务下的消息
The ExecutionContext Object
ExecutionContext 提供 让工作实例执行一个上下文环境,资源适配器通过从FRSMessage提取的事务信息中产生 ExecutionContext。如Listing3所示。
Listing 3 Creating an ExecutionContextpublic ExecutionContext createExecutionContext(FRSMessage msg)
throws JMSException, NotSupportedException {
// Get Xid and transaction timeout from message
// FRS_XID and FRS_TX_TIMEOUT are the properties
// set on this message by EIS
Xid xid = (Xid) msg.getObjectProperty("FRS_XID");
long txTimeOut = msg.getLongProperty("FRS_TX_TIMEOUT");
// Create an ExecutionContext object with these values
ExecutionContext execCtx = new ExecutionContext();
execCtx.setXid(xid);
execCtx.setTransactionTimeout(10000);
return execCtx;
}
无论什么时候资源工作实例被应用程序服务器执行,一个可选的ExecutionContext被提供,默认的情况下,一个空的ExecutionContext被提供,指的是工作实例不在事务中。事务工作在TxWork中处理,如Listing4所示。
Listing 4 The TxWork run Methodpublic void run() {
try {
// Create an endpoint listener. You can implement a
// sophisticated MDBs pool here. For example, before creating
// an endpoint, check whether one is available. If not available,
// check the pool to grab one, etc.
_endpointListener = (FRSListener)_endpointFactory.createEndpoint(null);
// Now that we have the EIS message,
// process it under the transaction
_endpointListener.onMessage(_frsMsg);
} catch (UnavailableException e) {
...
}
...
}
在引入的EIS事务下所有的工作都被run方法执行。在这里,通常的j2ee事务概念实行。
Transaction Completion
依据 one-phase 或two-phase 提交准则,EIS必须发送 预编译/提交 消息。资源适配器通过Xid 事务调用预编译,当它接受到一个预编译的调用。预编译的调用结果通过notifyPrepareResultToEIS方法传回EIS.如Listing5所示。
Listing 5 Notifying the Prepare Result to EISprivate void notifyPrepareResultToEIS(EISMessage psSignal, int xa_result) {
// Logic to inform the EIS about the prepare call
// This uses the outbound connectivity for connecting to the EIS
FRSConnection connection = FRSConnectionFactory.createConnection();
PrepareSignalResult PREPARE_MESSAGE = new PrepareSignalResult(psSignal, xa_result);
connection.sendPrepareMessage(PREPARE_MESSAGE);
}
}
为了发送预编译结果,资源适配器得获得一个连接以发送一个消息给EIS的边界通道。
一旦预编译调用的结果被接收,EIS将决定是否提交或回退事务。这个过程和预编译一样:
1.EIS用Xid事务发送一个 提交/回退 的消息。
2.资源适配器在XATerminator 对象上调用 提交/回退 操作。
3.XATerminator 对象提交/ 回退 标记Xid 的事务。
紧急故障恢复
任何关于事务的话题不能没有至少一个紧急故障恢复的涉及,虽然实现超出了这篇文章的范围。Java Connector Architecture 提供为EIS或 应用服务器故障 实现故障恢复的空间。
.如果在一个应用服务器在启动的事务(没有预编译的事务)中发生故障,EIS将中止这个事务。同样的,如果EIS在启动事务发生故障,资源适配器将中止它。
.如果一个应用服务在一个不确定的事务(事务已经准备好了但是没有提交)中下降,EIS将试着和应用服务建立联系并且完成这个事务。如果EIS事故在一个不确定事务中产生,
资源适配器等到EIS返回并且试着完成这个事务。应用服务调用 getXAResource(..) 方法当它从一个故障中恢复,检索为各自的ActivationSpecs 分配的XAResources.然后它将为每个XAResource获得的调用恢复工作。
小节
从一个不同平台引入一个额外的事务到j2ee平台很困难,在JCA1.5的到来之前,这种工作几乎不可能想象。事务流程已经为注入事务从现有的系统比如 CICS,SAP等等到现代的j2ee应用平台铺平了一条道路。
参考
Java 2 Platform, Enterprise Edition (J2EE)
Java Connector Architecture (JCA)
---------------------------------------------------------------------------------------------------------------