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的事务是你自己启动的,相当与已经启动了事务。但是这两个事务不是一样的,从而导致你的事务提交后没有体现出结果。不知道对不对,我是这么猜想的。