You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@openjpa.apache.org by "Jonas Petersen (JIRA)" <ji...@apache.org> on 2007/11/19 20:52:43 UTC

[jira] Created: (OPENJPA-446) Problem when setting String fields of detached objects

Problem when setting String fields of detached objects
------------------------------------------------------

                 Key: OPENJPA-446
                 URL: https://issues.apache.org/jira/browse/OPENJPA-446
             Project: OpenJPA
          Issue Type: Bug
          Components: jpa, kernel
    Affects Versions: 1.0.1
         Environment: OpenJPA 1.0.1
Java 1.5.0_13
MySQL Server 5.0
MySQL Connector Java 5.0.6
            Reporter: Jonas Petersen


I would like to report some strange behavior with detach and merge. To me it looks like a bug.

I'm trying implement the following strategy:
 
persistence context A:
  1. get persistent object
  2. detach the object
no persistence context:
  3. modify the (detached) object
persistence context B:
  4. attach (merge) the object

This is quite simple and straight forward. It generally works except in one situation. When committing the merge() (step 4) an "optimistic locking error" is is thrown under the following condition: (step 3) a (String) field is set to the same text that it already contains but using a different String instance. In other words, when the following expressions are true:
    
    newString.equals(oldString)
    newString != oldString

I have written some test code that reproduces this effect (see Attachment).

The tests are using the same code except for one line:

Test 1 sets the String to a different one than the object contains:
    record.setContent("a text different than the one in the record");

Test 2 sets the String to the same instance the object contains:
  record.setContent(record.getContent());

Test 3 sets the String to the same text but as a different String instance:
  record.setContent(record.getContent()+"");

 This is the result (output of the test run):
----------------------------------
Test 1: SUCCESS
Test 2: SUCCESS
Test 3: FAILED (Optimistic locking errors were detected when flushing 
                to the data store. The following objects may have been
                concurrently modified in another transaction: 
                [test.Record-1])
----------------------------------

While doing some debugging I noticed two things:

1. When setting the value:

Class: org.apache.openjpa.kernel.DetachedStateManager
Line: 555
Method: settingStringField()

        if (cur == next || !_loaded.get(idx))
          return;

Here the old and the new value (String) is compared with the == operator.
The expression can be false with the same text (but different instances). I find this interesting as it matches exacly the problematic condition. I think an .equals() would fix the issue I am having. But I suppose there is something going wrong at another place as well.

2. Here is the point where execution splits into different ways when calling commit().

