Transaction does not rollback on exception

122 views
Skip to first unread message

David Hofmann

unread,
Nov 5, 2016, 9:20:22 AM11/5/16
to Ebean ORM
ServerConfig
ServerConfig config = new ServerConfig();
config.setDataSource(ds);
config.setName("db");
config.setAutoCommitMode(false);
config.setDatabasePlatform(new PostgresPlatform());
config.setRegister(true);
config.setDefaultServer(true);
config.setTransactionRollbackOnChecked(true);
config.addPackage(Usuario.class.getPackage().getName());

This rollbacks ok

        EbeanServer des = null;
try {
des = Ebean.getDefaultServer();
des.beginTransaction();

// code that saves something and then throws Exception

des.commitTransaction();
} catch (Exception e) {
try {
des.rollbackTransaction();
} catch (Exception ie) {
ie.printStackTrace();
throw new RuntimeException(e);
}
} finally {
try {
des.endTransaction();
} catch (Exception ie) {
ie.printStackTrace();
}
}
}

This code doesn't rollback
EbeanServer des = Ebean.getDefaultServer();
des.execute(
TxScope.requiresNew().setRollbackFor(Exception.class),
() -> {
            // code that saves something and then throws Exception            
            }
);


Am I missing something?

Rob Bygrave

unread,
Nov 6, 2016, 1:14:55 AM11/6/16
to ebean@googlegroups
> Am I missing something?

Maybe. I can't get your case to reproduce (and actually you can't throw Exception without a compiler error so I'm not sure exactly what your code in the lamda looks like?).

That is the following works as expected:



package main;

import com.avaje.ebean.Ebean;
import com.avaje.ebean.EbeanServer;
import com.avaje.ebean.EbeanServerFactory;
import com.avaje.ebean.TxScope;
import com.avaje.ebean.config.ServerConfig;
import org.example.domain.Country;

import static org.assertj.core.api.Assertions.assertThat;

public class TxExample {

  private ServerConfig createConfig() {


    ServerConfig config = new ServerConfig();
    //config.setDataSource(ds);
    config.setName("db");

    // Rob: I'll just use the Ebean supplied DataSource implementation (because it is very good and supplied)
    config.loadFromProperties();
    config.loadTestProperties();
  
    // Rob: Note that this will not fix/sort out a DataSource that defaults autoCommit to true
    config.setAutoCommitMode(false);

//    config.setDatabasePlatform(new PostgresPlatform());
    config.setRegister(true);
    config.setDefaultServer(true);
    config.setTransactionRollbackOnChecked(true);
    config.addPackage("org.example.domain");

    return config;
  }

  public static void main(String[] args) {

    new TxExample().doIt();
  }

  public void doIt() {

    EbeanServer server = EbeanServerFactory.create(createConfig());
    try {
      // Rob: Note des and server are exactly the same instance ...
      //EbeanServer des = Ebean.getDefaultServer();
      server.execute(

          TxScope.requiresNew().setRollbackFor(Exception.class),
          () -> {

            // code that saves something and then throws Exception

            Country sa = new Country("SA", "South Africa");
            sa.save();

            throw new RuntimeException("Yeah, nah!!");
          }
      );
    } catch (Exception e) {
      System.out.println("Expecting Yeah Nah exception: "+e);
      Country sa = Country.find.byId("SA");
      assertThat(sa).isNull();
    }
  }
}


Producing logs of:


18:52:25.574 [main] INFO  c.a.e.s.c.b.BootupClassPathSearch - Classpath search entities[9] searchTime[58] in packages[[org.example.domain]]
18:52:25.589 [main] INFO  o.a.datasource.pool.ConnectionPool - DataSourcePool [db] autoCommit[false] transIsolation[READ_COMMITTED] min[2] max[100]
18:52:25.711 [main] INFO  c.a.ebean.internal.DefaultContainer - DatabasePlatform name:db platform:h2
18:52:26.005 [main] TRACE org.avaje.ebean.TXN - txn[1001] Begin
18:52:26.006 [main] INFO  org.avaje.dbmigration.ddl.DdlRunner - Executing db-create-all.sql - 28 statements
18:52:26.125 [main] DEBUG org.avaje.ebean.TXN - txn[1001] Commit
18:52:26.185 [main] TRACE org.avaje.ebean.TXN - txn[1002] Begin
18:52:26.185 [main] INFO  org.avaje.dbmigration.ddl.DdlRunner - Executing extra-dll - 1 statements
18:52:26.187 [main] DEBUG org.avaje.ebean.TXN - txn[1002] Commit
18:52:26.256 [main] TRACE org.avaje.ebean.TXN - txn[1003] Begin
18:52:26.263 [main] DEBUG org.avaje.ebean.SQL - txn[1003] insert into o_country (code, name) values (?,?); --bind(SA,South Africa,)
18:52:26.265 [main] DEBUG org.avaje.ebean.SUM - txn[1003] Inserted [Country] [SA]
18:52:26.267 [main] DEBUG org.avaje.ebean.TXN - txn[1003] Rollback error: java.lang.RuntimeException: Yeah, nah!! stack0: main.TxExample.lambda$doIt$0(TxExample.java:50)
Expecting Yeah Nah exception: java.lang.RuntimeException: Yeah, nah!!
18:52:26.298 [main] DEBUG org.avaje.ebean.SQL - txn[1004] select t0.code c0, t0.name c1 from o_country t0 where t0.code = ?  ; --bind(SA)
18:52:26.298 [main] DEBUG org.avaje.ebean.SUM - txn[1004] FindBean type[Country] origin[-YgOm.pCARS.CVgDXh] exeMicros[5657] rows[0] bind[SA]


