Foros de discusión

Transaction management (rollback) for calling multiple services

LR BEGINNER, modificado hace 7 años.

Transaction management (rollback) for calling multiple services

New Member Mensajes: 24 Fecha de incorporación: 21/07/16 Mensajes recientes
Hi All,

I want to check whether anyone here have any idea on how to rollback transactions if there're multiple calls to multiple instances.

Below is my code in my MVCPortlet class. If there's no error for MainTableLocalServiceUtil.updateMainTableData(.....);, but there's error for DtlTableLocalServiceUtil.updateDetailTableData(.....);, there'll no rollback for the main table data. Any advise? Thanks.

methodA(...) throws SystemException {
try {
...
MainTableLocalServiceUtil.updateMainTableData(.....);
DtlTableLocalServiceUtil.updateDetailTableData(.....);
}
catch (SystemException e) {
throw SystemException("Error in methodA: " + e.getMessage());
}
catch (Exception e) {
throw SystemException("Error in methodA: " + e.getMessage());
}
}
thumbnail
David H Nebinger, modificado hace 7 años.

RE: Transaction management (rollback) for calling multiple services

Liferay Legend Mensajes: 14919 Fecha de incorporación: 2/09/06 Mensajes recientes
You need a master method in a SB class, appropriately named, that orchestrates all of the child calls.

SB transactions wrap methods by name, like addXxxx(), updateXxx() and deleteXxx(). Anything done within the scope of the method falls under the transaction.

So you could go and create the MatinTableLocalServiceImpl's updateAllTables(MainTable main, DtlTable dtl) method such as:

public void updateAllTables(MainTable main, DtlTable dtl) throws PortalException {

    updateMainTableData(main);

    dtlTableLocalService.updateDetailTableData(dtl);
}


Both updates occur now under the same transaction and a failure in one results in the rollback of all.

Note this only works when both are part of the same DB; if you're crossing different DBs you should be using XA transactions.

Note also that it is bad form to name your entities MainTable and DtlTable. Entities should be named for the business entity they represent because in your java code you should not worry about whether they are being stored in a table in a database or an xml file or ... For example, Liferay has entities for User, Asset and Release; even though all of these are stored in the database, there's not a "Table" suffix in sight.







Come meet me at the LSNA!
LR BEGINNER, modificado hace 7 años.

RE: Transaction management (rollback) for calling multiple services

New Member Mensajes: 24 Fecha de incorporación: 21/07/16 Mensajes recientes
Hi David,

Thanks for your reply and suggestion. I'm actually working on the different DB for the different services. Do you mind to share the details of the XA transactions and how i can implement it?

Thanks again.
LR BEGINNER, modificado hace 7 años.

RE: Transaction management (rollback) for calling multiple services

New Member Mensajes: 24 Fecha de incorporación: 21/07/16 Mensajes recientes
Hi David,

I manage to transfer both main and detail table into 1 DB. But when i tried to put below method in MainTableLocalServiceImpl, when there's error for insertion to details table, the system does not rollback the data inserted to MainTable. In my Portlet class below, it actually captured the exception. Any advise? Thanks.
1. Service class
public class MainTableLocalServiceImpl extends MainTableLocalServiceBaseImpl {
....
public void updateAllTables(MainTable main, DtlTable dtl) throws PortalException {
updateMainTableData(main);
dtlTableLocalService.updateDetailTableData(dtl);
}
}