Class: org.apache.openjpa.jdbc.kernel.AbstractUpdateManager
Line: 151
Method: populateRowManager()

    } else if ((dirty = ImplHelper.getUpdateFields(sm)) != null) {

In the tests that succeed "ImplHelper.getUpdateFields(sm)" will return a BitSet. So the condition is true.
In the tests that fail "ImplHelper.getUpdateFields(sm)" will return null. So the condition is false.

Note: the problem persist with OpenJPA 1.1.0-SNAPSHOT. When run without enhancing the Record class, all tests will succeed though (printing this message „INFO   [main] openjpa.Enhance - Creating subclass for "[class test.Record]". This means that your application will be less efficient and will consume more memory than it would if you ran the OpenJPA enhancer. Additionally, lazy loading will not be available for one-to-one and many-to-one persistent attributes in types using field access; they will be loaded eagerly instead.")

Regards
Jonas


-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


RE: [jira] Updated: (OPENJPA-446) Problem when setting String fields of detached objects

Posted by Pinaki Poddar <pp...@bea.com>.
Did you try the patch when current value of String field is null?

Looks like the patch should check for passed 'cur' being null. 

-----Original Message-----
From: Jonas Petersen (JIRA) [mailto:jira@apache.org] 
Sent: Monday, November 19, 2007 2:57 PM
To: dev@openjpa.apache.org
Subject: [jira] Updated: (OPENJPA-446) Problem when setting String
fields of detached objects


     [
https://issues.apache.org/jira/browse/OPENJPA-446?page=com.atlassian.jir
a.plugin.system.issuetabpanels:all-tabpanel ]

Jonas Petersen updated OPENJPA-446:
-----------------------------------

    Attachment: detach-attach-fix.patch

I have fixed the DetachedStateManager so it correctly compares the
strings (as described in "1. When setting the value:").

I have rebuilt OpenJPA and ran all maven tests successfully.

My DetachAttachTest runs all successfull as well now.

I'm attaching a patch.


> Problem when setting String fields of detached objects
> ------------------------------------------------------
>
>                 Key: OPENJPA-446
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-446
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: jpa, kernel
>    Affects Versions: 1.0.1
>         Environment: OpenJPA 1.0.1
> Java 1.5.0_13
> MySQL Server 5.0
> MySQL Connector Java 5.0.6
>            Reporter: Jonas Petersen
>         Attachments: detach-attach-fix.patch, DetachAttachTest.zip
>
>
> I would like to report some strange behavior with detach and merge. To
me it looks like a bug.
> I'm trying implement the following strategy:
>  
> persistence context A:
>   1. get persistent object
>   2. detach the object
> no persistence context:
>   3. modify the (detached) object
> persistence context B:
>   4. attach (merge) the object
> This is quite simple and straight forward. It generally works except
in one situation. When committing the merge() (step 4) an "optimistic
locking error" is is thrown under the following condition: (step 3) a
(String) field is set to the same text that it already contains but
using a different String instance. In other words, when the following
expressions are true:
>     
>     newString.equals(oldString)
>     newString != oldString
> I have written some test code that reproduces this effect (see
Attachment).
> The tests are using the same code except for one line:
> Test 1 sets the String to a different one than the object contains:
>     record.setContent("a text different than the one in the record"); 
> Test 2 sets the String to the same instance the object contains:
>   record.setContent(record.getContent());
> Test 3 sets the String to the same text but as a different String
instance:
>   record.setContent(record.getContent()+"");
>  This is the result (output of the test run):
> ----------------------------------
> Test 1: SUCCESS
> Test 2: SUCCESS
> Test 3: FAILED (Optimistic locking errors were detected when flushing 
>                 to the data store. The following objects may have been
>                 concurrently modified in another transaction: 
>                 [test.Record-1])
> ----------------------------------
> While doing some debugging I noticed two things:
> 1. When setting the value:
> Class: org.apache.openjpa.kernel.DetachedStateManager
> Line: 555
> Method: settingStringField()
>         if (cur == next || !_loaded.get(idx))
>           return;
> Here the old and the new value (String) is compared with the ==
operator.
> The expression can be false with the same text (but different
instances). I find this interesting as it matches exacly the problematic
condition. I think an .equals() would fix the issue I am having. But I
suppose there is something going wrong at another place as well.
> 2. Here is the point where execution splits into different ways when
calling commit().
> Class: org.apache.openjpa.jdbc.kernel.AbstractUpdateManager
> Line: 151
> Method: populateRowManager()
>     } else if ((dirty = ImplHelper.getUpdateFields(sm)) != null) { In 
> the tests that succeed "ImplHelper.getUpdateFields(sm)" will return a
BitSet. So the condition is true.
> In the tests that fail "ImplHelper.getUpdateFields(sm)" will return
null. So the condition is false.
> Note: the problem persist with OpenJPA 1.1.0-SNAPSHOT. When run
without enhancing the Record class, all tests will succeed though
(printing this message "INFO   [main] openjpa.Enhance - Creating
subclass for "[class test.Record]". This means that your application
will be less efficient and will consume more memory than it would if you
ran the OpenJPA enhancer. Additionally, lazy loading will not be
available for one-to-one and many-to-one persistent attributes in types
using field access; they will be loaded eagerly instead.")
> Regards
> Jonas

--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


Notice:  This email message, together with any attachments, may contain information  of  BEA Systems,  Inc.,  its subsidiaries  and  affiliated entities,  that may be confidential,  proprietary,  copyrighted  and/or legally privileged, and is intended solely for the use of the individual or entity named in this message. If you are not the intended recipient, and have received this message in error, please immediately return this by email and then delete it.

[jira] Commented: (OPENJPA-446) Problem when setting String fields of detached objects

Posted by "Simon Droscher (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/OPENJPA-446?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12548322 ] 

Simon Droscher commented on OPENJPA-446:
----------------------------------------

Any reason why the same change shouldn't be made to the settingObjectField() method of DetachedStateManager ?

> Problem when setting String fields of detached objects
> ------------------------------------------------------
>
>                 Key: OPENJPA-446
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-446
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: jpa, kernel
>    Affects Versions: 1.0.1
>         Environment: OpenJPA 1.0.1
> Java 1.5.0_13
> MySQL Server 5.0
> MySQL Connector Java 5.0.6
>            Reporter: Jonas Petersen
>             Fix For: 1.0.2, 1.1.0
>
>         Attachments: detach-attach-fix-proper.patch, detach-attach-fix.patch, DetachAttachTest-updated.zip, DetachAttachTest.zip
>
>
> I would like to report some strange behavior with detach and merge. To me it looks like a bug.
> I'm trying implement the following strategy:
>  
> persistence context A:
>   1. get persistent object
>   2. detach the object
> no persistence context:
>   3. modify the (detached) object
> persistence context B:
>   4. attach (merge) the object
> This is quite simple and straight forward. It generally works except in one situation. When committing the merge() (step 4) an "optimistic locking error" is is thrown under the following condition: (step 3) a (String) field is set to the same text that it already contains but using a different String instance. In other words, when the following expressions are true:
>     
>     newString.equals(oldString)
>     newString != oldString
> I have written some test code that reproduces this effect (see Attachment).
> The tests are using the same code except for one line:
> Test 1 sets the String to a different one than the object contains:
>     record.setContent("a text different than the one in the record");
> Test 2 sets the String to the same instance the object contains:
>   record.setContent(record.getContent());
> Test 3 sets the String to the same text but as a different String instance:
>   record.setContent(record.getContent()+"");
>  This is the result (output of the test run):
> ----------------------------------
> Test 1: SUCCESS
> Test 2: SUCCESS
> Test 3: FAILED (Optimistic locking errors were detected when flushing 
>                 to the data store. The following objects may have been
>                 concurrently modified in another transaction: 
>                 [test.Record-1])
> ----------------------------------
> While doing some debugging I noticed two things:
> 1. When setting the value:
> Class: org.apache.openjpa.kernel.DetachedStateManager
> Line: 555
> Method: settingStringField()
>         if (cur == next || !_loaded.get(idx))
>           return;
> Here the old and the new value (String) is compared with the == operator.
> The expression can be false with the same text (but different instances). I find this interesting as it matches exacly the problematic condition. I think an .equals() would fix the issue I am having. But I suppose there is something going wrong at another place as well.
> 2. Here is the point where execution splits into different ways when calling commit().
> Class: org.apache.openjpa.jdbc.kernel.AbstractUpdateManager
> Line: 151
> Method: populateRowManager()
>     } else if ((dirty = ImplHelper.getUpdateFields(sm)) != null) {
> In the tests that succeed "ImplHelper.getUpdateFields(sm)" will return a BitSet. So the condition is true.
> In the tests that fail "ImplHelper.getUpdateFields(sm)" will return null. So the condition is false.
> Note: the problem persist with OpenJPA 1.1.0-SNAPSHOT. When run without enhancing the Record class, all tests will succeed though (printing this message „INFO   [main] openjpa.Enhance - Creating subclass for "[class test.Record]". This means that your application will be less efficient and will consume more memory than it would if you ran the OpenJPA enhancer. Additionally, lazy loading will not be available for one-to-one and many-to-one persistent attributes in types using field access; they will be loaded eagerly instead.")
> Regards
> Jonas

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Updated: (OPENJPA-446) Problem when setting String fields of detached objects

Posted by "Jonas Petersen (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/OPENJPA-446?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Jonas Petersen updated OPENJPA-446:
-----------------------------------

    Attachment: detach-attach-fix.patch

I have fixed the DetachedStateManager so it correctly compares the strings (as described in "1. When setting the value:").

I have rebuilt OpenJPA and ran all maven tests successfully.

My DetachAttachTest runs all successfull as well now.

I'm attaching a patch.


> Problem when setting String fields of detached objects
> ------------------------------------------------------
>
>                 Key: OPENJPA-446
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-446
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: jpa, kernel
>    Affects Versions: 1.0.1
>         Environment: OpenJPA 1.0.1
> Java 1.5.0_13
> MySQL Server 5.0
> MySQL Connector Java 5.0.6
>            Reporter: Jonas Petersen
>         Attachments: detach-attach-fix.patch, DetachAttachTest.zip
>
>
> I would like to report some strange behavior with detach and merge. To me it looks like a bug.
> I'm trying implement the following strategy:
>  
> persistence context A:
>   1. get persistent object
>   2. detach the object
> no persistence context:
>   3. modify the (detached) object
> persistence context B:
>   4. attach (merge) the object
> This is quite simple and straight forward. It generally works except in one situation. When committing the merge() (step 4) an "optimistic locking error" is is thrown under the following condition: (step 3) a (String) field is set to the same text that it already contains but using a different String instance. In other words, when the following expressions are true:
>     
>     newString.equals(oldString)
>     newString != oldString
> I have written some test code that reproduces this effect (see Attachment).
> The tests are using the same code except for one line:
> Test 1 sets the String to a different one than the object contains:
>     record.setContent("a text different than the one in the record");
> Test 2 sets the String to the same instance the object contains:
>   record.setContent(record.getContent());
> Test 3 sets the String to the same text but as a different String instance:
>   record.setContent(record.getContent()+"");
>  This is the result (output of the test run):
> ----------------------------------
> Test 1: SUCCESS
> Test 2: SUCCESS
> Test 3: FAILED (Optimistic locking errors were detected when flushing 
>                 to the data store. The following objects may have been
>                 concurrently modified in another transaction: 
>                 [test.Record-1])
> ----------------------------------
> While doing some debugging I noticed two things:
> 1. When setting the value:
> Class: org.apache.openjpa.kernel.DetachedStateManager
> Line: 555
> Method: settingStringField()
>         if (cur == next || !_loaded.get(idx))
>           return;
> Here the old and the new value (String) is compared with the == operator.
> The expression can be false with the same text (but different instances). I find this interesting as it matches exacly the problematic condition. I think an .equals() would fix the issue I am having. But I suppose there is something going wrong at another place as well.
> 2. Here is the point where execution splits into different ways when calling commit().
> Class: org.apache.openjpa.jdbc.kernel.AbstractUpdateManager
> Line: 151
> Method: populateRowManager()
>     } else if ((dirty = ImplHelper.getUpdateFields(sm)) != null) {
> In the tests that succeed "ImplHelper.getUpdateFields(sm)" will return a BitSet. So the condition is true.
> In the tests that fail "ImplHelper.getUpdateFields(sm)" will return null. So the condition is false.
> Note: the problem persist with OpenJPA 1.1.0-SNAPSHOT. When run without enhancing the Record class, all tests will succeed though (printing this message „INFO   [main] openjpa.Enhance - Creating subclass for "[class test.Record]". This means that your application will be less efficient and will consume more memory than it would if you ran the OpenJPA enhancer. Additionally, lazy loading will not be available for one-to-one and many-to-one persistent attributes in types using field access; they will be loaded eagerly instead.")
> Regards
> Jonas

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Commented: (OPENJPA-446) Problem when setting String fields of detached objects

Posted by "Nick Smith (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/OPENJPA-446?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12612817#action_12612817 ] 

Nick Smith commented on OPENJPA-446:
------------------------------------

Can someone definately confirm that this has been fixed in v1.0.2? I'm experiencing the same issue but am unable to upgrade to v1.1.0 due to an incompatability with BEA Kodo.

Nick

> Problem when setting String fields of detached objects
> ------------------------------------------------------
>
>                 Key: OPENJPA-446
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-446
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: jpa, kernel
>    Affects Versions: 1.0.1
>         Environment: OpenJPA 1.0.1
> Java 1.5.0_13
> MySQL Server 5.0
> MySQL Connector Java 5.0.6
>            Reporter: Jonas Petersen
>             Fix For: 1.0.2, 1.1.0
>
>         Attachments: detach-attach-fix-proper.patch, detach-attach-fix.patch, DetachAttachTest-updated.zip, DetachAttachTest.zip
>
>
> I would like to report some strange behavior with detach and merge. To me it looks like a bug.
> I'm trying implement the following strategy:
>  
> persistence context A:
>   1. get persistent object
>   2. detach the object
> no persistence context:
>   3. modify the (detached) object
> persistence context B:
>   4. attach (merge) the object
> This is quite simple and straight forward. It generally works except in one situation. When committing the merge() (step 4) an "optimistic locking error" is is thrown under the following condition: (step 3) a (String) field is set to the same text that it already contains but using a different String instance. In other words, when the following expressions are true:
>     
>     newString.equals(oldString)
>     newString != oldString
> I have written some test code that reproduces this effect (see Attachment).
> The tests are using the same code except for one line:
> Test 1 sets the String to a different one than the object contains:
>     record.setContent("a text different than the one in the record");
> Test 2 sets the String to the same instance the object contains:
>   record.setContent(record.getContent());
> Test 3 sets the String to the same text but as a different String instance:
>   record.setContent(record.getContent()+"");
>  This is the result (output of the test run):
> ----------------------------------
> Test 1: SUCCESS
> Test 2: SUCCESS
> Test 3: FAILED (Optimistic locking errors were detected when flushing 
>                 to the data store. The following objects may have been
>                 concurrently modified in another transaction: 
>                 [test.Record-1])
> ----------------------------------
> While doing some debugging I noticed two things:
> 1. When setting the value:
> Class: org.apache.openjpa.kernel.DetachedStateManager
> Line: 555
> Method: settingStringField()
>         if (cur == next || !_loaded.get(idx))
>           return;
> Here the old and the new value (String) is compared with the == operator.
> The expression can be false with the same text (but different instances). I find this interesting as it matches exacly the problematic condition. I think an .equals() would fix the issue I am having. But I suppose there is something going wrong at another place as well.
> 2. Here is the point where execution splits into different ways when calling commit().
> Class: org.apache.openjpa.jdbc.kernel.AbstractUpdateManager
> Line: 151
> Method: populateRowManager()
>     } else if ((dirty = ImplHelper.getUpdateFields(sm)) != null) {
> In the tests that succeed "ImplHelper.getUpdateFields(sm)" will return a BitSet. So the condition is true.
> In the tests that fail "ImplHelper.getUpdateFields(sm)" will return null. So the condition is false.
> Note: the problem persist with OpenJPA 1.1.0-SNAPSHOT. When run without enhancing the Record class, all tests will succeed though (printing this message „INFO   [main] openjpa.Enhance - Creating subclass for "[class test.Record]". This means that your application will be less efficient and will consume more memory than it would if you ran the OpenJPA enhancer. Additionally, lazy loading will not be available for one-to-one and many-to-one persistent attributes in types using field access; they will be loaded eagerly instead.")
> Regards
> Jonas

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Updated: (OPENJPA-446) Problem when setting String fields of detached objects

Posted by "Jonas Petersen (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/OPENJPA-446?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Jonas Petersen updated OPENJPA-446:
-----------------------------------

    Attachment: DetachAttachTest-updated.zip

Thanks for reviewing. It's fine for me if you put the DetachAttachTest.zip test files into OpenJPA under the ASL license. You may want to use the extended one that I just attached instead though. It also tests the null conditions and does some assertion for each test.

> Problem when setting String fields of detached objects
> ------------------------------------------------------
>
>                 Key: OPENJPA-446
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-446
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: jpa, kernel
>    Affects Versions: 1.0.1
>         Environment: OpenJPA 1.0.1
> Java 1.5.0_13
> MySQL Server 5.0
> MySQL Connector Java 5.0.6
>            Reporter: Jonas Petersen
>             Fix For: 1.0.2, 1.1.0
>
>         Attachments: detach-attach-fix-proper.patch, detach-attach-fix.patch, DetachAttachTest-updated.zip, DetachAttachTest.zip
>
>
> I would like to report some strange behavior with detach and merge. To me it looks like a bug.
> I'm trying implement the following strategy:
>  
> persistence context A:
>   1. get persistent object
>   2. detach the object
> no persistence context:
>   3. modify the (detached) object
> persistence context B:
>   4. attach (merge) the object
> This is quite simple and straight forward. It generally works except in one situation. When committing the merge() (step 4) an "optimistic locking error" is is thrown under the following condition: (step 3) a (String) field is set to the same text that it already contains but using a different String instance. In other words, when the following expressions are true:
>     
>     newString.equals(oldString)
>     newString != oldString
> I have written some test code that reproduces this effect (see Attachment).
> The tests are using the same code except for one line:
> Test 1 sets the String to a different one than the object contains:
>     record.setContent("a text different than the one in the record");
> Test 2 sets the String to the same instance the object contains:
>   record.setContent(record.getContent());
> Test 3 sets the String to the same text but as a different String instance:
>   record.setContent(record.getContent()+"");
>  This is the result (output of the test run):
> ----------------------------------
> Test 1: SUCCESS
> Test 2: SUCCESS
> Test 3: FAILED (Optimistic locking errors were detected when flushing 
>                 to the data store. The following objects may have been
>                 concurrently modified in another transaction: 
>                 [test.Record-1])
> ----------------------------------
> While doing some debugging I noticed two things:
> 1. When setting the value:
> Class: org.apache.openjpa.kernel.DetachedStateManager
> Line: 555
> Method: settingStringField()
>         if (cur == next || !_loaded.get(idx))
>           return;
> Here the old and the new value (String) is compared with the == operator.
> The expression can be false with the same text (but different instances). I find this interesting as it matches exacly the problematic condition. I think an .equals() would fix the issue I am having. But I suppose there is something going wrong at another place as well.
> 2. Here is the point where execution splits into different ways when calling commit().
> Class: org.apache.openjpa.jdbc.kernel.AbstractUpdateManager
> Line: 151
> Method: populateRowManager()
>     } else if ((dirty = ImplHelper.getUpdateFields(sm)) != null) {
> In the tests that succeed "ImplHelper.getUpdateFields(sm)" will return a BitSet. So the condition is true.
> In the tests that fail "ImplHelper.getUpdateFields(sm)" will return null. So the condition is false.
> Note: the problem persist with OpenJPA 1.1.0-SNAPSHOT. When run without enhancing the Record class, all tests will succeed though (printing this message „INFO   [main] openjpa.Enhance - Creating subclass for "[class test.Record]". This means that your application will be less efficient and will consume more memory than it would if you ran the OpenJPA enhancer. Additionally, lazy loading will not be available for one-to-one and many-to-one persistent attributes in types using field access; they will be loaded eagerly instead.")
> Regards
> Jonas

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Updated: (OPENJPA-446) Problem when setting String fields of detached objects

Posted by "Jonas Petersen (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/OPENJPA-446?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Jonas Petersen updated OPENJPA-446:
-----------------------------------

    Attachment: detach-attach-fix-proper.patch

I'm sorry, the patch that I posted (detach-attach-fix.patch) is bad. I'm posting a proper one: detach-attach-fix-proper.patch.

The problem was that it did not consider a String field set to null before setting it to another value.

Maybe a TestCase checking all the different situations would be a good idea.

> Problem when setting String fields of detached objects
> ------------------------------------------------------
>
>                 Key: OPENJPA-446
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-446
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: jpa, kernel
>    Affects Versions: 1.0.1
>         Environment: OpenJPA 1.0.1
> Java 1.5.0_13
> MySQL Server 5.0
> MySQL Connector Java 5.0.6
>            Reporter: Jonas Petersen
>         Attachments: detach-attach-fix-proper.patch, detach-attach-fix.patch, DetachAttachTest.zip
>
>
> I would like to report some strange behavior with detach and merge. To me it looks like a bug.
> I'm trying implement the following strategy:
>  
> persistence context A:
>   1. get persistent object
>   2. detach the object
> no persistence context:
>   3. modify the (detached) object
> persistence context B:
>   4. attach (merge) the object
> This is quite simple and straight forward. It generally works except in one situation. When committing the merge() (step 4) an "optimistic locking error" is is thrown under the following condition: (step 3) a (String) field is set to the same text that it already contains but using a different String instance. In other words, when the following expressions are true:
>     
>     newString.equals(oldString)
>     newString != oldString
> I have written some test code that reproduces this effect (see Attachment).
> The tests are using the same code except for one line:
> Test 1 sets the String to a different one than the object contains:
>     record.setContent("a text different than the one in the record");
> Test 2 sets the String to the same instance the object contains:
>   record.setContent(record.getContent());
> Test 3 sets the String to the same text but as a different String instance:
>   record.setContent(record.getContent()+"");
>  This is the result (output of the test run):
> ----------------------------------
> Test 1: SUCCESS
> Test 2: SUCCESS
> Test 3: FAILED (Optimistic locking errors were detected when flushing 
>                 to the data store. The following objects may have been
>                 concurrently modified in another transaction: 
>                 [test.Record-1])
> ----------------------------------
> While doing some debugging I noticed two things:
> 1. When setting the value:
> Class: org.apache.openjpa.kernel.DetachedStateManager
> Line: 555
> Method: settingStringField()
>         if (cur == next || !_loaded.get(idx))
>           return;
> Here the old and the new value (String) is compared with the == operator.
> The expression can be false with the same text (but different instances). I find this interesting as it matches exacly the problematic condition. I think an .equals() would fix the issue I am having. But I suppose there is something going wrong at another place as well.
> 2. Here is the point where execution splits into different ways when calling commit().
> Class: org.apache.openjpa.jdbc.kernel.AbstractUpdateManager
> Line: 151
> Method: populateRowManager()
>     } else if ((dirty = ImplHelper.getUpdateFields(sm)) != null) {
> In the tests that succeed "ImplHelper.getUpdateFields(sm)" will return a BitSet. So the condition is true.
> In the tests that fail "ImplHelper.getUpdateFields(sm)" will return null. So the condition is false.
> Note: the problem persist with OpenJPA 1.1.0-SNAPSHOT. When run without enhancing the Record class, all tests will succeed though (printing this message „INFO   [main] openjpa.Enhance - Creating subclass for "[class test.Record]". This means that your application will be less efficient and will consume more memory than it would if you ran the OpenJPA enhancer. Additionally, lazy loading will not be available for one-to-one and many-to-one persistent attributes in types using field access; they will be loaded eagerly instead.")
> Regards
> Jonas

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Updated: (OPENJPA-446) Problem when setting String fields of detached objects

Posted by "Jonas Petersen (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/OPENJPA-446?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Jonas Petersen updated OPENJPA-446:
-----------------------------------

    Attachment: DetachAttachTest.zip

Sourcecode to reproduce the issue.

> Problem when setting String fields of detached objects
> ------------------------------------------------------
>
>                 Key: OPENJPA-446
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-446
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: jpa, kernel
>    Affects Versions: 1.0.1
>         Environment: OpenJPA 1.0.1
> Java 1.5.0_13
> MySQL Server 5.0
> MySQL Connector Java 5.0.6
>            Reporter: Jonas Petersen
>         Attachments: DetachAttachTest.zip
>
>
> I would like to report some strange behavior with detach and merge. To me it looks like a bug.
> I'm trying implement the following strategy:
>  
> persistence context A:
>   1. get persistent object
>   2. detach the object
> no persistence context:
>   3. modify the (detached) object
> persistence context B:
>   4. attach (merge) the object
> This is quite simple and straight forward. It generally works except in one situation. When committing the merge() (step 4) an "optimistic locking error" is is thrown under the following condition: (step 3) a (String) field is set to the same text that it already contains but using a different String instance. In other words, when the following expressions are true:
>     
>     newString.equals(oldString)
>     newString != oldString
> I have written some test code that reproduces this effect (see Attachment).
> The tests are using the same code except for one line:
> Test 1 sets the String to a different one than the object contains:
>     record.setContent("a text different than the one in the record");
> Test 2 sets the String to the same instance the object contains:
>   record.setContent(record.getContent());
> Test 3 sets the String to the same text but as a different String instance:
>   record.setContent(record.getContent()+"");
>  This is the result (output of the test run):
> ----------------------------------
> Test 1: SUCCESS
> Test 2: SUCCESS
> Test 3: FAILED (Optimistic locking errors were detected when flushing 
>                 to the data store. The following objects may have been
>                 concurrently modified in another transaction: 
>                 [test.Record-1])
> ----------------------------------
> While doing some debugging I noticed two things:
> 1. When setting the value:
> Class: org.apache.openjpa.kernel.DetachedStateManager
> Line: 555
> Method: settingStringField()
>         if (cur == next || !_loaded.get(idx))
>           return;
> Here the old and the new value (String) is compared with the == operator.
> The expression can be false with the same text (but different instances). I find this interesting as it matches exacly the problematic condition. I think an .equals() would fix the issue I am having. But I suppose there is something going wrong at another place as well.
> 2. Here is the point where execution splits into different ways when calling commit().
> Class: org.apache.openjpa.jdbc.kernel.AbstractUpdateManager
> Line: 151
> Method: populateRowManager()
>     } else if ((dirty = ImplHelper.getUpdateFields(sm)) != null) {
> In the tests that succeed "ImplHelper.getUpdateFields(sm)" will return a BitSet. So the condition is true.
> In the tests that fail "ImplHelper.getUpdateFields(sm)" will return null. So the condition is false.
> Note: the problem persist with OpenJPA 1.1.0-SNAPSHOT. When run without enhancing the Record class, all tests will succeed though (printing this message „INFO   [main] openjpa.Enhance - Creating subclass for "[class test.Record]". This means that your application will be less efficient and will consume more memory than it would if you ran the OpenJPA enhancer. Additionally, lazy loading will not be available for one-to-one and many-to-one persistent attributes in types using field access; they will be loaded eagerly instead.")
> Regards
> Jonas

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Commented: (OPENJPA-446) Problem when setting String fields of detached objects

Posted by "Kevin Sutter (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/OPENJPA-446?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12612890#action_12612890 ] 

Kevin Sutter commented on OPENJPA-446:
--------------------------------------

Nick,
Two things you can look at.  One is the "fix versions".  On this JIRA Issue, the 1.0.2 version is listed as being a "fix version".  The other thing you can look at is the specific SVN Commits.  The changes were put into the 1.0.x release via svn revision #596737.  The 1.0.2 release was tagged at revision #628944.  So, yes, this change has been put into the 1.0.2 release.

Kevin

> Problem when setting String fields of detached objects
> ------------------------------------------------------
>
>                 Key: OPENJPA-446
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-446
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: jpa, kernel
>    Affects Versions: 1.0.1
>         Environment: OpenJPA 1.0.1
> Java 1.5.0_13
> MySQL Server 5.0
> MySQL Connector Java 5.0.6
>            Reporter: Jonas Petersen
>             Fix For: 1.0.2, 1.1.0
>
>         Attachments: detach-attach-fix-proper.patch, detach-attach-fix.patch, DetachAttachTest-updated.zip, DetachAttachTest.zip
>
>
> I would like to report some strange behavior with detach and merge. To me it looks like a bug.
> I'm trying implement the following strategy:
>  
> persistence context A:
>   1. get persistent object
>   2. detach the object
> no persistence context:
>   3. modify the (detached) object
> persistence context B:
>   4. attach (merge) the object
> This is quite simple and straight forward. It generally works except in one situation. When committing the merge() (step 4) an "optimistic locking error" is is thrown under the following condition: (step 3) a (String) field is set to the same text that it already contains but using a different String instance. In other words, when the following expressions are true:
>     
>     newString.equals(oldString)
>     newString != oldString
> I have written some test code that reproduces this effect (see Attachment).
> The tests are using the same code except for one line:
> Test 1 sets the String to a different one than the object contains:
>     record.setContent("a text different than the one in the record");
> Test 2 sets the String to the same instance the object contains:
>   record.setContent(record.getContent());
> Test 3 sets the String to the same text but as a different String instance:
>   record.setContent(record.getContent()+"");
>  This is the result (output of the test run):
> ----------------------------------
> Test 1: SUCCESS
> Test 2: SUCCESS
> Test 3: FAILED (Optimistic locking errors were detected when flushing 
>                 to the data store. The following objects may have been
>                 concurrently modified in another transaction: 
>                 [test.Record-1])
> ----------------------------------
> While doing some debugging I noticed two things:
> 1. When setting the value:
> Class: org.apache.openjpa.kernel.DetachedStateManager
> Line: 555
> Method: settingStringField()
>         if (cur == next || !_loaded.get(idx))
>           return;
> Here the old and the new value (String) is compared with the == operator.
> The expression can be false with the same text (but different instances). I find this interesting as it matches exacly the problematic condition. I think an .equals() would fix the issue I am having. But I suppose there is something going wrong at another place as well.
> 2. Here is the point where execution splits into different ways when calling commit().
> Class: org.apache.openjpa.jdbc.kernel.AbstractUpdateManager
> Line: 151
> Method: populateRowManager()
>     } else if ((dirty = ImplHelper.getUpdateFields(sm)) != null) {
> In the tests that succeed "ImplHelper.getUpdateFields(sm)" will return a BitSet. So the condition is true.
> In the tests that fail "ImplHelper.getUpdateFields(sm)" will return null. So the condition is false.
> Note: the problem persist with OpenJPA 1.1.0-SNAPSHOT. When run without enhancing the Record class, all tests will succeed though (printing this message „INFO   [main] openjpa.Enhance - Creating subclass for "[class test.Record]". This means that your application will be less efficient and will consume more memory than it would if you ran the OpenJPA enhancer. Additionally, lazy loading will not be available for one-to-one and many-to-one persistent attributes in types using field access; they will be loaded eagerly instead.")
> Regards
> Jonas

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Resolved: (OPENJPA-446) Problem when setting String fields of detached objects

Posted by "Michael Dick (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/OPENJPA-446?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Michael Dick resolved OPENJPA-446.
----------------------------------

       Resolution: Fixed
    Fix Version/s: 1.1.0
                   1.0.2

The attached patch looks good, thanks Jonas!

> Problem when setting String fields of detached objects
> ------------------------------------------------------
>
>                 Key: OPENJPA-446
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-446
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: jpa, kernel
>    Affects Versions: 1.0.1
>         Environment: OpenJPA 1.0.1
> Java 1.5.0_13
> MySQL Server 5.0
> MySQL Connector Java 5.0.6
>            Reporter: Jonas Petersen
>             Fix For: 1.0.2, 1.1.0
>
>         Attachments: detach-attach-fix-proper.patch, detach-attach-fix.patch, DetachAttachTest.zip
>
>
> I would like to report some strange behavior with detach and merge. To me it looks like a bug.
> I'm trying implement the following strategy:
>  
> persistence context A:
>   1. get persistent object
>   2. detach the object
> no persistence context:
>   3. modify the (detached) object
> persistence context B:
>   4. attach (merge) the object
> This is quite simple and straight forward. It generally works except in one situation. When committing the merge() (step 4) an "optimistic locking error" is is thrown under the following condition: (step 3) a (String) field is set to the same text that it already contains but using a different String instance. In other words, when the following expressions are true:
>     
>     newString.equals(oldString)
>     newString != oldString
> I have written some test code that reproduces this effect (see Attachment).
> The tests are using the same code except for one line:
> Test 1 sets the String to a different one than the object contains:
>     record.setContent("a text different than the one in the record");
> Test 2 sets the String to the same instance the object contains:
>   record.setContent(record.getContent());
> Test 3 sets the String to the same text but as a different String instance:
>   record.setContent(record.getContent()+"");
>  This is the result (output of the test run):
> ----------------------------------
> Test 1: SUCCESS
> Test 2: SUCCESS
> Test 3: FAILED (Optimistic locking errors were detected when flushing 
>                 to the data store. The following objects may have been
>                 concurrently modified in another transaction: 
>                 [test.Record-1])
> ----------------------------------
> While doing some debugging I noticed two things:
> 1. When setting the value:
> Class: org.apache.openjpa.kernel.DetachedStateManager
> Line: 555
> Method: settingStringField()
>         if (cur == next || !_loaded.get(idx))
>           return;
> Here the old and the new value (String) is compared with the == operator.
> The expression can be false with the same text (but different instances). I find this interesting as it matches exacly the problematic condition. I think an .equals() would fix the issue I am having. But I suppose there is something going wrong at another place as well.
> 2. Here is the point where execution splits into different ways when calling commit().
> Class: org.apache.openjpa.jdbc.kernel.AbstractUpdateManager
> Line: 151
> Method: populateRowManager()
>     } else if ((dirty = ImplHelper.getUpdateFields(sm)) != null) {
> In the tests that succeed "ImplHelper.getUpdateFields(sm)" will return a BitSet. So the condition is true.
> In the tests that fail "ImplHelper.getUpdateFields(sm)" will return null. So the condition is false.
> Note: the problem persist with OpenJPA 1.1.0-SNAPSHOT. When run without enhancing the Record class, all tests will succeed though (printing this message „INFO   [main] openjpa.Enhance - Creating subclass for "[class test.Record]". This means that your application will be less efficient and will consume more memory than it would if you ran the OpenJPA enhancer. Additionally, lazy loading will not be available for one-to-one and many-to-one persistent attributes in types using field access; they will be loaded eagerly instead.")
> Regards
> Jonas

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


Fwd: [jira] Commented: (OPENJPA-446) Problem when setting String fields of detached objects

Posted by Craig L Russell <Cr...@Sun.COM>.
First, thanks for the patch and all the work on debugging.

A couple of comments on the JIRA stuff...

1. If a patch is submitted without granting license to Apache, then  
it needs to be resubmitted (as was done here) with the license grant.

2. A patch can be resubmitted under the same name, and JIRA figures  
out that only the latest is to be used. The other one is grayed out  
so you have to think twice about downloading it.

3. The submitter of a patch can remove the patch. I can't verify this  
but the original submitter should be able to. If there is a problem,  
we can fix JIRA to allow it.

Craig

Begin forwarded message:

> From: "Patrick Linskey (JIRA)" <ji...@apache.org>
> Date: November 20, 2007 11:34:43 AM PST
> To: dev@openjpa.apache.org
> Subject: [jira] Commented: (OPENJPA-446) Problem when setting  
> String fields of detached objects
> Reply-To: dev@openjpa.apache.org
>
>
>     [ https://issues.apache.org/jira/browse/OPENJPA-446? 
> page=com.atlassian.jira.plugin.system.issuetabpanels:comment- 
> tabpanel#action_12544020 ]
>
> Patrick Linskey commented on OPENJPA-446:
> -----------------------------------------
>
> Thanks for the debugging work on this.
>
> Is it ok for us to put the DetachAttachTest.zip test files into  
> OpenJPA under the ASL license?
>
>> Problem when setting String fields of detached objects
>> ------------------------------------------------------
>>
>>                 Key: OPENJPA-446
>>                 URL: https://issues.apache.org/jira/browse/ 
>> OPENJPA-446
>>             Project: OpenJPA
>>          Issue Type: Bug
>>          Components: jpa, kernel
>>    Affects Versions: 1.0.1
>>         Environment: OpenJPA 1.0.1
>> Java 1.5.0_13
>> MySQL Server 5.0
>> MySQL Connector Java 5.0.6
>>            Reporter: Jonas Petersen
>>             Fix For: 1.0.2, 1.1.0
>>
>>         Attachments: detach-attach-fix-proper.patch, detach-attach- 
>> fix.patch, DetachAttachTest.zip
>>
>>
>> I would like to report some strange behavior with detach and  
>> merge. To me it looks like a bug.
>> I'm trying implement the following strategy:
>>
>> persistence context A:
>>   1. get persistent object
>>   2. detach the object
>> no persistence context:
>>   3. modify the (detached) object
>> persistence context B:
>>   4. attach (merge) the object
>> This is quite simple and straight forward. It generally works  
>> except in one situation. When committing the merge() (step 4) an  
>> "optimistic locking error" is is thrown under the following  
>> condition: (step 3) a (String) field is set to the same text that  
>> it already contains but using a different String instance. In  
>> other words, when the following expressions are true:
>>
>>     newString.equals(oldString)
>>     newString != oldString
>> I have written some test code that reproduces this effect (see  
>> Attachment).
>> The tests are using the same code except for one line:
>> Test 1 sets the String to a different one than the object contains:
>>     record.setContent("a text different than the one in the record");
>> Test 2 sets the String to the same instance the object contains:
>>   record.setContent(record.getContent());
>> Test 3 sets the String to the same text but as a different String  
>> instance:
>>   record.setContent(record.getContent()+"");
>>  This is the result (output of the test run):
>> ----------------------------------
>> Test 1: SUCCESS
>> Test 2: SUCCESS
>> Test 3: FAILED (Optimistic locking errors were detected when flushing
>>                 to the data store. The following objects may have  
>> been
>>                 concurrently modified in another transaction:
>>                 [test.Record-1])
>> ----------------------------------
>> While doing some debugging I noticed two things:
>> 1. When setting the value:
>> Class: org.apache.openjpa.kernel.DetachedStateManager
>> Line: 555
>> Method: settingStringField()
>>         if (cur == next || !_loaded.get(idx))
>>           return;
>> Here the old and the new value (String) is compared with the ==  
>> operator.
>> The expression can be false with the same text (but different  
>> instances). I find this interesting as it matches exacly the  
>> problematic condition. I think an .equals() would fix the issue I  
>> am having. But I suppose there is something going wrong at another  
>> place as well.
>> 2. Here is the point where execution splits into different ways  
>> when calling commit().
>> Class: org.apache.openjpa.jdbc.kernel.AbstractUpdateManager
>> Line: 151
>> Method: populateRowManager()
>>     } else if ((dirty = ImplHelper.getUpdateFields(sm)) != null) {
>> In the tests that succeed "ImplHelper.getUpdateFields(sm)" will  
>> return a BitSet. So the condition is true.
>> In the tests that fail "ImplHelper.getUpdateFields(sm)" will  
>> return null. So the condition is false.
>> Note: the problem persist with OpenJPA 1.1.0-SNAPSHOT. When run  
>> without enhancing the Record class, all tests will succeed though  
>> (printing this message „INFO   [main] openjpa.Enhance - Creating  
>> subclass for "[class test.Record]". This means that your  
>> application will be less efficient and will consume more memory  
>> than it would if you ran the OpenJPA enhancer. Additionally, lazy  
>> loading will not be available for one-to-one and many-to-one  
>> persistent attributes in types using field access; they will be  
>> loaded eagerly instead.")
>> Regards
>> Jonas
>
> -- 
> This message is automatically generated by JIRA.
> -
> You can reply to this email to add a comment to the issue online.
>

Craig Russell
Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
408 276-5638 mailto:Craig.Russell@sun.com
P.S. A good JDO? O, Gasp!


[jira] Commented: (OPENJPA-446) Problem when setting String fields of detached objects

Posted by "Patrick Linskey (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/OPENJPA-446?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12544020 ] 

Patrick Linskey commented on OPENJPA-446:
-----------------------------------------

Thanks for the debugging work on this.

Is it ok for us to put the DetachAttachTest.zip test files into OpenJPA under the ASL license?

> Problem when setting String fields of detached objects
> ------------------------------------------------------
>
>                 Key: OPENJPA-446
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-446
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: jpa, kernel
>    Affects Versions: 1.0.1
>         Environment: OpenJPA 1.0.1
> Java 1.5.0_13
> MySQL Server 5.0
> MySQL Connector Java 5.0.6
>            Reporter: Jonas Petersen
>             Fix For: 1.0.2, 1.1.0
>
>         Attachments: detach-attach-fix-proper.patch, detach-attach-fix.patch, DetachAttachTest.zip
>
>
> I would like to report some strange behavior with detach and merge. To me it looks like a bug.
> I'm trying implement the following strategy:
>  
> persistence context A:
>   1. get persistent object
>   2. detach the object
> no persistence context:
>   3. modify the (detached) object
> persistence context B:
>   4. attach (merge) the object
> This is quite simple and straight forward. It generally works except in one situation. When committing the merge() (step 4) an "optimistic locking error" is is thrown under the following condition: (step 3) a (String) field is set to the same text that it already contains but using a different String instance. In other words, when the following expressions are true:
>     
>     newString.equals(oldString)
>     newString != oldString
> I have written some test code that reproduces this effect (see Attachment).
> The tests are using the same code except for one line:
> Test 1 sets the String to a different one than the object contains:
>     record.setContent("a text different than the one in the record");
> Test 2 sets the String to the same instance the object contains:
>   record.setContent(record.getContent());
> Test 3 sets the String to the same text but as a different String instance:
>   record.setContent(record.getContent()+"");
>  This is the result (output of the test run):
> ----------------------------------
> Test 1: SUCCESS
> Test 2: SUCCESS
> Test 3: FAILED (Optimistic locking errors were detected when flushing 
>                 to the data store. The following objects may have been
>                 concurrently modified in another transaction: 
>                 [test.Record-1])
> ----------------------------------
> While doing some debugging I noticed two things:
> 1. When setting the value:
> Class: org.apache.openjpa.kernel.DetachedStateManager
> Line: 555
> Method: settingStringField()
>         if (cur == next || !_loaded.get(idx))
>           return;
> Here the old and the new value (String) is compared with the == operator.
> The expression can be false with the same text (but different instances). I find this interesting as it matches exacly the problematic condition. I think an .equals() would fix the issue I am having. But I suppose there is something going wrong at another place as well.
> 2. Here is the point where execution splits into different ways when calling commit().
> Class: org.apache.openjpa.jdbc.kernel.AbstractUpdateManager
> Line: 151
> Method: populateRowManager()
>     } else if ((dirty = ImplHelper.getUpdateFields(sm)) != null) {
> In the tests that succeed "ImplHelper.getUpdateFields(sm)" will return a BitSet. So the condition is true.
> In the tests that fail "ImplHelper.getUpdateFields(sm)" will return null. So the condition is false.
> Note: the problem persist with OpenJPA 1.1.0-SNAPSHOT. When run without enhancing the Record class, all tests will succeed though (printing this message „INFO   [main] openjpa.Enhance - Creating subclass for "[class test.Record]". This means that your application will be less efficient and will consume more memory than it would if you ran the OpenJPA enhancer. Additionally, lazy loading will not be available for one-to-one and many-to-one persistent attributes in types using field access; they will be loaded eagerly instead.")
> Regards
> Jonas

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Commented: (OPENJPA-446) Problem when setting String fields of detached objects

Posted by "Patrick Linskey (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/OPENJPA-446?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12548941 ] 

Patrick Linskey commented on OPENJPA-446:
-----------------------------------------

I think that this patch should be applied for any non-primitive setting*Field() methods.

> Problem when setting String fields of detached objects
> ------------------------------------------------------
>
>                 Key: OPENJPA-446
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-446
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: jpa, kernel
>    Affects Versions: 1.0.1
>         Environment: OpenJPA 1.0.1
> Java 1.5.0_13
> MySQL Server 5.0
> MySQL Connector Java 5.0.6
>            Reporter: Jonas Petersen
>             Fix For: 1.0.2, 1.1.0
>
>         Attachments: detach-attach-fix-proper.patch, detach-attach-fix.patch, DetachAttachTest-updated.zip, DetachAttachTest.zip
>
>
> I would like to report some strange behavior with detach and merge. To me it looks like a bug.
> I'm trying implement the following strategy:
>  
> persistence context A:
>   1. get persistent object
>   2. detach the object
> no persistence context:
>   3. modify the (detached) object
> persistence context B:
>   4. attach (merge) the object
> This is quite simple and straight forward. It generally works except in one situation. When committing the merge() (step 4) an "optimistic locking error" is is thrown under the following condition: (step 3) a (String) field is set to the same text that it already contains but using a different String instance. In other words, when the following expressions are true:
>     
>     newString.equals(oldString)
>     newString != oldString
> I have written some test code that reproduces this effect (see Attachment).
> The tests are using the same code except for one line:
> Test 1 sets the String to a different one than the object contains:
>     record.setContent("a text different than the one in the record");
> Test 2 sets the String to the same instance the object contains:
>   record.setContent(record.getContent());
> Test 3 sets the String to the same text but as a different String instance:
>   record.setContent(record.getContent()+"");
>  This is the result (output of the test run):
> ----------------------------------
> Test 1: SUCCESS
> Test 2: SUCCESS
> Test 3: FAILED (Optimistic locking errors were detected when flushing 
>                 to the data store. The following objects may have been
>                 concurrently modified in another transaction: 
>                 [test.Record-1])
> ----------------------------------
> While doing some debugging I noticed two things:
> 1. When setting the value:
> Class: org.apache.openjpa.kernel.DetachedStateManager
> Line: 555
> Method: settingStringField()
>         if (cur == next || !_loaded.get(idx))
>           return;
> Here the old and the new value (String) is compared with the == operator.
> The expression can be false with the same text (but different instances). I find this interesting as it matches exacly the problematic condition. I think an .equals() would fix the issue I am having. But I suppose there is something going wrong at another place as well.
> 2. Here is the point where execution splits into different ways when calling commit().
> Class: org.apache.openjpa.jdbc.kernel.AbstractUpdateManager
> Line: 151
> Method: populateRowManager()
>     } else if ((dirty = ImplHelper.getUpdateFields(sm)) != null) {
> In the tests that succeed "ImplHelper.getUpdateFields(sm)" will return a BitSet. So the condition is true.
> In the tests that fail "ImplHelper.getUpdateFields(sm)" will return null. So the condition is false.
> Note: the problem persist with OpenJPA 1.1.0-SNAPSHOT. When run without enhancing the Record class, all tests will succeed though (printing this message „INFO   [main] openjpa.Enhance - Creating subclass for "[class test.Record]". This means that your application will be less efficient and will consume more memory than it would if you ran the OpenJPA enhancer. Additionally, lazy loading will not be available for one-to-one and many-to-one persistent attributes in types using field access; they will be loaded eagerly instead.")
> Regards
> Jonas

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.