简体   繁体   English

容器管理事务 - 未标记为回滚

[英]Container Managed Transaction - Not marked for roll back

Bank.java银行.java

@Stateless
@Local
public class Bank implements IBank {

    @EJB
    IConfigBean iConfigBean;

    @EJB
    IDbs iDBS;

    @EJB
    IPosb iPosb;

    @Override
    public void doTransaction() {
        System.out.println("--Bank Transaction Started--");
        try {
            Config config1 = getConfig(1);
            iConfigBean.create(config1);

            iDBS.doDBSTransaction();

            Config config3 = getConfig(3);
            iConfigBean.create(config3);

            iPosb.doPOSBTransaction();

            Config config5 = getConfig(5);
            iConfigBean.create(config5);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("---Bank Exception--");
        }
        System.out.println("--Bank Transaction End--");
    }

    @Override
    public Config getConfig(int inserttionOrderNo) {
        Config config = new Config();
        config.setType("EJBTransactionTESTING - " + inserttionOrderNo);
        return config;
    }
}

DBS.java DBS.java

@Stateless
@Local
public class DBS implements IDbs {

    @EJB
    IConfigBean iConfigBean;

    @Override
    public void doDBSTransaction() {
        System.out.println("--DBS Transaction Started--");
        try {
            Config config2 = getConfig(2);
            iConfigBean.create(config2);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("--DBS Exception--");
        }
        System.out.println("--DBS Transaction End--");
    }

    @Override
    public Config getConfig(int inserttionOrderNo) {
        Config config = new Config();
        config.setType("EJBTransactionTESTING - " + inserttionOrderNo);
        return config;
    }

}

POSB.java POSB.java

@Stateless
@Local
public class POSB implements IPosb {

    @EJB
    IConfigBean iConfigBean;

    @Override
    public void doPOSBTransaction() {
        System.out.println("--POSB Transaction Started--");
        try {
            Config config4 = getConfig(4);
            iConfigBean.create(config4);
            if (true) {
                //For Test 1 
                //throw new NullPointerException(); 
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("--POSB Exception--");
        }
        if (true) {
            //For Test 2 
            // throw new NullPointerException();
        }
        System.out.println("--POSB Transaction End--");
    }

    @Override
    public Config getConfig(int inserttionOrderNo) {
        Config config = new Config();
        config.setType("EJBTransactionTESTING - " + inserttionOrderNo);
        return config;
    }
}

I am new to Stack Overflow and Its my new question so correct me If I am wrong.我是 Stack Overflow 的新手,这是我的新问题,如果我错了,请纠正我。

Environment is..环境是..

  • Windows 10 Windows 10
  • Java 1.8 Java 1.8
  • Eclipse Eclipse
  • Tomcat 8.5 Tomcat 8.5
  • EJB3 EJB3

I have Three stateless bean, Please look at the Sequence Diagram of the Transaction flow.我有三个无状态bean,请看事务流的序列图

I purposely making NullPointer Exception at two places during the transaction to know the difference and I have marked with Lightening Bold symbol in sequence diagram.我故意在交易过程中的两个地方制作 NullPointer Exception 以了解差异,并在序列图中用 Lightening Bold 符号标记。

I am not using any @TransactionAttribute to any methods.我没有对任何方法使用任何@TransactionAttribute。

Test 1 - Null Pointer in Inside the try block (Lightening Bold symbol with Green) When I start the testing, Got Null pointer exception and all the transaction are not marked for roll back and data also got inserted in db.测试 1 - 尝试块内的 Null 指针(带绿色的闪电粗体符号)当我开始测试时,出现 Null 指针异常并且所有事务都没有标记为回滚,并且数据也插入到了数据库中。

I can only see Null pointer exception in the console log.我只能在控制台日志中看到 Null 指针异常。

Test 2 - Null Pointer in Outside the try - catch method (Lightening Bold symbol with Red) When I start the testing, Got Null pointer exception plus EJBTransactionRolledbackException and all the transaction marked for roll back and no data inserted in db.测试 2 - Null 指针在 try - catch 方法之外(带红色的闪电粗体符号)当我开始测试时,得到 Null 指针异常加上 EJBTransactionRolledbackException 和所有标记为回滚的事务并且没有数据插入到数据库中。

I can see NullPointer and EJBTransactionRolledback Exception in the console log.我可以在控制台日志中看到 NullPointer 和 EJBTransactionRolledback 异常。

Question here is,这里的问题是,

  1. Why EJB transaction is not marked for roll back If I made Null pointer inside try block为什么 EJB 事务没有标记为回滚如果我在 try 块中创建了 Null 指针
  2. Why EJB transaction is roll back happens If I made null pointer outside try block为什么会发生 EJB 事务回滚如果我在 try 块之外创建了 null 指针

Thanks in advance.提前致谢。

Keep in mind EJB calls, all the "magic" made by container happens there, including transaction markup.请记住 EJB 调用,容器制造的所有“魔法”都发生在那里,包括事务标记。 It's possible due to the fact that EJB calls are not direct, but always go through proxy.这是可能的,因为 EJB 调用不是直接的,但总是通过代理 go。

You have such calls in your code:您的代码中有这样的调用:

iPosb.doPOSBTransaction(); 

So, if unchecked exception (NPE for example) is thrown in this method and not caught - it's ultimately caught by container due to EJB proxy wrapping the call above.因此,如果在此方法中抛出未经检查的异常(例如 NPE)并且未捕获 - 由于 EJB 代理包装了上面的调用,它最终被容器捕获。 In this case transaction only could be rolled back.在这种情况下,事务只能回滚。

Adding a call to a method of the same bean in your method (without using @EJB reference), does not change that:在您的方法中添加对同一 bean 的方法的调用(不使用 @EJB 引用)不会改变这一点:

@Override
public void doPOSBTransaction() {
    try {
        Config config4 = getConfig(4);
        iConfigBean.create(config4);
        if (true) {
            newMethod(); 
        }
    } catch (Exception e) {
        e.printStackTrace();
        System.out.println("--POSB Exception--");
    }
    if (true) {
        newMethod(); 
    }        
}

private void newMethod(){
    throw new RuntimeException();
}

You can easily check that commit/rollback behaviour is just the same in this case, no matter that a method is added to call stack.在这种情况下,您可以轻松检查提交/回滚行为是否相同,无论是否将方法添加到调用堆栈。

So the important thing you have to remember is that all container tricks work only on @EJB calls.因此,您必须记住的重要一点是,所有容器技巧仅适用于 @EJB 调用。 So, for example, it's pointless to place transactional annotation on a private method - it won't be used ever.因此,例如,将事务注释放在私有方法上是没有意义的——它永远不会被使用。

Another important point is about checked exceptions.另一个重要的一点是关于检查的异常。 By default these do not cause transaction rollback indeed.默认情况下,这些确实不会导致事务回滚。 But it's still possible to annotate your checked exception like below to make it rollback ongoing transaction:但是仍然可以像下面这样注释您的检查异常以使其回滚正在进行的事务:

@ApplicationException(rollback = true) 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM