本文最后一次修改日期:2013-06-16
上一个例子中,方法doTran1和doTran2是在一个类中,实际情况中,这两个方法往往来自不同的类,比如可能来自两个不同的EJB。这时,如何保证全局的事务呢?
测试环境:1个WebLogic Server,两个Oracle XE数据库,其中WebLogic Server上建立了两个DataSource指向两个Oracle XE数据库;两个EJB,部署到同一个WebLogic Server上。
1. 创建EJB
右键选择增加的方法:doTran1,选择暴露到Remote和Local Interface中。
同时,注意到我们可以在doTran1方法上增加事务属性,这里我们选择TransactionAttributeType.REQUIRED。
EJB 完整代码如下(另一个EJB也是同样的逻辑):
package model;
import java.sql.Connection;
import java.sql.Statement;
import javax.annotation.Resource;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.sql.DataSource;
@Stateless(name = "DoTran1SessionEJB", mappedName = "XATest-Model-DoTran1SessionEJB")
public class DoTran1SessionEJBBean implements DoTran1SessionEJB, DoTran1SessionEJBLocal {
@Resource
SessionContext sessionContext;
@Resource(name = "jdbc/hr1DS")
DataSource hr1DS;
public DoTran1SessionEJBBean() {
}
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void doTran1() throws Exception {
System.out.println("Hello doTran1");
Connection hr1 = hr1DS.getConnection();
hr1.setAutoCommit(false);
Statement stm1 = hr1.createStatement();
stm1.execute("DELETE FROM jobs WHERE job_id='CEO1'");
stm1.execute("INSERT INTO jobs VALUES('CEO1', 'CEO1', 1,2)");
stm1.close();
if (hr1 != null)
hr1.close();
}
}
注意这里使用了依赖注入的方式“注入了”DataSource。
2. 创建每个EJB测试的Client类,确保测试成功。
3. 根据每个EJB测试的Client类,创建一个测试两个EJB的Client类。
package model;
import java.util.Hashtable;
import javax.naming.CommunicationException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.transaction.UserTransaction;
public class DoTranSessionEJBBeanClient {
public DoTranSessionEJBBeanClient() {
super();
}
public static void main(String[] args) {
UserTransaction tran = null;
try {
final Context context = getInitialContext();
tran = (UserTransaction)context.lookup("javax.transaction.UserTransaction");
tran.begin();
DoTran1SessionEJB doTran1SessionEJB =
(DoTran1SessionEJB)context.lookup("XATest-Model-DoTran1SessionEJB#model.DoTran1SessionEJB");
doTran1SessionEJB.doTran1();
DoTran2SessionEJB doTran2SessionEJB =
(DoTran2SessionEJB)context.lookup("XATest-Model-DoTran2SessionEJB#model.DoTran2SessionEJB");
doTran2SessionEJB.doTran2();
tran.commit();
} catch (CommunicationException ex) {
System.out.println(ex.getClass().getName());
System.out.println(ex.getRootCause().getLocalizedMessage());
System.out.println("\n*** A CommunicationException was raised. This typically\n*** occurs when the target WebLogic server is not running.\n");
} catch (Exception e) {
e.printStackTrace();
try {
tran.rollback();
} catch (Exception ex) {
System.out.println("Rollback Exception: " + ex);
}
}
}
private static Context getInitialContext() throws NamingException {
Hashtable env = new Hashtable();
// WebLogic Server 10.x connection details
env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
env.put(Context.PROVIDER_URL, "t3://127.0.0.1:7101");
return new InitialContext(env);
}
}
4. 测试
测试结果应该和上一个实验一样。
Project 下载:XATest.7z