Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
AW: [eclipselink-dev] Test EntityManagerJUnitTestSuite.testSetRollbackOnly on NetWeaver: Problem with JTA/non-JTA data sources

Hi Tom,

actually, I think the issue does not only occur in the rollback-only state. It seems that EclipseLink does non-transactional reads as long as nothing requiring a transaction occurred on the persistence context. This made us wonder how EclipseLink can know what is going on on a JTA transaction. 

Please find attached a test we wrote to reproduce this: in a JTA transaction, we firstly insert data using JDBC and try to read the same data by EclipseLink in the same transaction. The data is not found.

I don't want to question that the non-transactional reads are a very valuable optimization. But is it correct to do so? Is there a switch to suppress the non-transactional reads?

-Adrian

===

Adrian Görler
SAP AG

Pflichtangaben/Mandatory Disclosure Statements: http://www.sap.com/company/legal/impressum.epx



-----Ursprüngliche Nachricht-----
Von: eclipselink-dev-bounces@xxxxxxxxxxx [mailto:eclipselink-dev-bounces@xxxxxxxxxxx] Im Auftrag von Tom Ware
Gesendet: Mittwoch, 9. Dezember 2009 16:39
An: Dev mailing list for Eclipse Persistence Services
Betreff: Re: AW: AW: [eclipselink-dev] Test EntityManagerJUnitTestSuite.testSetRollbackOnly on NetWeaver: Problem with JTA/non-JTA data sources

Hi Adrian,


Goerler, Adrian wrote:
> Hi Tom,
> 
>> - we need to check isOneServer before running the assert
> 
> I am actually, not sure I am understanding. Are you suggesting we should skip the assert on #990 in case we are on server?

After looking further at this issue, I think we probably need to change the 
assert to somehow determine if the transaction is in rollback-only mode in 
another way.   I think the following would allow the test to pass, but ideally 
we would change the assertion in some other way.

