]
Gail Badner updated HHH-5207:
-----------------------------
Attachment: HHH-5207.patch
Unexpected exception occurs during refresh of a transient immutable
business object.
------------------------------------------------------------------------------------
Key: HHH-5207
URL:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-5207
Project: Hibernate Core
Issue Type: Bug
Components: core
Affects Versions: 3.5.0-Final, 3.5.1
Environment: Oracle9i Enterprise Edition Release 9.2.0.8.0 - 64bit Production,
Hibernate 3.5.1,
Spring 3.0.2,
Struts 1.3.10,
J2SE 1.6.0_14
Reporter: James Norton
Assignee: Gail Badner
Fix For: 3.5.2
Attachments: HHH-5207.patch, TestCase.zip
As mentioned in the Hibernate Forums (_[Cannot make an immutable entity
modifiable|https://forums.hibernate.org/viewtopic.php?f=1&t=1003756]_), I am dealing
with an issue brought to my attention wherein a detached transient business object is
being refreshed by the session and returns an exception. The exception(_See Below_) is
thrown from within the DefaultRefreshEventListener's onRefresh method at the end of
processing just prior to returning the refreshed object.
----
{{{code:title=The Exception}
java.lang.IllegalStateException: Cannot make an immutable entity modifiable.
at org.hibernate.engine.EntityEntry.setReadOnly(EntityEntry.java:314)
at
org.hibernate.engine.StatefulPersistenceContext.setEntityReadOnly(StatefulPersistenceContext.java:1388)
at
org.hibernate.engine.StatefulPersistenceContext.setReadOnly(StatefulPersistenceContext.java:1365)
at org.hibernate.impl.SessionImpl.setReadOnly(SessionImpl.java:1982)
at
org.hibernate.event.def.DefaultRefreshEventListener.onRefresh(DefaultRefreshEventListener.java:155)
at
org.hibernate.event.def.DefaultRefreshEventListener.onRefresh(DefaultRefreshEventListener.java:62)
at org.hibernate.impl.SessionImpl.fireRefresh(SessionImpl.java:1108)
at org.hibernate.impl.SessionImpl.refresh(SessionImpl.java:1088)
at bug.BugReport.testRefreshTransientImmutable(BugReport.java:136)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at junit.framework.TestCase.runTest(TestCase.java:168)
at
org.hibernate.junit.functional.FunctionalTestCase.runTest(FunctionalTestCase.java:125)
at junit.framework.TestCase.runBare(TestCase.java:134)
at org.hibernate.junit.UnitTestCase.runBare(UnitTestCase.java:63)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at junit.framework.TestSuite.runTest(TestSuite.java:243)
at
org.hibernate.junit.functional.FunctionalTestClassTestSuite.runTest(FunctionalTestClassTestSuite.java:115)
at junit.framework.TestSuite.run(TestSuite.java:238)
at
org.hibernate.junit.functional.FunctionalTestClassTestSuite.run(FunctionalTestClassTestSuite.java:84)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83)
at
org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
{code}}}
----
This problem showed up during an update from Hibernate libraries 3.3.2. The issue was
proven not to exist in the previous version through the attached test case. It is mine
and my coworkers opinion that the issue lies with the DefaultRefreshEventListener
attempting to set the read only state of the refreshed object _back_ to the state that it
was in prior to refreshing. Being that the object is detached from the current session,
and therefore viewed as transient, the previous state of the object cannot be ascertained
and the listener tries to set the read only to source default.
----
{{{code:title=DefaultRefreshEventListener lines 152 - 156 \\\\ onRefresh(RefreshEvent
event, Map refreshedAlready)}
// Keep the same read-only/modifiable setting for the entity that it had before
refreshing;
// If it was transient, then set it to the default for the source.
if ( result != null ) {
source.setReadOnly( result, ( e == null ? source.isDefaultReadOnly() : e.isReadOnly() )
);
}
{code}}}
----
While this appears to be a fairly straightforward procedure, the object being refreshed
is immutable. With the object being transient, the persistence context does not have an
entry for the object and the _source_ tries to {{*setReadOnly*}} to
{{source.isDefaultReadOnly()}}. This results in the session trying to set an immutable
object's state to writable.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: