@Override
@Transactional(type = TxType.REQUIRED)
public void method1(Product product1) {
removeProductAndAssociations(product1)
}
public void removeProductAndAssociations(Product product1) {EbeanServer server = productDAO.getServer();
server.beginTransaction();try {productDAO.update(product1);// further logicproductOptionsDAO.update(options1);server.commitTransaction();} finally {
server.endTransaction();
}}
In case of 500, I see that it doesn't completely rollback... the Product model classes are enhanced by ebean, service classes are not. How would one best do nested transactions, so that even in case of multiple methods annotated with @Transactional(type = TxType.REQUIRED) that are callled, it joins the exisiting transaction and doesn't start a new one. On an error it should completely rollback.
We are on Play 2.3.8, hence using 3.3.4 version of Ebean.Let me know if there any other major changes to be aware of in regard to transaction management in the more recent version of Ebean ! It would help us evaluate if it is worth the upgrade !
Hi Rob/CommunityI have found issues with getting the nested transactions to work with ebean. It will be of great help if you guys can kindly advice on how best to handle nested transactions !Ebean transaction page (http://ebean-orm.github.io/docs/transactions/) says : You must be using ENHANCEMENT for @Transactional to work. That means you must be enhancing the classes via IDE Plugin, Ant Task or javaagent. Refer to the user guide for more details on enhancement.This means that we cannot be using the @Transactional annotation in the service layer ?Service.java@Override
@Transactional(type = TxType.REQUIRED)
public void method1(Product product1) {removeProductAndAssociations(product1)}public void removeProductAndAssociations(Product product1) {EbeanServer server = productDAO.getServer();
server.beginTransaction();try {productDAO.update(product1);// further logicproductOptionsDAO.update(options1);server.commitTransaction();} finally {
server.endTransaction();
}}In case of 500, I see that it doesn't completely rollback... the Product model classes are enhanced by ebean, service classes are not. How would one best do nested transactions, so that even in case of multiple methods annotated with @Transactional(type = TxType.REQUIRED) that are callled, it joins the exisiting transaction and doesn't start a new one. On an error it should completely rollback.
--
---
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+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Thanks Rob for coming back on this ! Appreciate that
@Override
public void method1(Product product1) {
server.beginTransaction();try {
removeProduct(product1)
removeProductAssociations(productOption1)server.commitTransaction();} finally {
server.endTransaction();
}
}
public void removeProduct(Product product1) {
EbeanServer server = productDAO.getServer();
server.beginTransaction();try {productDAO.update(product1);
// business logicserver.commitTransaction();} finally {
server.endTransaction();
}}public void removeProductAssociations(ProductOption productOption1) {EbeanServer server = productOptionsDAO.getServer();
server.beginTransaction();try {productOptionsDAO.update(productOption1);server.commitTransaction();} finally {
server.endTransaction();
}}// So if an error occured in removeProductAssociations, t wouldn't rollback the update on the product ?
public void testCreateRollback() {
EbeanServer ebeanServer = Ebean.getServer("default");
Integer testInt = null;
ebeanServer.beginTransaction();
try {
someDAO.create(someModel1);
// throw a 500
if (testInt == null) {
throw new NullPointerException("Something unexpected happened");
}
someDAO.create(someModel2);
ebeanServer.commitTransaction();
} catch (Exception e) {
Logger.info("testCreateRollback for Some Models threw exception.");
} finally {
ebeanServer.endTransaction();
}
SomeModel model1 = someDAO.server.find(SomeModel.class)
.where().eq("id", 1L).findUnique();
assertEquals(null, model1);
}
public void testCreateRollback() {
EbeanServer ebeanServer = Ebean.getServer("default");
Integer testInt = null;
ebeanServer.execute(new TxRunnable() {
@Override
public void run() {
try {
someDAO.create(someModel1);
if (testInt == null) {
throw new NullPointerException("Something unexpected happened");
}
someDAO.create(someModel2);
} catch (Exception e) {
Logger.info("testCreateRollback for Some Models threw exception.");
}
}
});SomeModel model1 = someDAO.server.find(SomeModel.class)}
.where().eq("id", 1L).findUnique();
assertEquals(null, model1);
additionalConfig.put("db.default.driver", "org.h2.Driver");
additionalConfig.put("db.default.url", "jdbc:h2:mem:play;MODE=MYSQL");
additionalConfig.put("db.default.user", "sa");
additionalConfig.put("db.default.password", "");
Could you kindly advice what could be different between ebeanServer.beginTransaction() and using TxRunnable approach, that one would rollback and other doesn't ?
Hi RobI have been trying out some permutations and combinations, to get the nested tx's to work ... The behavior when using TxRunnable approach seems to be working in few cases where a complete rollback happens and not in other cases.
public void execute(TxScope scope, TxRunnable r) {
ScopeTrans scopeTrans = createScopeTrans(scope);
try {
r.run();
} catch (Error e) {
throw scopeTrans.caughtError(e);
} catch (RuntimeException e) {
throw scopeTrans.caughtThrowable(e);
} finally {
scopeTrans.onFinally();
}
@Before
public void setup() {someDAO = mock(SomeDAO.class);}
when(someDAO.getServer()).thenReturn(mock(EbeanServer.class));
@Test
public void check() {
apply()
//asserts
}public void apply() {EbeanServer server = someDAO.getServer();// server being returned is a mock server !
TxScope txScope = TxScope
.required()
.setIsolation(TxIsolation.READ_COMMITED);
server.execute(new TxRunnable() {
@Override
public void run() {
// This code never gets called.
}
});
}So with a mock EbeanServer, seems the behavior s different ! instantiating and using DefaultServer Implementation instead of mock seemed way off approach
EbeanServer ebeanServer = mock(EbeanServer.class);
when(someDAO.getServer()).thenReturn(ebeanServer);
doAnswer((InvocationOnMock invocation) -> {
Object[] args = invocation.getArguments();
TxRunnable arg = (TxRunnable)args[0];
arg.run();
return arg;
}).when(ebeanServer).execute(Mockito.<TxRunnable>any());