if (!isOnServer){
                 String eName = (String)em.createQuery("SELECT e.firstName FROM 
Employee e where e.id = " + emp2.getId()).getSingleResult();
                 assertTrue("Failed to keep txn open for set RollbackOnly", 
eName.equals(newName));
}

I cannot think of a way to test the transaction's state that will work both in 
JTA and non-JTA.  Can you?


>> - we should determine if the EE spec indicates what the expected behavior is here, so we know if this is just a test bug, or if it exposes an issue on NetWeaver.
> 
> Sabine observed that the flush (#980) is executed on a connection obtained from the JTA data source while the query (#989) is executed on a connection obtained from the non-JTA data source. It appears that once the persistence context is marked for rollback only, EclipseLink goes non-transactional. But the test asserts that EclipseLink hangs on the transactional data source (sees the change on the transactional data source). 
> 
> Could it be that EclipseLink switches to a non-transactional mode if the PC is marked for rollback? 
> 
> If that's the case, I would like to question that this behavior is correct. (One could argue that it doesn't really matter which connection is used for reading as the tx will be rolled back eventually anyhow).

I am not sure the specification has any opinion about whether this behavior is 
correct, so I guess we have to figure out what we think is best.

To me, the transaction is in rollback-only mode and therefore it is probably not 
correct to try to get transactional data.  Based on that assumption, I think the 
non-transactional read is probably as good a choice as we have available.

Admittedly, in an extended persistence context the behavior is inconsistent with 
that assumption (since the assert passes in extended persistence context) - we 
do a non-transactional read that gets a cache hit that returns uncommitted data.

The question I have is whether it is even reasonable for a user to to write a 
query in the rollback only state.  Based on that, I think we should just fix the 
assertion to do a better check if we can figure one out.

-Tom


> -Adrian
> 
> ===
> 
> Adrian Görler
> SAP AG
> 
> Pflichtangaben/Mandatory Disclosure Statements: http://www.sap.com/company/legal/impressum.epx
> 
> 
> -----Ursprüngliche Nachricht-----
> Von: eclipselink-dev-bounces@xxxxxxxxxxx [mailto:eclipselink-dev-bounces@xxxxxxxxxxx] Im Auftrag von Tom Ware
> Gesendet: Dienstag, 8. Dezember 2009 17:55
> An: Dev mailing list for Eclipse Persistence Services
> Betreff: Re: AW: [eclipselink-dev] Test EntityManagerJUnitTestSuite.testSetRollbackOnly on NetWeaver: Problem with JTA/non-JTA data sources
> 
> Hi Adrian,
> 
>    The reason the test passes on other servers can be observed in the comment:
> 
> 987: // Query may fail in server as connection marked for rollback.
> 
>    Basically, in the server case, we do not get to the statement:
> 
> 993: assertTrue("Failed to keep txn open for set RollbackOnly", 
> eName.equals(newName));
> 
>     Instead, an exception is thrown when we run the query and we get to:
> 
> 995: } catch (Exception ignore) {}
> 
>      The likely means the following:
> 
> - we need to check isOneServer before running the assert
> - we should determine if the EE spec indicates what the expected behavior is 
> here, so we know if this is just a test bug, or if it exposes an issue on NetWeaver.
> 
> -Tom
> 
> Goerler, Adrian wrote:
>> Hi Tom,
>>
>> I just reran the test. This is the current stack trace:
>>
>> 	at junit.framework.Assert.fail(Assert.java:47)
>> 	at junit.framework.Assert.assertTrue(Assert.java:20)
>> 	at org.eclipse.persistence.testing.tests.jpa.advanced.EntityManagerJUnitTestSuite.testSetRollbackOnly(EntityManagerJUnitTestSuite.java:990)
>> 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>> 	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>> 	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
>> 	at java.lang.reflect.Method.invoke(Method.java:597)
>> 	at junit.framework.TestCase.runTest(TestCase.java:168)
>> 	at junit.framework.TestCase.runBare(TestCase.java:134)
>> 	at org.eclipse.persistence.testing.framework.junit.JUnitTestCase.runBareServer(JUnitTestCase.java:463)
>> 	at org.eclipse.persistence.testing.framework.server.TestRunnerBean.runTest(TestRunnerBean.java:87)
>> 	at sun.reflect.GeneratedMethodAccessor267.invoke(Unknown Source)
>> 	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
>> 	at java.lang.reflect.Method.invoke(Method.java:597)
>>
>>
>>>>    1. update some test data and flush the changes to the database
>> 977-980:
>>         Employee emp2 = (Employee)result.get(1);
>>         String newName = ""+System.currentTimeMillis();
>>         emp2.setFirstName(newName);
>>         em.flush();
>>
>>>>    2. provoke an OptimisticLockException so that the current transaction is marked for rollback
>> 981-984:
>>         emp2.setLastName("Whatever");
>>         emp2.setVersion(0);
>>         try{
>>             em.flush();
>>
>>>>    3. read the test data updated in step 1) and assert that the changes are there
>> 985-990:
>>         }catch (Exception ex){
>>             em.clear(); //prevent the flush again
>>             // Query may fail in server as connection marked for rollback.
>>             try {
>>                 String eName = (String)em.createQuery("SELECT e.firstName FROM Employee e where e.id = " + emp2.getId()).getSingleResult();
>>                 assertTrue("Failed to keep txn open for set RollbackOnly", eName.equals(newName));
>>
>>
>> We think that for the flush on 980, a connection from the JTA data source is being used and for the query  on line 989 a connection from the non-JTA data source.
>>
>> Hence the result of the flush on 980 is not visible to the query on 989.
>>
>> -Adrian
>>
>> ====
>>
>> Adrian Görler
>> SAP AG
>>
>> Pflichtangaben/Mandatory Disclosure Statements: http://www.sap.com/company/legal/impressum.epx
>>
>>
>>
>> -----Ursprüngliche Nachricht-----
>> Von: eclipselink-dev-bounces@xxxxxxxxxxx [mailto:eclipselink-dev-bounces@xxxxxxxxxxx] Im Auftrag von Tom Ware
>> Gesendet: Dienstag, 8. Dezember 2009 16:09
>> An: Dev mailing list for Eclipse Persistence Services
>> Betreff: Re: [eclipselink-dev] Test EntityManagerJUnitTestSuite.testSetRollbackOnly on NetWeaver: Problem with JTA/non-JTA data sources
>>
>> Hi Sabine,
>>
>>    The line numbers in my test do not correspond with the ones in your exception 
>> trace and I cannot tell from the error message which assertion is failing for 
>> you.   What is on the line that causes the exception for you? 
>> (EntityManagerJUnitTestSuite.java:994)
>>
>> -Tom
>>
>> Kevin Yuan wrote:
>>> Hi Sabine,
>>> This test passed on both JTA and non-JTA datasource on both WebLogic and 
>>> WebSphere, I don't think that's EclipseLink behaves incorrect in this 
>>> situation, but I am not familiar with NetWeaver server. Probably you 
>>> have to follow on the setting with the server.  I will let you know if I 
>>> find more info.
>>>
>>> Regards,
>>> Kevin
>>>  
>>> Heider, Sabine wrote:
>>>> Hi,
>>>>
>>>>  
>>>>
>>>> does anyone have an opinion on the error described below?
>>>>
>>>> I'm under the impression that EclipseLink behaves incorrectly in this 
>>>> situation, but it could also be that there is a problem with our 
>>>> application server that I would have to follow on.
>>>>
>>>>  
>>>>
>>>> Thanks and best regards,
>>>>
>>>> Sabine
>>>>
>>>>  
>>>>
>>>>  
>>>>
>>>> *From:* eclipselink-dev-bounces@xxxxxxxxxxx 
>>>> [mailto:eclipselink-dev-bounces@xxxxxxxxxxx] *On Behalf Of *Heider, Sabine
>>>> *Sent:* Dienstag, 1. Dezember 2009 12:39
>>>> *To:* Dev mailing list for Eclipse Persistence Services
>>>> *Subject:* [eclipselink-dev] Test 
>>>> EntityManagerJUnitTestSuite.testSetRollbackOnly on NetWeaver: Problem 
>>>> with JTA/non-JTA data sources
>>>>
>>>>  
>>>>
>>>> Hi all,
>>>>
>>>>  
>>>>
>>>> when running on the NetWeaver server, the test 
>>>> EntityManagerJUnitTestSuite.testSetRollbackOnly fails with the 
>>>> following assertion error:
>>>>
>>>>  
>>>>
>>>> junit.framework.AssertionFailedError: eName was 'testRefreshRemoved' 
>>>> but expected '1259661366483'
>>>>
>>>>         at junit.framework.Assert.fail(Assert.java:47)
>>>>
>>>>         at junit.framework.Assert.assertTrue(Assert.java:20)
>>>>
>>>>         at 
>>>> org.eclipse.persistence.testing.tests.jpa.advanced.EntityManagerJUnitTestSuite.testSetRollbackOnly(EntityManagerJUnitTestSuite.java:994)
>>>>
>>>>         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>>>>
>>>>         at 
>>>> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>>>>
>>>>         at 
>>>> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
>>>>
>>>>         at java.lang.reflect.Method.invoke(Method.java:597)
>>>>
>>>>         at junit.framework.TestCase.runTest(TestCase.java:168)
>>>>
>>>>         at junit.framework.TestCase.runBare(TestCase.java:134)
>>>>
>>>>         at 
>>>> org.eclipse.persistence.testing.framework.junit.JUnitTestCase.runBareServer(JUnitTestCase.java:463)
>>>>
>>>>         at 
>>>> org.eclipse.persistence.testing.framework.server.TestRunnerBean.runTest(TestRunnerBean.java:87)
>>>>
>>>>  
>>>>
>>>> What the test basically does is that it executes the following steps 
>>>> inside a single JTA transaction:
>>>>
>>>>    1. update some test data and flush the changes to the database
>>>>    2. provoke an OptimisticLockException so that the current
>>>>       transaction is marked for rollback
>>>>    3. read the test data updated in step 1) and assert that the
>>>>       changes are there
>>>>
>>>>  
>>>>
>>>> Step 3) fails on NetWeaver - the query can still be executed but it 
>>>> returns the unmodified (i.e. committed) data.
>>>>
>>>>  
>>>>
>>>> I did some debugging and found out that step 1) uses the data source 
>>>> from PersistenceUnitInfo. getJtaDataSource(), while in step 3) the 
>>>> data source is obtained from PersistenceUnitInfo. 
>>>> getNonJtaDataSource(). Thus we ended up with two different 
>>>> connections, and as transaction isolation TRANSACTION_READ_COMMITTED 
>>>> is used we don't see the uncommitted changes from the flush operation 
>>>> before.
>>>>
>>>>  
>>>>
>>>> It seems wrong to me that EclipseLink uses the non-JTA data source in 
>>>> that situation, but I'm unable to decide whether it is a general 
>>>> problem or rather caused by some peculiarity of our server. What 
>>>> happens on different application servers?
>>>>
>>>>  
>>>>
>>>> Best regards,
>>>>
>>>> Sabine
>>>>
>>>>  
>>>>
>>>> *Sabine Heider
>>>> **SAP AG
>>>>
>>>> *Pflichtangaben/Mandatory Disclosure Statements:
>>>> http://www.sap.com/company/legal/impressum.epx
>>>>
>>>>  
>>>>
>>>>  
>>>>
>>>> ------------------------------------------------------------------------
>>>>
>>>> _______________________________________________
>>>> eclipselink-dev mailing list
>>>> eclipselink-dev@xxxxxxxxxxx
>>>> https://dev.eclipse.org/mailman/listinfo/eclipselink-dev
>>>>   
>>> ------------------------------------------------------------------------
>>>
>>> _______________________________________________
>>> eclipselink-dev mailing list
>>> eclipselink-dev@xxxxxxxxxxx
>>> https://dev.eclipse.org/mailman/listinfo/eclipselink-dev
>> _______________________________________________
>> eclipselink-dev mailing list
>> eclipselink-dev@xxxxxxxxxxx
>> https://dev.eclipse.org/mailman/listinfo/eclipselink-dev
>> _______________________________________________
>> eclipselink-dev mailing list
>> eclipselink-dev@xxxxxxxxxxx
>> https://dev.eclipse.org/mailman/listinfo/eclipselink-dev
> _______________________________________________
> eclipselink-dev mailing list
> eclipselink-dev@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/eclipselink-dev
> _______________________________________________
> eclipselink-dev mailing list
> eclipselink-dev@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/eclipselink-dev
_______________________________________________
eclipselink-dev mailing list
eclipselink-dev@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/eclipselink-dev

Attachment: JTA_issue.patch
Description: JTA_issue.patch


Back to the top