You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@openjpa.apache.org by "Vikram Bhatia (JIRA)" <ji...@apache.org> on 2007/09/13 16:06:32 UTC
[jira] Created: (OPENJPA-368) Multithreaded client fails randomly
on EntityManager.persist() with out transaction context.
Multithreaded client fails randomly on EntityManager.persist() with out transaction context.
--------------------------------------------------------------------------------------------
Key: OPENJPA-368
URL: https://issues.apache.org/jira/browse/OPENJPA-368
Project: OpenJPA
Issue Type: Bug
Components: jdbc
Affects Versions: 1.0.0, 0.9.7
Environment: WebLogic Server 10.0, Oracle DB
Reporter: Vikram Bhatia
This issue happens with the following scenario with JTA transaction.
Suppose there is Entity A which is related to table with two columns accountId and name. accountId is PK of the table whose value is generated using sequence in DB.
1. Thread A starts Transaction 1.
2. Thread B starts Transaction 2.
3. Thread A and Thread B both calls EntityManager.persist(o) where o is
Entity object whose primary key is generated with a sequence in DB.
4. A call is made to o.getAccountId() concurrently.
5. Thread A suspends Transaction 1, and gets the value of accountId. It updates
sequence value in DB with new Transaction 3. It saves Transaction 1.
6. Thread B suspends Transaction 2, and gets the value of accountId. It updates
sequence value in DB with new Transaction 4. It saves Transaction 2.
7. Now, when both Thread A and Thread B resumes outer transaction
concurrently, it updates Transaction Manager with Transaction 2.
The problem happens when JTA transaction is saved in AbstractJDBCSeq _outerTransaction variable. The variable gets overwritten if multiple threads load the value of accountId from sequence in DB, when it resumes the JTA transaction later it resumes the transaction 2 for both threads resulting in following exception.
javax.ejb.EJBException: nested exception is: javax.persistence.TransactionRequiredException: The method public abstract void javax.persistence.EntityManager.persist(java.lang.Object) must be called in the context of a transaction.
javax.persistence.TransactionRequiredException: The method public abstract void javax.persistence.EntityManager.persist(java.lang.Object) must be called in the context of a transaction.
at weblogic.deployment.BasePersistenceContextProxyImpl.validateInvocation(BasePersistenceContextProxyImpl.java:121)
at weblogic.deployment.BasePersistenceContextProxyImpl.invoke(BasePersistenceContextProxyImpl.java:86)
at weblogic.deployment.TransactionalEntityManagerProxyImpl.invoke(TransactionalEntityManagerProxyImpl.java:90)
at weblogic.deployment.BasePersistenceContextProxyImpl.invoke(BasePersistenceContextProxyImpl.java:80)
at $Proxy63.persist(Unknown Source)
Please check README.txt of attached testcase.zip to see how to reproduce the issue.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
[jira] Resolved: (OPENJPA-368) Multithreaded client fails randomly
on EntityManager.persist() with out transaction context.
Posted by "Patrick Linskey (JIRA)" <ji...@apache.org>.
[ https://issues.apache.org/jira/browse/OPENJPA-368?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Patrick Linskey resolved OPENJPA-368.
-------------------------------------
Resolution: Fixed
Fix Version/s: 1.1.0
1.0.1
Committing Vikram's patch. FTR, I don't love the fact that we're using a ThreadLocal; it feels wrong. However, given the current API design, I think it's unavoidable. Once we move to a system that provides a means to execute a Runnable or some analog in an out-of-band transaction via the ManagedRuntime interface, we'll be able to simplify this code.
> Multithreaded client fails randomly on EntityManager.persist() with out transaction context.
> --------------------------------------------------------------------------------------------
>
> Key: OPENJPA-368
> URL: https://issues.apache.org/jira/browse/OPENJPA-368
> Project: OpenJPA
> Issue Type: Bug
> Components: jdbc
> Affects Versions: 0.9.7, 1.0.0
> Environment: WebLogic Server 10.0, Oracle DB
> Reporter: Vikram Bhatia
> Fix For: 1.0.1, 1.1.0
>
> Attachments: proposed-fix-v2.patch, proposed-fix.patch, testcase.zip
>
>
> This issue happens with the following scenario with JTA transaction.
> Suppose there is Entity A which is related to table with two columns accountId and name. accountId is PK of the table whose value is generated using sequence in DB.
> 1. Thread A starts Transaction 1.
> 2. Thread B starts Transaction 2.
> 3. Thread A and Thread B both calls EntityManager.persist(o) where o is
> Entity object whose primary key is generated with a sequence in DB.
> 4. A call is made to o.getAccountId() concurrently.
> 5. Thread A suspends Transaction 1, and gets the value of accountId. It updates
> sequence value in DB with new Transaction 3. It saves Transaction 1.
> 6. Thread B suspends Transaction 2, and gets the value of accountId. It updates
> sequence value in DB with new Transaction 4. It saves Transaction 2.
> 7. Now, when both Thread A and Thread B resumes outer transaction
> concurrently, it updates Transaction Manager with Transaction 2.
> The problem happens when JTA transaction is saved in AbstractJDBCSeq _outerTransaction variable. The variable gets overwritten if multiple threads load the value of accountId from sequence in DB, when it resumes the JTA transaction later it resumes the transaction 2 for both threads resulting in following exception.
> javax.ejb.EJBException: nested exception is: javax.persistence.TransactionRequiredException: The method public abstract void javax.persistence.EntityManager.persist(java.lang.Object) must be called in the context of a transaction.
> javax.persistence.TransactionRequiredException: The method public abstract void javax.persistence.EntityManager.persist(java.lang.Object) must be called in the context of a transaction.
> at weblogic.deployment.BasePersistenceContextProxyImpl.validateInvocation(BasePersistenceContextProxyImpl.java:121)
> at weblogic.deployment.BasePersistenceContextProxyImpl.invoke(BasePersistenceContextProxyImpl.java:86)
> at weblogic.deployment.TransactionalEntityManagerProxyImpl.invoke(TransactionalEntityManagerProxyImpl.java:90)
> at weblogic.deployment.BasePersistenceContextProxyImpl.invoke(BasePersistenceContextProxyImpl.java:80)
> at $Proxy63.persist(Unknown Source)
> Please check README.txt of attached testcase.zip to see how to reproduce the issue.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
[jira] Commented: (OPENJPA-368) Multithreaded client fails randomly
on EntityManager.persist() with out transaction context.
Posted by "Patrick Linskey (JIRA)" <ji...@apache.org>.
[ https://issues.apache.org/jira/browse/OPENJPA-368?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12529271 ]
Patrick Linskey commented on OPENJPA-368:
-----------------------------------------
If the solution is going to be based on a thread-keyed map, why not use a ThreadLocal instead?
Another possible solution would be to obtain a lock on something so that only a single thread can obtain a seq value for a particular instance. Personally, I think that the proposed patch (potentially with a ThreadLocal mod) would be better, though.
> Multithreaded client fails randomly on EntityManager.persist() with out transaction context.
> --------------------------------------------------------------------------------------------
>
> Key: OPENJPA-368
> URL: https://issues.apache.org/jira/browse/OPENJPA-368
> Project: OpenJPA
> Issue Type: Bug
> Components: jdbc
> Affects Versions: 0.9.7, 1.0.0
> Environment: WebLogic Server 10.0, Oracle DB
> Reporter: Vikram Bhatia
> Attachments: proposed-fix.patch, testcase.zip
>
>
> This issue happens with the following scenario with JTA transaction.
> Suppose there is Entity A which is related to table with two columns accountId and name. accountId is PK of the table whose value is generated using sequence in DB.
> 1. Thread A starts Transaction 1.
> 2. Thread B starts Transaction 2.
> 3. Thread A and Thread B both calls EntityManager.persist(o) where o is
> Entity object whose primary key is generated with a sequence in DB.
> 4. A call is made to o.getAccountId() concurrently.
> 5. Thread A suspends Transaction 1, and gets the value of accountId. It updates
> sequence value in DB with new Transaction 3. It saves Transaction 1.
> 6. Thread B suspends Transaction 2, and gets the value of accountId. It updates
> sequence value in DB with new Transaction 4. It saves Transaction 2.
> 7. Now, when both Thread A and Thread B resumes outer transaction
> concurrently, it updates Transaction Manager with Transaction 2.
> The problem happens when JTA transaction is saved in AbstractJDBCSeq _outerTransaction variable. The variable gets overwritten if multiple threads load the value of accountId from sequence in DB, when it resumes the JTA transaction later it resumes the transaction 2 for both threads resulting in following exception.
> javax.ejb.EJBException: nested exception is: javax.persistence.TransactionRequiredException: The method public abstract void javax.persistence.EntityManager.persist(java.lang.Object) must be called in the context of a transaction.
> javax.persistence.TransactionRequiredException: The method public abstract void javax.persistence.EntityManager.persist(java.lang.Object) must be called in the context of a transaction.
> at weblogic.deployment.BasePersistenceContextProxyImpl.validateInvocation(BasePersistenceContextProxyImpl.java:121)
> at weblogic.deployment.BasePersistenceContextProxyImpl.invoke(BasePersistenceContextProxyImpl.java:86)
> at weblogic.deployment.TransactionalEntityManagerProxyImpl.invoke(TransactionalEntityManagerProxyImpl.java:90)
> at weblogic.deployment.BasePersistenceContextProxyImpl.invoke(BasePersistenceContextProxyImpl.java:80)
> at $Proxy63.persist(Unknown Source)
> Please check README.txt of attached testcase.zip to see how to reproduce the issue.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
[jira] Commented: (OPENJPA-368) Multithreaded client fails randomly
on EntityManager.persist() with out transaction context.
Posted by "Patrick Linskey (JIRA)" <ji...@apache.org>.
[ https://issues.apache.org/jira/browse/OPENJPA-368?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12529270 ]
Patrick Linskey commented on OPENJPA-368:
-----------------------------------------
I believe that an easy workaround would be to specify a non-jta-data-source in persistence.xml.
> Multithreaded client fails randomly on EntityManager.persist() with out transaction context.
> --------------------------------------------------------------------------------------------
>
> Key: OPENJPA-368
> URL: https://issues.apache.org/jira/browse/OPENJPA-368
> Project: OpenJPA
> Issue Type: Bug
> Components: jdbc
> Affects Versions: 0.9.7, 1.0.0
> Environment: WebLogic Server 10.0, Oracle DB
> Reporter: Vikram Bhatia
> Attachments: proposed-fix.patch, testcase.zip
>
>
> This issue happens with the following scenario with JTA transaction.
> Suppose there is Entity A which is related to table with two columns accountId and name. accountId is PK of the table whose value is generated using sequence in DB.
> 1. Thread A starts Transaction 1.
> 2. Thread B starts Transaction 2.
> 3. Thread A and Thread B both calls EntityManager.persist(o) where o is
> Entity object whose primary key is generated with a sequence in DB.
> 4. A call is made to o.getAccountId() concurrently.
> 5. Thread A suspends Transaction 1, and gets the value of accountId. It updates
> sequence value in DB with new Transaction 3. It saves Transaction 1.
> 6. Thread B suspends Transaction 2, and gets the value of accountId. It updates
> sequence value in DB with new Transaction 4. It saves Transaction 2.
> 7. Now, when both Thread A and Thread B resumes outer transaction
> concurrently, it updates Transaction Manager with Transaction 2.
> The problem happens when JTA transaction is saved in AbstractJDBCSeq _outerTransaction variable. The variable gets overwritten if multiple threads load the value of accountId from sequence in DB, when it resumes the JTA transaction later it resumes the transaction 2 for both threads resulting in following exception.
> javax.ejb.EJBException: nested exception is: javax.persistence.TransactionRequiredException: The method public abstract void javax.persistence.EntityManager.persist(java.lang.Object) must be called in the context of a transaction.
> javax.persistence.TransactionRequiredException: The method public abstract void javax.persistence.EntityManager.persist(java.lang.Object) must be called in the context of a transaction.
> at weblogic.deployment.BasePersistenceContextProxyImpl.validateInvocation(BasePersistenceContextProxyImpl.java:121)
> at weblogic.deployment.BasePersistenceContextProxyImpl.invoke(BasePersistenceContextProxyImpl.java:86)
> at weblogic.deployment.TransactionalEntityManagerProxyImpl.invoke(TransactionalEntityManagerProxyImpl.java:90)
> at weblogic.deployment.BasePersistenceContextProxyImpl.invoke(BasePersistenceContextProxyImpl.java:80)
> at $Proxy63.persist(Unknown Source)
> Please check README.txt of attached testcase.zip to see how to reproduce the issue.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
[jira] Updated: (OPENJPA-368) Multithreaded client fails randomly
on EntityManager.persist() with out transaction context.
Posted by "Vikram Bhatia (JIRA)" <ji...@apache.org>.
[ https://issues.apache.org/jira/browse/OPENJPA-368?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Vikram Bhatia updated OPENJPA-368:
----------------------------------
Attachment: proposed-fix.patch
Proposed Fix.
> Multithreaded client fails randomly on EntityManager.persist() with out transaction context.
> --------------------------------------------------------------------------------------------
>
> Key: OPENJPA-368
> URL: https://issues.apache.org/jira/browse/OPENJPA-368
> Project: OpenJPA
> Issue Type: Bug
> Components: jdbc
> Affects Versions: 0.9.7, 1.0.0
> Environment: WebLogic Server 10.0, Oracle DB
> Reporter: Vikram Bhatia
> Attachments: proposed-fix.patch, testcase.zip
>
>
> This issue happens with the following scenario with JTA transaction.
> Suppose there is Entity A which is related to table with two columns accountId and name. accountId is PK of the table whose value is generated using sequence in DB.
> 1. Thread A starts Transaction 1.
> 2. Thread B starts Transaction 2.
> 3. Thread A and Thread B both calls EntityManager.persist(o) where o is
> Entity object whose primary key is generated with a sequence in DB.
> 4. A call is made to o.getAccountId() concurrently.
> 5. Thread A suspends Transaction 1, and gets the value of accountId. It updates
> sequence value in DB with new Transaction 3. It saves Transaction 1.
> 6. Thread B suspends Transaction 2, and gets the value of accountId. It updates
> sequence value in DB with new Transaction 4. It saves Transaction 2.
> 7. Now, when both Thread A and Thread B resumes outer transaction
> concurrently, it updates Transaction Manager with Transaction 2.
> The problem happens when JTA transaction is saved in AbstractJDBCSeq _outerTransaction variable. The variable gets overwritten if multiple threads load the value of accountId from sequence in DB, when it resumes the JTA transaction later it resumes the transaction 2 for both threads resulting in following exception.
> javax.ejb.EJBException: nested exception is: javax.persistence.TransactionRequiredException: The method public abstract void javax.persistence.EntityManager.persist(java.lang.Object) must be called in the context of a transaction.
> javax.persistence.TransactionRequiredException: The method public abstract void javax.persistence.EntityManager.persist(java.lang.Object) must be called in the context of a transaction.
> at weblogic.deployment.BasePersistenceContextProxyImpl.validateInvocation(BasePersistenceContextProxyImpl.java:121)
> at weblogic.deployment.BasePersistenceContextProxyImpl.invoke(BasePersistenceContextProxyImpl.java:86)
> at weblogic.deployment.TransactionalEntityManagerProxyImpl.invoke(TransactionalEntityManagerProxyImpl.java:90)
> at weblogic.deployment.BasePersistenceContextProxyImpl.invoke(BasePersistenceContextProxyImpl.java:80)
> at $Proxy63.persist(Unknown Source)
> Please check README.txt of attached testcase.zip to see how to reproduce the issue.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
[jira] Updated: (OPENJPA-368) Multithreaded client fails randomly
on EntityManager.persist() with out transaction context.
Posted by "Vikram Bhatia (JIRA)" <ji...@apache.org>.
[ https://issues.apache.org/jira/browse/OPENJPA-368?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Vikram Bhatia updated OPENJPA-368:
----------------------------------
Attachment: proposed-fix-v2.patch
Thanks Patrick. Here is Version 2 of the patch using ThreadLocal.
> Multithreaded client fails randomly on EntityManager.persist() with out transaction context.
> --------------------------------------------------------------------------------------------
>
> Key: OPENJPA-368
> URL: https://issues.apache.org/jira/browse/OPENJPA-368
> Project: OpenJPA
> Issue Type: Bug
> Components: jdbc
> Affects Versions: 0.9.7, 1.0.0
> Environment: WebLogic Server 10.0, Oracle DB
> Reporter: Vikram Bhatia
> Attachments: proposed-fix-v2.patch, proposed-fix.patch, testcase.zip
>
>
> This issue happens with the following scenario with JTA transaction.
> Suppose there is Entity A which is related to table with two columns accountId and name. accountId is PK of the table whose value is generated using sequence in DB.
> 1. Thread A starts Transaction 1.
> 2. Thread B starts Transaction 2.
> 3. Thread A and Thread B both calls EntityManager.persist(o) where o is
> Entity object whose primary key is generated with a sequence in DB.
> 4. A call is made to o.getAccountId() concurrently.
> 5. Thread A suspends Transaction 1, and gets the value of accountId. It updates
> sequence value in DB with new Transaction 3. It saves Transaction 1.
> 6. Thread B suspends Transaction 2, and gets the value of accountId. It updates
> sequence value in DB with new Transaction 4. It saves Transaction 2.
> 7. Now, when both Thread A and Thread B resumes outer transaction
> concurrently, it updates Transaction Manager with Transaction 2.
> The problem happens when JTA transaction is saved in AbstractJDBCSeq _outerTransaction variable. The variable gets overwritten if multiple threads load the value of accountId from sequence in DB, when it resumes the JTA transaction later it resumes the transaction 2 for both threads resulting in following exception.
> javax.ejb.EJBException: nested exception is: javax.persistence.TransactionRequiredException: The method public abstract void javax.persistence.EntityManager.persist(java.lang.Object) must be called in the context of a transaction.
> javax.persistence.TransactionRequiredException: The method public abstract void javax.persistence.EntityManager.persist(java.lang.Object) must be called in the context of a transaction.
> at weblogic.deployment.BasePersistenceContextProxyImpl.validateInvocation(BasePersistenceContextProxyImpl.java:121)
> at weblogic.deployment.BasePersistenceContextProxyImpl.invoke(BasePersistenceContextProxyImpl.java:86)
> at weblogic.deployment.TransactionalEntityManagerProxyImpl.invoke(TransactionalEntityManagerProxyImpl.java:90)
> at weblogic.deployment.BasePersistenceContextProxyImpl.invoke(BasePersistenceContextProxyImpl.java:80)
> at $Proxy63.persist(Unknown Source)
> Please check README.txt of attached testcase.zip to see how to reproduce the issue.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.