Bug 1034444

Summary: JPA and Camel JPA use different transaction scopes in same transaction
Product: [JBoss] JBoss Fuse Service Works 6 Reporter: Daniel Tschan, Puzzle ITC <tschan+redhat>
Component: SwitchYardAssignee: Tomohisa Igarashi <toigaras>
Status: CLOSED NOTABUG QA Contact: Jiri Sedlacek <jsedlace>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 6.0.0CC: atangrin, jcordes, ldimaggi, oskutka, serviceworks, soa-p-jira, toigaras, tschan+redhat
Target Milestone: ---   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2013-11-29 05:57:56 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Attachments:
Description Flags
Test case none

Description Daniel Tschan, Puzzle ITC 2013-11-25 20:46:09 UTC
Created attachment 828874 [details]
Test case

Description of problem:
JPA and Camel JPA use different transaction scopes even when running in the same transaction, meaning that there are two first level caches for the same transaction, possibly holding different versions of the same entity. This is not what developers expect and could lead to hard to diagnose problems.
The cause of this seems to be that the Spring version used by Camel JPA uses its own transaction scoping mechanism and not the one provided by Java EE.

Version-Release number of selected component (if applicable):


How reproducible:
Always, see attached test case.


Steps to Reproduce:
1. Start a standard installation of JBoss Fuse Service Works 6 Beta
2. Make sure you have the JBoss Fuse Service Works 6 Beta Maven repositories configured in your settings.xml
3. Run TransactionScopeTest JUnit/Arquillian test in provided test case

Actual results:
Test fails because there two instances of the same entity, caused by two entity managers (each with its own cache) associated with the same transaction.

Expected results:
Test succeeds because there is only one entity manager, therefore only one cache and only one instance of the test entity.

Additional info:
The test case also contains a workaround for the problem in class TransactionScopedEntityManagerFactory which is demonstrated by the test TransactionScopeWorkaroundTest.

Comment 2 Tomohisa Igarashi 2013-11-26 08:36:11 UTC
It looks like the workaround you suggested is the right approach - letting EntityManagerFactory producer cache the EntityManager and return it for createEntityManager() if you really want to share EntityManager instance between application and camel-jpa. However it would be harmful sometimes since EntityManager is not thread-safe so need to be careful.

Anyway, I think there's nothing to do on the SwitchYard side.

Comment 3 Daniel Tschan, Puzzle ITC 2013-11-26 10:00:12 UTC
I think about having a custom camel expressions which maintains a persistent state with JPA, e.g. as part of a dynamic router or dynamic recipient list and a JPA Binding in the same SwitchYard exchange. Aggregators sometimes also maintain a persistent state. Since these are established enterprise integration patterns I think it should at least be documented that there could be issues with transaction scoping.

You're right that entity managers are generally not thread safe. However transaction scoped entity managers are by default. That's why I have that crude check in the TransactionScopedEntityManagerFactory constructor. As far as I know there is no standard way to ensure that an entity manager is transaction scoped. However, I don't know what happens if one explicitly associates multiple threads with a single transaction, which is supported by JBossTS. So this might not mix with TransactionScopedEntityManagerFactory.

Comment 4 Tomohisa Igarashi 2013-11-26 13:01:12 UTC
Although I may not understand what you mean by "transaction scope", but I don't recommend sharing EntityManager and expecting it always returns the same instance.  Application should be responsible to persist() or merge() to persist the changes it makes.

Comment 5 Daniel Tschan, Puzzle ITC 2013-11-28 08:28:08 UTC
Perhaps this is a better explanation. I'd expect that there is only ever one transaction scoped entity manager associated with a transaction, as is the case in Java EE or Spring applications. The other developers in the project, all experience Java EE and/or Spring developers, have the same expectations.
If there are multiple transaction scoped entity managers associated with the same transaction, special care has to be taken because there are now multiple independent first level caches active in the same transaction.

The test case actually should test that Camel JPA and JPA use the same transaction scoped entity manager. But since there is no way to get access to a transaction scoped entity manager (you only ever get a delegating proxy) it resorts to compare  entity references. This is only a means to demonstrate the issue, not how we implement our applications.

Comment 6 Tomohisa Igarashi 2013-11-28 09:23:30 UTC
Again, application should be responsible to persist() or merge() before the entity is accessed by other components, and find() to acquire latest one after the entity is accessed by other components. Sharing EntityManager doesn't sound a good practice. If you really want to do that, then please take the workaround you suggested in your testcase.

Comment 7 Daniel Tschan, Puzzle ITC 2013-11-28 10:07:13 UTC
We don't try to do anything special and are just using JBoss FSW based on established Enterprise Integration and Java EE patterns.
But the transaction scoped entity manager really should be shared by all components in the same transaction. Otherwise "persist" and "merge" will not be enough. You will have to use additional "flush" and "clear" calls to make sure the different first level caches are synchronized, otherwise "find" might not return the latest entity. Developers are not traind and used to do this. Additionally this leads to a loss of performance, because flush involves the database.

So far we looked at JBoss FSW as a single development platform and expected the contained components, e.g. SwitchYard and Camel to be integrated accordingly. Are we wrong with this? Looking at FSW as a collection of more or less independent software stacks is of course possible, but makes it much harder to use it.

Comment 8 Tomohisa Igarashi 2013-11-29 05:57:56 UTC
Closing this ticket since it's not a bug report - Tschan, could you post on the FSW6 forum if you want to have a discussion?
https://community.jboss.org/en/fsw

Or you may be able to get a FSW6 subscription to get the support. Please take a look at this and contact to the sales if you like.
http://www.jboss.org/products/fsw.html