Hello Liferay Champs,
Requirement for Database Transaction :
It is common requirement in Liferay that in our custom portlet we have to update tables defined in custom portlet service builder and tables of Liferay portal. See following code, and I guess it will be common requirement for many of the projects you are working on.
/** Employee is our custom table **/
Employee emp = employeeLocalService.create(counterLocalService.increment());
/** Update User table with Employee as user also. For example we have not covered all the fields of user_ table **/
User user = userLocalService.create(counterLocalService.increment());
Here we are not explaining that how do we can have or standard way of implementing transactions over multiple objects, between custom service and portal service. Books on Liferay will give you that idea. Here we are trying to explain the issues with Liferay version 6.0.6.
Problem with Liferay 6.0.6 :
Even after following standard way of having transaction between custom and portal service objects, we found that Liferay version 6.0.6 is having problem with that. On failure database operations done on custom objects were not getting roll backed. Considering the example given before on failure of user update, employee updates were not getting roll backed.
We have tried to search a lot for this, but we couldn’t find the solution. We have implemented JTA as an alternative of this, but we found that JTA has it’s own overhead in implementing on Liferay Tomcat. And JTA has it’s own problem with timeout in database updates that we found during our implementation.
But then we found one of the issue raised in Liferay and we followed that issue for sometime and here it is : https://issues.liferay.com/browse/LPS-15904
This thread clearly mention that it was a problem with Liferay 6.0.6 and they have resolved with Liferay 6.1 CE version. Our biggest dilemma was we couldn’t upgrade it to 6.1. So we were searching for hint on how we can apply those patches to Liferay 6.0.6 CE. But thank Shuyang Zhou, who has mentioned every details in the thread which gave a good idea about how to patch in Liferay 6.0.6 CE.
Basically we have followed these steps :
- First of all we took the Liferay source of 6.0.6 CE
- Then we gone through the list of files mentioned by Shuyang Zhou in thread and we list down the differences, from Liferay repository in Github. Proper commit versions are given the thread.
- We have modified the files or some added in Liferay 6.0.6 and compiled the source with newer changes.
- We have taken two jars portal-impl.jar and portal-service.jar from compiled source and replaced into our tomcat – where we were having issue with Database Transaction.
- Then the only thing we had to do is to build all the services after putting the new jars in tomcat. Reason of that mentioned in below section where we have written about the nature of this problem.
That’s it. We are done !! We able to resolved the issue and now we are having rock solid application, where transaction integrity is secure and our client also got happy with that solution.
Nature of Problem :
Now the question is why database transactions were failing with this version. The reason was that with version, even if custom service and portal service were using the same Transaction Manager , they were using different session factory to open the hibernate sessions. Because of that they were not coming into one transaction although they were sharing the same transaction Manager.
Solution with Patch :
After applying patches, if you run the service builder again for your custom services, it will use the same SessionFactory to get the session which portal uses internally. So now they will share the session and will allow them to fall in one transaction.
We hope that this blog will help the champs to solve their complex database transaction related issue.