web应用跨容器调用EJB的异常问题

08-05-16 chinee

有两个容器,一个是jboss,一个是websphere,

websphere里放一个web应用,jboss里放一个EJB,

web调用ejb,并试图使用websphere的JTA事务,管理jboss那边EJB的事务,

调用的ejb的事务类型 <transaction-type>Container </transaction-type>, <trans-attribute>Mandatory </trans-attribute>

报错说:Transaction Required Exception

即表示调用EJB时,没有启用JTA事务,这是什么原因呢???

请帮忙解答,谢谢了!

web侧的部分代码如下:

//绑定websphere的Usertransaction

Properties h = new Properties();

h.put(Context.INITIAL_CONTEXT_FACTORY,

"com.ibm.websphere.naming.WsnInitialContextFactory");

h.put(Context.PROVIDER_URL, "iiop://10.80.12.124:2809/");

InitialContext ctx = new InitialContext(h);

tx = (UserTransaction) ctx.lookup("jta/usertransaction");

//启用JTA事务

tx.begin();

//绑定jboss侧的EJB

Properties env = new Properties();

env.setProperty(Context.INITIAL_CONTEXT_FACTORY,

"org.jnp.interfaces.NamingContextFactory");

env.setProperty(Context.URL_PKG_PREFIXES,

"org.jboss.naming:org.jnp.interfaces");

env.setProperty(Context.PROVIDER_URL, "jnp://10.80.12.124:1099");

Context enc = new InitialContext(env);

// 得到本地接口

UserServiceHome home = (UserServiceHome) enc

.lookup("ejb/UserService");

// 得到远程对象

UserService userService = home.create();

String value = String.valueOf(System.currentTimeMillis());

// 调用远程对象的方法

String msg = userService.listAllUsers(value);

// 提交JTA事务

tx.commit();

ctx.close();

enc.close();

chinee
2008-05-16 11:18

我在这个事务中绑定websphere自己的XA数据源,执行事务没有问题的

Properties h = new Properties();

h.put(Context.INITIAL_CONTEXT_FACTORY,

"com.ibm.websphere.naming.WsnInitialContextFactory");

h.put(Context.PROVIDER_URL, "iiop://10.80.12.124:2809/");

InitialContext ctx = new InitialContext(h);

tx = (UserTransaction) ctx.lookup("jta/usertransaction");

tx.begin();

ctx = new InitialContext();

DataSource ds = (DataSource) ctx.lookup("mydbxa");

conn = ds.getConnection();

PreparedStatement stmt = conn

.prepareStatement("insert into c(c.compid,c.userid) values(?,?)");

String value = String.valueOf(System.currentTimeMillis());

stmt.setString(1, value);

stmt.setString(2, value);

stmt.executeUpdate();

tx.commit();

ctx.close();

chinee
2008-05-16 11:31

后来我尝试着把<transaction-type>Container</transaction-type>、

<trans-attribute>Mandatory</trans-attribute>

改成<transaction-type>Bean</transaction-type>、

<trans-attribute>Mandatory</trans-attribute>

虽然不报错,能进入EJB执行,但是事务后提交了,没有体现提交的效果,rollback也一样。

如果是使用<transaction-type>Bean</transaction-type>、<trans-attribute>Mandatory</trans-attribute>,也是要求在调用 bean 时客户端必须已经启动了一个事务。

同样是这样的要求,为什么使用<transaction-type>Container</transaction-type>和使用<transaction-type>Bean</transaction-type>会有不同结果???

我使用的是EJB2,EJB方面我是新手,请大家帮帮我!

banq
2008-05-17 12:52

><transaction-type>Container</transaction-type>和使用<transaction-type>Bean</transaction-type>会有不同结果???

一个是Container也就是JBoss自己管理事务,自己启动,而Bean则是要求你程序自己必须启动,你从Webshrer启动的事务必须让JBoss知道,你这个方式很少见。

一般EJB和事务都是在一个容器实现,而你分开,非常怪异,你要websphere事务,那么就让EJB在websphere中实现,而且websphere这些商业产品EJB容器肯定比JBossm开源要强,所以,一般思路是:JBoss/Tomcat中运行Web程序,EJB在Websphere,否则你花大钱买来的Websphere只做相当于tomcat的WEB作用,非常浪费哦。

当然,有可能有历史背景和各种原因。

xmuzyu
2008-05-24 01:52

我觉得你在使用CMT的时候,因为你的事务属性是Mandatory,所以要求websphere服务器中的事务必须要传递到JBoss中,而你现在没有传递过来所以就报错,要求客户启动事务。而你使用BMT的时候,你调用EJB的事务是你自己启动的,相当与已经启动了事务。但是这两个事务不是一样的,从而导致你的事务提交后没有体现出结果。不知道对不对,我是这么猜想的。