2. Portlet
public class MainPortlet extends MVCPortlet {
.....
public approveRecs(ActionRequest request, ActionResponse response) throws PortalException, SystemException {
.....
try {
MainTableLocalServiceUtil.updateAllTables(...);
catch (Exception e) {
throw new SystemException();
}
}

}

Error in in the Portlet class with below exception:
Caused by: com.liferay.portal.kernel.exception.SystemException: Error in approveAcctUpdate: Could not execute JDBC batch update; SQL
thumbnail
David H Nebinger, modificado hace 7 años.

RE: Transaction management (rollback) for calling multiple services

Liferay Legend Mensajes: 14919 Fecha de incorporación: 2/09/06 Mensajes recientes
Transaction management is handled by an AOP aspect wrapping the updateAllTables() method; on return from the method when an exception was thrown, the rollback should be automatic. It's not going to stop the exception from being returned and printed, but if you look in the database the actual values should be unchanged.
LR BEGINNER, modificado hace 7 años.

RE: Transaction management (rollback) for calling multiple services

New Member Mensajes: 24 Fecha de incorporación: 21/07/16 Mensajes recientes
Thanks again for your reply.

Now i faced with another strange issue. In my ...LocalServiceImpl class, i have this mehod updateAllAccountData(...), and inside these methods, i called 4 services as per listed below, but the insertion (part 2) doesn't seemed to rollback. For part 1 and part 3, it's rollback when there's error in part 4 below, but not the part 2.

Is there anything that i missed out? Thanks.

public MasterAccount updateAllAccountData(.....)
throws PortalException, SystemException {

MasterAccount mastAcct = null;
try {
// 1
mastAcct = MasterAccountLocalServiceUtil.updateMasterAccount(masterAcctData);

// 2
AccountDtl acctDtl = AccountDtlLocalServiceUtil.createAccountDtl(-1);
acctDtl.setFirstName("Joe");
acctDtl.setLastName("Anderson");
AccountDtlLocalServiceUtil.addAccountDtl(acctDtl);

// 3
AccountDtl ad = AccountDtlLocalServiceUtil.getAccountDtl(acctDtlId);
ad.setRemarks("TRIAL....");
AccountDtlLocalServiceUtil.updateAccountDtl(ad);

// 4 -- error when triggering this section
ContactDtlLocalServiceUtil.updateContactDtl(ctcDtl);
}
catch (Exception e) {
throw new SystemException("Error in updateAllAccountData: " + e.getMessage());
}

return mastAcct;
}
LR BEGINNER, modificado hace 7 años.

RE: Transaction management (rollback) for calling multiple services

New Member Mensajes: 24 Fecha de incorporación: 21/07/16 Mensajes recientes
I managed to make the rollback work by adding the reference to the object and call the persistence method directly.
- refer service.xml
<reference entity="AccountDtl" package-path="com.db.model"></

- In ....LocalServiceImpl class
..
accountDtlPersistence.update(acctDtl);
..

But after adding the reference to the service.xml, when i build service.xml, it throws this error below. Any advise? Thanks.
[echo] java.io.IOException: Unable to open resource in class loader com/db/model/service.xml
thumbnail
David H Nebinger, modificado hace 7 años.

RE: Transaction management (rollback) for calling multiple services

Liferay Legend Mensajes: 14919 Fecha de incorporación: 2/09/06 Mensajes recientes
So going through the util classes may be causing you some issues..

Inside of the XxxLocalServiceImpl class you actually have access to service instances, so static util classes are unnecessary. Check your available member services by starting "this." in the ide and let auto correct show you the member list.

In both of your XxxLocalServiceImpl classes, you'll find that you have a masterTableLocalService and a detailTblLocalService members, so you can invoke other services directly without going through the util guys.

It may resolve the issues by staying within the current class loader and the current object instance.
LR BEGINNER, modificado hace 7 años.

RE: Transaction management (rollback) for calling multiple services

New Member Mensajes: 24 Fecha de incorporación: 21/07/16 Mensajes recientes
hi David,

Thanks for the reply.
But it seems that the rollback is still having some issues. The strange this is that 2 of the updates are rollback, but the insert is not being rollback.
LR BEGINNER, modificado hace 7 años.

RE: Transaction management (rollback) for calling multiple services

New Member Mensajes: 24 Fecha de incorporación: 21/07/16 Mensajes recientes
Hi,

Anyone has any idea about this issue? Thanks.