-
Transaction
Transaction是J2EE架构中重要的一部分。简单的讲,Transaction意味着某一系列的操作要么全做,要么全不做。Transaction 需要遵循ACID 规则:
Atomicity:原子性,Transaction作为一个整体,要么完全完成要么完全不做
Cosistensy:Transaction操作前后,系统数据都要处于一致的,无矛盾的状态
Isolation:Transaction之间互相独立,互不影响,Transaction的任何中间结果不应该被看到
Durability:Transaction一旦完成,结果被保存,不可撤销
关于Transaction的基本概念介绍,参见:
http://www.subbu.org/articles/transactions/NutsAndBoltsOfTP.html
-
JCA Adapter 中的Transaction
JCA Adapter作为J2EE规范的一部分,需要支持在J2EE多component协作环境下的Transaction。关于J2EE的Transaction要求,参见:J2EE Specification 1.4, chapter 4。具体JCA Adapter 规范要求,参见:JCA1.5 specification, Chapter 7, Transaction Management ; Chapter 12, section 12.5.6,12.5.7;Chapter 14 Transaction inflow。
-
Outbound Transaction管理
JCA Adapter 可以支持也可以不支持outbound Transaction,这通过在ra.xml 中来定义。
The transaction-supportType specifies the level of
transaction support provided by the resource adapter. It is
used by transaction-support elements.
The value must be one of the following:
NoTransaction
LocalTransaction
XATransaction
-
Local vs. XA transaction
Local Transaction 表示Transaction只在自己Adapter处理,不需要外部Transaction Manager 参与。Adapter需要实现如下接口,
public interface javax.resource.spi.LocalTransaction {
public void begin() throws ResourceException;
public void commit() throws ResourceException;
public void rollback() throws ResourceException;
}
并且实现ManagedConnection接口中的getLocalTransaction方法。
public interface javax.resource.spi.ManagedConnection {
public XAResource getXAResource() throws ResourceException;
public LocalTransaction getLocalTransaction()
}
这些方法可供adapter的调用者或app server来调用实现transacation管理。
XA transaction 表示Adapter支持由外部Transaction Manager所管理的多个component参与的Transaction。Adapter需要实现javax.transaction.xa.XAResource接口,并实现ManagedConnection中的getXAResource()方法。
-
Component-managed vs. container-managed
JCA Adapter本身是J2EE规范中的一种Resource,类似于JDBC driver,是被动的component。如何参与Transaction,是由使用Adapter的component 来决定的。以调用者是Session Bean为例,Session Bean deploy 时可以选择bean-managed 或container-managed Transaction管理。Container-managed情况下,transaction由Application server自动管理。如果选择bean-managed就表明是Component-managed方式,在这种方式下,server不会主动调用connection上关于transaction 的接口,需要调用者通过编程来调用。
SAP Adapter支持Local transaction,以下以SAP Adapter为例说明不同情况下过程的区别:
如下,用一个Stateless session bean来调用Adapter。Transaction Type 是 Bean,即Component-managed。
-
Container-managed,调用方不使用Transaction API
该EJB实现了两个方法:
不使用Transaction API :
public void callBapi() throws RemoteException {
try {
InitialContext initCx = new InitialContext();
String jndi = "BAPITx/SAPOutboundInterface_CF";
ConnectionFactory cxf = (ConnectionFactory) initCx.lookup(jndi);
Connection connection = null;
connection = cxf.getConnection();
Interaction interaction = null;
try {
interaction = connection.createInteraction();
} catch (ResourceException e) {
e.printStackTrace();
}
WBIInteractionSpec interactionSpec = new WBIInteractionSpec();
String functionName = "Create";
interactionSpec.setFunctionName(functionName);
WBIRecord inputRecord = new WBIRecord();
DataObject inputObject = null;
inputObject = AdapterBOUtil
.createDataObject( "http://www.ibm.com/xmlns/prod/websphere/j2ca/sap/sapcustomertxnbg",
"SapCustomerTxnBG");
inputObject.set("verb", "Create");
DataObject wrapper = inputObject.createDataObject("SapCustomerTxn");
DataObject createWreg = wrapper
.createDataObject("SapBapiCustomerCreatepwreg");
createWreg.set("CustomerNumber", "10");
inputRecord.setDataObject(inputObject);
Record utputRecord = interaction.execute(interactionSpec,
inputRecord);
DataObject utputObject = ((WBIRecord) outputRecord)
.getDataObject();
} catch (Exception e) {
e.printStackTrace();
}
}
执行的log如下,不涉及任何LocalTransaction 相关调用:
[7/10/06 13:49:14:245 CST] 00000054 SystemOut O Call BAPI....................
[7/10/06 13:49:14:245 CST] 00000054 SystemOut O Initial JNDI Context created
[7/10/06 13:49:14:245 CST] 00000054 SystemOut O
[7/10/06 13:49:14:245 CST] 00000054 SystemOut O javax.naming.InitialContext@59e677b
[7/10/06 13:49:14:308 CST] 00000054 SystemOut O Connection factory found. It is:
[7/10/06 13:49:14:308 CST] 00000054 SystemOut O
[7/10/06 13:49:14:308 CST] 00000054 SystemOut O com.ibm.j2ca.sap.SAPConnectionFactory@5b1fa77b
[7/10/06 13:49:15:776 CST] 00000054 SystemOut O Connection requested. The connection is:
[7/10/06 13:49:15:776 CST] 00000054 SystemOut O
[7/10/06 13:49:15:776 CST] 00000054 SystemOut O com.ibm.j2ca.sap.SAPConnection@7ca0677c
[7/10/06 13:49:15:792 CST] 00000054 SystemOut O Interaction created. The interaction is:
[7/10/06 13:49:15:792 CST] 00000054 SystemOut O
[7/10/06 13:49:15:792 CST] 00000054 SystemOut O com.ibm.j2ca.sap.SAPInteraction@e39677c
[7/10/06 13:49:15:808 CST] 00000054 SystemOut O Interaction spec created. The interaction spec is:
[7/10/06 13:49:15:808 CST] 00000054 SystemOut O
[7/10/06 13:49:15:808 CST] 00000054 SystemOut O com.ibm.j2ca.base.WBIInteractionSpec@190de77c
[7/10/06 13:49:15:808 CST] 00000054 SystemOut O Function name is:
[7/10/06 13:49:15:808 CST] 00000054 SystemOut O
[7/10/06 13:49:15:808 CST] 00000054 SystemOut O Create
[7/10/06 13:49:15:886 CST] 00000054 SystemOut O Input record created. Set input data object
[7/10/06 13:49:16:214 CST] 00000054 ResourceAdapt I SAPInteraction execute executing BAPI
[7/10/06 13:49:19:573 CST] 00000054 SystemOut O Interaction executed. Output object is received
-
Component-managed,调用方使用Transaction API
另一个函数使用了UserTransaction API:
public void callBapiTx() throws RemoteException {
try {
InitialContext initCx = new InitialContext();
String jndi = "BAPITx/SAPOutboundInterface_CF";
UserTransaction ut = (UserTransaction)this.getSessionContext().getUserTransaction();
System.out.println("*************Transaction Begin*********************");
ut.begin();//Transaction Begin here
ConnectionFactory cxf = (ConnectionFactory) initCx.lookup(jndi);
Connection connection = null;
connection = cxf.getConnection();
Interaction interaction = null;
try {
interaction = connection.createInteraction();
} catch (ResourceException e) {
e.printStackTrace();
}
WBIRecord inputRecord = new WBIRecord();
DataObject inputObject = null;
inputObject = AdapterBOUtil
.createDataObject(
"http://www.ibm.com/xmlns/prod/websphere/j2ca/sap/sapcustomertxnbg",
"SapCustomerTxnBG");
inputObject.set("verb", "Create");
DataObject wrapper = inputObject.createDataObject("SapCustomerTxn");
DataObject createWreg = wrapper
.createDataObject("SapBapiCustomerCreatepwreg");
createWreg.set("CustomerNumber", "10");
DataObject Wreg = wrapper.createDataObject("SapBapiCustomerGetpwreg");
getWreg.set("CustomerNumber", "10");
inputRecord.setDataObject(inputObject);
WBIInteractionSpec interactionSpec = new WBIInteractionSpec();
String functionName = "Create";
interactionSpec.setFunctionName(functionName);
try{
Record utputRecord = interaction.execute(interactionSpec,
inputRecord);
DataObject utputObject = ((WBIRecord) outputRecord)
.getDataObject();
ut.commit();// Execute success, commit the transaction.
System.out.println("***Transaction Commited*************************");
} catch (Exception e) {
ut.rollback();//Execute failure, rollback transaction
System.out.println("***Transaction Rollbacked**************************");
}
} catch (Exception e) {
e.printStackTrace();
}
}
执行的log如下,注意红色部分:
[7/10/06 13:17:06:022 CST] 00000054 SystemOut O ******************Transaction Begin*********************
[7/10/06 13:17:06:022 CST] 00000054 ResourceAdapt I SAPManagedConnection begin ++Inside (SPI) the MANAGED Resource Adapter! Calling SAPManagedConnection.begin().
[7/10/06 13:17:06:022 CST] 00000054 SystemOut O Interaction spec created. The interaction spec is:
[7/10/06 13:17:06:022 CST] 00000054 SystemOut O com.ibm.j2ca.base.WBIInteractionSpec@5da16765
[7/10/06 13:17:06:022 CST] 00000054 SystemOut O Function name is:
[7/10/06 13:17:06:022 CST] 00000054 SystemOut O Create
[7/10/06 13:17:06:038 CST] 00000054 ResourceAdapt I SAPInteraction execute executing BAPI
[7/10/06 13:17:09:194 CST] 00000054 SystemOut O Interaction executed. Output object is received
[7/10/06 13:17:09:194 CST] 00000054 ResourceAdapt I com.ibm.j2ca.sap.bapi.SapBAPIInvoker commit() ++Inside (SPI)the MANAGED Resource Adapter !calling SAPManagedConnection.commit()
[7/10/06 13:17:09:429 CST] 00000054 SystemOut O **********************Transaction Commited*************************
-
Container-managed,调用方不使用Transaction API
而同样的callBapi 在container-managed环境下执行的log却不相同,看如下例子,注意红色部分,app sever自动调用了Transaction管理:
[7/10/06 13:37:38:054 CST] 00000057 SystemOut O Call BAPI....................
[7/10/06 13:37:38:054 CST] 00000057 SystemOut O Initial JNDI Context created
[7/10/06 13:37:38:054 CST] 00000057 SystemOut O
[7/10/06 13:37:38:054 CST] 00000057 SystemOut O javax.naming.InitialContext@32e16725
[7/10/06 13:37:38:132 CST] 00000057 SystemOut O Connection factory found. It is:
[7/10/06 13:37:38:132 CST] 00000057 SystemOut O
[7/10/06 13:37:38:132 CST] 00000057 SystemOut O com.ibm.j2ca.sap.SAPConnectionFactory@730b6726
[7/10/06 13:37:38:148 CST] 00000057 ResourceAdapt I SAPManagedConnection begin ++Inside (SPI) the MANAGED Resource Adapter! Calling SAPManagedConnection.begin().
[7/10/06 13:37:40:226 CST] 00000057 SystemOut O Connection requested. The connection is:
[7/10/06 13:37:40:226 CST] 00000057 SystemOut O
[7/10/06 13:37:40:226 CST] 00000057 SystemOut O com.ibm.j2ca.sap.SAPConnection@7421e727
[7/10/06 13:37:40:242 CST] 00000057 SystemOut O Interaction created. The interaction is:
[7/10/06 13:37:40:258 CST] 00000057 SystemOut O
[7/10/06 13:37:40:258 CST] 00000057 SystemOut O com.ibm.j2ca.sap.SAPInteraction@856727
[7/10/06 13:37:40:258 CST] 00000057 SystemOut O Interaction spec created. The interaction spec is:
[7/10/06 13:37:40:258 CST] 00000057 SystemOut O
[7/10/06 13:37:40:258 CST] 00000057 SystemOut O com.ibm.j2ca.base.WBIInteractionSpec@1f7d2727
[7/10/06 13:37:40:258 CST] 00000057 SystemOut O Function name is:
[7/10/06 13:37:40:258 CST] 00000057 SystemOut O
[7/10/06 13:37:40:258 CST] 00000057 SystemOut O Create
[7/10/06 13:37:40:492 CST] 00000057 SystemOut O Input record created. Set input data object
[7/10/06 13:37:41:179 CST] 00000057 ResourceAdapt I SAPInteraction execute executing BAPI
[7/10/06 13:37:45:258 CST] 00000057 SystemOut O Interaction executed. Output object is received
[7/10/06 13:37:45:273 CST] 00000057 ResourceAdapt I com.ibm.j2ca.sap.bapi.SapBAPIInvoker commit() ++Inside (SPI)the MANAGED Resource Adapter !calling SAPManagedConnection.commit()
-
Inbound Transaction
Inbound Transaction同样取决于Adapter的使用者。Event Deliver是否是Transacted 要看Endpoint是否是支持Transaction。Adapter通过询问app server是否支持Transaction来决定自己如何deliver event。
-
Transacted event deliver
这种情况下,在创建Endpoint的时候,adapter传递XAResource给server,来跟踪Transaction的状态。有两种方式:
A:只传递XAResource给server,由server完全来控制
B:传递XAResource给server,并通过调用server端的API:beforeDelivery 和 afterDelivery来控制Transaction的开始和结束。
从Base Class的FS来看,Websphere adapter 使用Transacted event deliver来实现Assured Once delivery,并且采用的是方式B。(参见: IBM WebSphere Adapter Foundation Classes 1.1.0 FS R9 6.2.4.5)所以要测试Assured Once delivery,必须保证endpoint,通常是MDB,支持Transaction。
-
Non-transacted Delivery
这种情况下,Adapter只能通过消息接口的返回来确定消息的状态。
-
Transacted Delivery Using an Imported Transaction
这种情况下,Adapter在消息源——通常是EIS——发起的Transaction之内来Deliver 消息。JCA Specification chapter 14专门讨论这一情况。目前的Websphere Adapter没有用到。
对于MDB来说,无论是bean-managed 或container-managed Transaction,都是支持Transaction的Endpoint。
作者简介:
刘冬清 IBM CDL WeSphere Adapters 功能测试Tech Lead,5+ 年Java 开发测试经验。兴趣:Java 开发,敏捷测试
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/21456021/viewspace-606355/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/21456021/viewspace-606355/
本文深入探讨了J2EE架构中的事务管理机制,包括事务的基本概念、ACID特性及其实现方式。详细介绍了JCA适配器如何支持本地事务和XA事务,以及组件管理和容器管理下的事务行为差异。

1824

被折叠的 条评论
为什么被折叠?



