【问题标题】:EJB : Achieving Transaction propagation through Bean Managed Transaction?EJB:通过 Bean Managed Transaction 实现事务传播?
【发布时间】:2013-10-28 09:14:15
【问题描述】:

我需要尝试跨多个有状态 bean 实现事务传播 我的应用程序中有 3 个有状态 EJB。开始和结束事务通过远程接口方法调用控制为外部 Java 应用程序。

@Remote
@Stateful
public class MyEJB1 implements RemoteEJB1{
@EJB
 private RemoteEJB2 ejb2;
@Resource
UserTransaction utx;

public void startTransaction() {
    try {

        utx.begin();

    } catch (NotSupportedException e) {
        throw new EJBException(e);
    } catch (SystemException e) {
        throw new EJBException(e);
    }
}

public void commitTransaction() {
    try {
        utx.commit();

    } catch (SecurityException e) {
        throw new EJBException(e);
    } catch (IllegalStateException e) {
        throw new EJBException(e);
    } catch (RollbackException e) {
        throw new EJBException(e);
    } catch (HeuristicMixedException e) {
        throw new EJBException(e);
    } catch (HeuristicRollbackException e) {
        throw new EJBException(e);
    } catch (SystemException e) {
        throw new EJBException(e);
    }
}

public RemoteEJB2 getEJB2() {
    return ejb2;
}

}


public class MyEJB2 implements RemoteEJB2{

@EJB
private RemoteEJB3 ejb3;
@Resource(name = "java:jboss/datasources/MyDS")
private DataSource ds;

public RemoteEJB3 getEJB3() {
    return ejb3;
}

@TransactionAttribute(TransactionAttributeType.MANDATORY)
public void insertElement(String elementName) {
    PreparedStatement pStat = null;
    Connection con = null;
    try {
        con = ds.getConnection();
        String sql = "insert into TRANSACTIONTEST(COL1,COL2) values(?,?)";
        pStat = con.prepareStatement(sql);
        pStat.setString(1, elementName);
        pStat.setDouble(2, Math.random());
        pStat.executeUpdate();

    } catch (Exception ex) {
        ex.printStackTrace();
    } finally {
        try {
            con.close();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}
}

public class MyEJB3 implements RemoteEJB3{
@Resource(name="java:jboss/datasources/MyDS")
private DataSource ds;

@TransactionAttribute(TransactionAttributeType.MANDATORY)
public void updateElement(String newName) {
    PreparedStatement pStat = null;
    Connection con = null;
    try{    con = getDs().getConnection();
        String sql ="update  TRANSACTIONTEST set COL1=?";           
        pStat = con.prepareStatement(sql);
        pStat.setString(1, newName);        
        pStat.executeUpdate();

    }catch(Exception ex){
        ex.printStackTrace();
    }finally{
        try {
            con.close();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}
}

测试类:

public class MyTest{
public static void main(String[] args) throws Exception {
    final Hashtable jndiProperties = new Hashtable();
    jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
    final Context context = new InitialContext(jndiProperties);
    MyEJB1 ejb1 = context.lookup("ejb:/EJBTrials/MyEJB1!edu.in.ejbinterfaces. RemoteEJB1?stateful");

    ejb1.startTransaction();
    RemoteEJB2 ejb2 = ejb1.getEJB2();
    ejb2.insertElement (“Test”);
    RemoteEJB3 ejb3 = ejb2.getEJB3();
    ejb3.updateElement (“UpdatedTest”);
    ejb1.commitTransaction();
}
}

理想情况下,我希望在 RemoteEJB1 bean 上调用 commitTransaction() 后完成整个事务(数据库中的记录插入)。

我尝试了 EJB1 的 BMT 和 EJB2 和 EJB3 的 CMT 组合,这导致 EJBTransactionRequiredException 被抛出 我试着把所有的豆子都做成 BMT。然而,根据 EJB3.1 规范,BMT 不能跨多个 bean 传播。 您能否告诉我可以用来解决此问题的任何想法/链接?

参考应用服务器:JBOSS AS 7.1

【问题讨论】:

  • 服务器应该如何链接ejb1ejb2 实例?的确,它们具有相同的经过身份验证的用户,但据服务器所知,它们可能被完全不同的、不相关的程序调用。您需要通过ejb1 调用ejb2ejb3 方法。
  • EJB1,EJB2,EJB3 表示标准 API 规范的接口和对象。因此,方法的合同是有约束力的,我在改变方面没有回旋余地。 API 规范的一个主要要求是模型和接口实现支持事务的可能性,事务控制将取决于我的输出的最终用户
  • 我知道。问题是服务器既不知道你的代码,也没有其他方法知道不同的bean在逻辑上是相关的,所以它不知道它们是否属于同一事务的一部分。您可以在有状态 EJB 中管理事务,因为服务器知道这些方法是相关的(因为您使用的是相同的 EJB)。

标签: java jakarta-ee jboss transactions ejb-3.1


【解决方案1】:

您能否告诉我可以用来解决此问题的任何想法/链接?

如果我正确理解您的问题,您需要的称为客户端管理的事务划分。与容器管理事务不同,在这种情况下,客户端负责设置事务边界(启动和提交/回滚事务)。你可以得到一些关于如何实现它的想法here

【讨论】:

  • 谢谢。链接中的内容帮助我解决了问题。 JBOSS AS7 补充阅读:link
猜你喜欢
  • 1970-01-01
  • 2015-03-10
  • 1970-01-01
  • 1970-01-01
  • 2010-11-19
  • 2014-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多