As you can see our insert is in Transaction 1003 and that is rolled back, and in transaction 1004 we try to fetch SA and it is not there (0 rows and assertThat(sa).isNull(); passes)


Notes:
------------------------

1) Your example code supplied a DataSource (as opposed to using the Ebean/avaje one). You should check that the DataSource used is not using autoCommit.

2) Increase the logging for SQL and TXN via:

<logger name="org.avaje.ebean.SQL" level="TRACE" />
<logger name="org.avaje.ebean.TXN" level="TRACE" />
<logger name="org.avaje.ebean.SUM" level="TRACE" />

... you ought to see similar logging to that above.


3) Maybe there is some other difference. I had to adjust the code to throw RuntimeException so maybe you can supply and exact case (perhaps as a branch or PR to https://github.com/ebean-orm-examples/example-java8



Note that if we don't have the outer try catch we see the stack trace but most importantly we see the txn[1003] Rollback error: ... message

19:05:49.396 [main] TRACE org.avaje.ebean.TXN - txn[1003] Begin
19:05:49.401 [main] DEBUG org.avaje.ebean.SQL - txn[1003] insert into o_country (code, name) values (?,?); --bind(SA,South Africa,)
19:05:49.402 [main] DEBUG org.avaje.ebean.SUM - txn[1003] Inserted [Country] [SA]
19:05:49.403 [main] DEBUG org.avaje.ebean.TXN - txn[1003] Rollback error: java.lang.RuntimeException: Yeah, nah!! stack0: main.TxExample.lambda$doIt$0(TxExample.java:50)
Exception in thread "main" java.lang.RuntimeException: Yeah, nah!!
    at main.TxExample.lambda$doIt$0(TxExample.java:50)
    at com.avaje.ebeaninternal.server.core.DefaultServer.execute(DefaultServer.java:608)
    at main.TxExample.doIt(TxExample.java:41)
    at main.TxExample.main(TxExample.java:33)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)




Cheers, Rob.



--

---
You received this message because you are subscribed to the Google Groups "Ebean ORM" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ebean+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

David Hofmann

unread,
Nov 6, 2016, 6:04:42 AM11/6/16
to eb...@googlegroups.com
Thanks for the answer Rob. 
 
Maybe. I can't get your case to reproduce (and actually you can't throw Exception without a compiler error so I'm not sure exactly what your code in the lamda looks like?).
Sorry I meant RuntimeException

Notes:
------------------------

1) Your example code supplied a DataSource (as opposed to using the Ebean/avaje one). You should check that the DataSource used is not using autoCommit.
I am using ebean inside wildlfy in a java ee 7 environment. Can not ebean just set the javax.sql.Connection to autocommit=false when it aquires one connection from the DS?

2) Increase the logging for SQL and TXN via:

<logger name="org.avaje.ebean.SQL" level="TRACE" />
<logger name="org.avaje.ebean.TXN" level="TRACE" />
<logger name="org.avaje.ebean.SUM" level="TRACE" />

... you ought to see similar logging to that above.

Yeah, I got this working, it took me a while though. I will prepare a document to showcase how to enable logging inside wildfly and glassfish/payara for people needing to use it in those environments.
 
3) Maybe there is some other difference. I had to adjust the code to throw RuntimeException so maybe you can supply and exact case (perhaps as a branch or PR to https://github.com/ebean-orm-examples/example-java8
Will try to do it soon



To unsubscribe from this group and stop receiving emails from it, send an email to ebean+un...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--

---
You received this message because you are subscribed to a topic in the Google Groups "Ebean ORM" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/ebean/tOzDSBwty_Y/unsubscribe.
To unsubscribe from this group and all its topics, send an email to ebean+un...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages