[hibernate-commits] Hibernate SVN: r18699 - in core/trunk: core/src/main/java/org/hibernate/event/def and 6 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Thu Feb 4 23:00:05 EST 2010


Author: gbadner
Date: 2010-02-04 23:00:04 -0500 (Thu, 04 Feb 2010)
New Revision: 18699

Added:
   core/trunk/core/src/main/java/org/hibernate/proxy/AbstractSerializableProxy.java
Modified:
   core/trunk/core/src/main/java/org/hibernate/engine/StatefulPersistenceContext.java
   core/trunk/core/src/main/java/org/hibernate/engine/TwoPhaseLoad.java
   core/trunk/core/src/main/java/org/hibernate/event/def/DefaultLoadEventListener.java
   core/trunk/core/src/main/java/org/hibernate/proxy/AbstractLazyInitializer.java
   core/trunk/core/src/main/java/org/hibernate/proxy/LazyInitializer.java
   core/trunk/core/src/main/java/org/hibernate/proxy/pojo/cglib/CGLIBLazyInitializer.java
   core/trunk/core/src/main/java/org/hibernate/proxy/pojo/cglib/SerializableProxy.java
   core/trunk/core/src/main/java/org/hibernate/proxy/pojo/javassist/JavassistLazyInitializer.java
   core/trunk/core/src/main/java/org/hibernate/proxy/pojo/javassist/SerializableProxy.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/nonflushedchanges/GetLoadTest.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/proxy/ProxyTest.java
   core/trunk/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyProxyTest.java
Log:
HHH-4841 : Read-only proxies in NonFlushedChanges are not read-only when applied to a new session

Modified: core/trunk/core/src/main/java/org/hibernate/engine/StatefulPersistenceContext.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/engine/StatefulPersistenceContext.java	2010-02-05 02:42:55 UTC (rev 18698)
+++ core/trunk/core/src/main/java/org/hibernate/engine/StatefulPersistenceContext.java	2010-02-05 04:00:04 UTC (rev 18699)
@@ -672,10 +672,19 @@
 			}
 			else {
 				proxy = persister.createProxy( key.getIdentifier(), session );
-				proxiesByKey.put(key, proxy); //overwrite old proxy
+				Object proxyOrig = proxiesByKey.put(key, proxy); //overwrite old proxy
+				if ( proxyOrig != null ) {
+					if ( ! ( proxyOrig instanceof HibernateProxy ) ) {
+						throw new AssertionFailure(
+								"proxy not of type HibernateProxy; it is " + proxyOrig.getClass()
+						);
+					}
+					// set the read-only/modifiable mode in the new proxy to what it was in the original proxy
+					boolean readOnlyOrig = ( ( HibernateProxy ) proxyOrig ).getHibernateLazyInitializer().isReadOnly();
+					( ( HibernateProxy ) proxy ).getHibernateLazyInitializer().setReadOnly( readOnlyOrig );
+				}
 				return proxy;
-			}
-			
+			}			
 		}
 		else {
 			

Modified: core/trunk/core/src/main/java/org/hibernate/engine/TwoPhaseLoad.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/engine/TwoPhaseLoad.java	2010-02-05 02:42:55 UTC (rev 18698)
+++ core/trunk/core/src/main/java/org/hibernate/engine/TwoPhaseLoad.java	2010-02-05 04:00:04 UTC (rev 18699)
@@ -190,13 +190,18 @@
 			}
 		}
 
-		boolean isReallyReadOnly = readOnly || !persister.isMutable();
-		Object proxy = persistenceContext.getProxy( entityEntry.getEntityKey() );
-		if ( proxy != null ) {
-			// there is already a proxy for this impl
-			// only set the status to read-only if the proxy is read-only
-			isReallyReadOnly = ( ( HibernateProxy ) proxy ).getHibernateLazyInitializer().isReadOnly();
+		boolean isReallyReadOnly = readOnly;
+		if ( !persister.isMutable() ) {
+			isReallyReadOnly = true;
 		}
+		else {
+			Object proxy = persistenceContext.getProxy( entityEntry.getEntityKey() );
+			if ( proxy != null ) {
+				// there is already a proxy for this impl
+				// only set the status to read-only if the proxy is read-only
+				isReallyReadOnly = ( ( HibernateProxy ) proxy ).getHibernateLazyInitializer().isReadOnly();
+			}
+		}
 		if ( isReallyReadOnly ) {
 			//no need to take a snapshot - this is a 
 			//performance optimization, but not really

Modified: core/trunk/core/src/main/java/org/hibernate/event/def/DefaultLoadEventListener.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/event/def/DefaultLoadEventListener.java	2010-02-05 02:42:55 UTC (rev 18698)
+++ core/trunk/core/src/main/java/org/hibernate/event/def/DefaultLoadEventListener.java	2010-02-05 04:00:04 UTC (rev 18699)
@@ -360,9 +360,6 @@
 			Object proxy = persister.createProxy( event.getEntityId(), event.getSession() );
 			persistenceContext.getBatchFetchQueue().addBatchLoadableEntityKey(keyToLoad);
 			persistenceContext.addProxy(keyToLoad, proxy);
-			( ( HibernateProxy ) proxy )
-					.getHibernateLazyInitializer()
-					.setReadOnly( event.getSession().isDefaultReadOnly() || ! persister.isMutable() );
 			return proxy;
 		}
 	}

Modified: core/trunk/core/src/main/java/org/hibernate/proxy/AbstractLazyInitializer.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/proxy/AbstractLazyInitializer.java	2010-02-05 02:42:55 UTC (rev 18698)
+++ core/trunk/core/src/main/java/org/hibernate/proxy/AbstractLazyInitializer.java	2010-02-05 04:00:04 UTC (rev 18699)
@@ -26,12 +26,14 @@
 
 import java.io.Serializable;
 
+import org.hibernate.AssertionFailure;
 import org.hibernate.HibernateException;
 import org.hibernate.LazyInitializationException;
 import org.hibernate.TransientObjectException;
 import org.hibernate.SessionException;
 import org.hibernate.engine.EntityKey;
 import org.hibernate.engine.SessionImplementor;
+import org.hibernate.persister.entity.EntityPersister;
 
 /**
  * Convenience base class for lazy initialization handlers.  Centralizes the basic plumbing of doing lazy
@@ -48,6 +50,7 @@
 	private boolean readOnly;
 	private boolean unwrap;
 	private transient SessionImplementor session;
+	private Boolean readOnlyBeforeAttachedToSession;
 
 	/**
 	 * For serialization from the non-pojo initializers (HHH-3309)
@@ -65,11 +68,9 @@
 	protected AbstractLazyInitializer(String entityName, Serializable id, SessionImplementor session) {
 		this.entityName = entityName;
 		this.id = id;
-		this.readOnly = false;
 		// initialize other fields depending on session state
 		if ( session == null ) {
-			// would be better to call unsetSession(), but it is not final...
-			session = null;
+			unsetSession();
 		}
 		else {
 			setSession( session );
@@ -116,18 +117,27 @@
 	 */
 	public final void setSession(SessionImplementor s) throws HibernateException {
 		if ( s != session ) {
-			readOnly = false;
 			// check for s == null first, since it is least expensive
 			if ( s == null ){
-				// would be better to call unsetSession(), but it is not final...
-				session = null;
+				unsetSession();
 			}
 			else if ( isConnectedToSession() ) {
 				//TODO: perhaps this should be some other RuntimeException...
 				throw new HibernateException("illegally attempted to associate a proxy with two open Sessions");
 			}
 			else {
+				// s != null
 				session = s;
+				if ( readOnlyBeforeAttachedToSession == null ) {
+					// use the default read-only/modifiable setting
+					final EntityPersister persister = s.getFactory().getEntityPersister( entityName );
+					setReadOnly( s.getPersistenceContext().isDefaultReadOnly() || ! persister.isMutable() );
+				}
+				else {
+					// use the read-only/modifiable setting indicated during deserialization
+					setReadOnly( readOnlyBeforeAttachedToSession.booleanValue() );
+					readOnlyBeforeAttachedToSession = null;
+				}
 			}
 		}
 	}
@@ -142,9 +152,10 @@
 	/**
 	 * {@inheritDoc}
 	 */
-	public void unsetSession() {
+	public final void unsetSession() {
 		session = null;
 		readOnly = false;
+		readOnlyBeforeAttachedToSession = null;
 	}
 
 	/**
@@ -236,43 +247,90 @@
 	/**
 	 * {@inheritDoc}
 	 */
-	public boolean isReadOnly() {
-		errorIfReadOnlySettingNotAvailable();
-		if ( !isConnectedToSession() ) {
+	public final boolean isReadOnlySettingAvailable() {
+		return ( session != null && ! session.isClosed() );
+	}
+
+	private void errorIfReadOnlySettingNotAvailable() {
+		if ( session == null ) {
 			throw new TransientObjectException(
-					"The read-only/modifiable setting is only accessible when the proxy is associated with a session." );
+					"Proxy is detached (i.e, session is null). The read-only/modifiable setting is only accessible when the proxy is associated with an open session." );
 		}
+		if ( session.isClosed() ) {
+			throw new SessionException(
+					"Session is closed. The read-only/modifiable setting is only accessible when the proxy is associated with an open session." );
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public final boolean isReadOnly() {
+		errorIfReadOnlySettingNotAvailable();
 		return readOnly;
 	}
 
 	/**
 	 * {@inheritDoc}
 	 */
-	public void setReadOnly(boolean readOnly) {
+	public final void setReadOnly(boolean readOnly) {
 		errorIfReadOnlySettingNotAvailable();
 		// only update if readOnly is different from current setting
 		if ( this.readOnly != readOnly ) {
-			Object proxy = getProxyOrNull();
-			if ( proxy == null ) {
-				throw new TransientObjectException(
-						"Cannot set the read-only/modifiable mode unless the proxy is associated with a session." );
+			final EntityPersister persister = session.getFactory().getEntityPersister( entityName );
+			if ( ! persister.isMutable() && ! readOnly ) {
+				throw new IllegalStateException( "cannot make proxies for immutable entities modifiable");
 			}
 			this.readOnly = readOnly;
 			if ( initialized ) {
-				session.getPersistenceContext().setReadOnly( target, readOnly );
+				EntityKey key = generateEntityKeyOrNull( getIdentifier(), session, getEntityName() );
+				if ( key != null && session.getPersistenceContext().containsEntity( key ) ) {
+					session.getPersistenceContext().setReadOnly( target, readOnly );
+				}
 			}
 		}
 	}
 
-	private void errorIfReadOnlySettingNotAvailable() {
-		if ( session == null ) {
-			throw new TransientObjectException(
-					"Proxy is detached (i.e, session is null). The read-only/modifiable setting is only accessible when the proxy is associated with an open session." );
+	/**
+	 * Get the read-only/modifiable setting that should be put in affect when it is
+	 * attached to a session.
+	 *
+	 * This method should only be called during serialization when read-only/modifiable setting
+	 * is not available (i.e., isReadOnlySettingAvailable() == false)
+	 *
+	 * @returns, null, if the default setting should be used;
+	 *           true, for read-only;
+	 *           false, for modifiable
+	 * @throws IllegalStateException if isReadOnlySettingAvailable() == true
+	 */
+	protected final Boolean isReadOnlyBeforeAttachedToSession() {
+		if ( isReadOnlySettingAvailable() ) {
+			throw new IllegalStateException(
+					"Cannot call isReadOnlyBeforeAttachedToSession when isReadOnlySettingAvailable == true"
+			);
 		}
-		if ( session.isClosed() ) {
-			throw new SessionException(
-					"Session is closed. The read-only/modifiable setting is only accessible when the proxy is associated with an open session." );
+		return readOnlyBeforeAttachedToSession;
+	}
+
+	/**
+	 * Set the read-only/modifiable setting that should be put in affect when it is
+	 * attached to a session.
+	 *
+	 * This method should only be called during deserialization, before associating
+	 * the proxy with a session.
+	 *
+	 * @param readOnlyBeforeAttachedToSession, the read-only/modifiable setting to use when
+	 * associated with a session; null indicates that the default should be used.
+	 * @throws IllegalStateException if isReadOnlySettingAvailable() == true
+	 */
+	/* package-private */
+	final void setReadOnlyBeforeAttachedToSession(Boolean readOnlyBeforeAttachedToSession) {
+		if ( isReadOnlySettingAvailable() ) {
+			throw new IllegalStateException(
+					"Cannot call setReadOnlyBeforeAttachedToSession when isReadOnlySettingAvailable == true"
+			);
 		}
+		this.readOnlyBeforeAttachedToSession = readOnlyBeforeAttachedToSession;
 	}
 
 	/**

Added: core/trunk/core/src/main/java/org/hibernate/proxy/AbstractSerializableProxy.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/proxy/AbstractSerializableProxy.java	                        (rev 0)
+++ core/trunk/core/src/main/java/org/hibernate/proxy/AbstractSerializableProxy.java	2010-02-05 04:00:04 UTC (rev 18699)
@@ -0,0 +1,72 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.proxy;
+
+import java.io.Serializable;
+
+/**
+ * Convenience base class for SerializableProxy.
+ * 
+ * @author Gail Badner
+ */
+public abstract class AbstractSerializableProxy implements Serializable {
+	private String entityName;
+	private Serializable id;
+	private Boolean readOnly;
+
+	/**
+	 * For serialization
+	 */
+	protected AbstractSerializableProxy() {
+	}
+
+	protected AbstractSerializableProxy(String entityName, Serializable id, Boolean readOnly) {
+		this.entityName = entityName;
+		this.id = id;
+		this.readOnly = readOnly;
+	}
+
+	protected String getEntityName() {
+		return entityName;
+	}
+
+	protected Serializable getId() {
+		return id;
+	}
+
+	/**
+	 * Set the read-only/modifiable setting from this object in an AbstractLazyInitializer.
+	 *
+	 * This method should only be called during deserialization, before associating the
+	 * AbstractLazyInitializer with a session.
+	 *
+	 * @param li, the read-only/modifiable setting to use when
+	 * associated with a session; null indicates that the default should be used.
+	 * @throws IllegalStateException if isReadOnlySettingAvailable() == true
+	 */
+	protected void setReadOnlyBeforeAttachedToSession(AbstractLazyInitializer li) {
+		li.setReadOnlyBeforeAttachedToSession( readOnly );
+	}
+}

Modified: core/trunk/core/src/main/java/org/hibernate/proxy/LazyInitializer.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/proxy/LazyInitializer.java	2010-02-05 02:42:55 UTC (rev 18698)
+++ core/trunk/core/src/main/java/org/hibernate/proxy/LazyInitializer.java	2010-02-05 04:00:04 UTC (rev 18699)
@@ -105,10 +105,23 @@
 	public void setImplementation(Object target);
 
 	/**
+	 * Is the proxy's read-only/modifiable setting available?
+	 * @return true, if the setting is available
+	 *         false, if the proxy is detached or its associated session is closed
+	 */
+	public boolean isReadOnlySettingAvailable();
+
+	/**
 	 * Is the proxy read-only?.
 	 *
+	 * The read-only/modifiable setting is not available when the proxy is
+	 * detached or its associated session is closed.
+	 *
+	 * To check if the read-only/modifiable setting is available:
+	 * @see org.hibernate.proxy.LazyInitializer#isReadOnlySettingAvailable()
+	 *
 	 * @return true, if this proxy is read-only; false, otherwise
-	 * @throws org.hibernate.TransientObjectException if the proxy is not association with a session
+	 * @throws org.hibernate.TransientObjectException if the proxy is detached (getSession() == null)
 	 * @throws org.hibernate.SessionException if the proxy is associated with a sesssion that is closed
 	 *
 	 * @see org.hibernate.Session#isReadOnly(Object entityOrProxy)

Modified: core/trunk/core/src/main/java/org/hibernate/proxy/pojo/cglib/CGLIBLazyInitializer.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/proxy/pojo/cglib/CGLIBLazyInitializer.java	2010-02-05 02:42:55 UTC (rev 18698)
+++ core/trunk/core/src/main/java/org/hibernate/proxy/pojo/cglib/CGLIBLazyInitializer.java	2010-02-05 04:00:04 UTC (rev 18699)
@@ -212,11 +212,10 @@
 				persistentClass,
 				interfaces,
 				getIdentifier(),
-				( getSession() != null && getSession().isOpen() ? isReadOnly() : false ),
+				( isReadOnlySettingAvailable() ? Boolean.valueOf( isReadOnly() ) : isReadOnlyBeforeAttachedToSession() ),
 				getIdentifierMethod,
 				setIdentifierMethod,
 				componentIdType 
 			);
 	}
-
 }

Modified: core/trunk/core/src/main/java/org/hibernate/proxy/pojo/cglib/SerializableProxy.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/proxy/pojo/cglib/SerializableProxy.java	2010-02-05 02:42:55 UTC (rev 18698)
+++ core/trunk/core/src/main/java/org/hibernate/proxy/pojo/cglib/SerializableProxy.java	2010-02-05 04:00:04 UTC (rev 18699)
@@ -28,19 +28,17 @@
 import java.lang.reflect.Method;
 
 import org.hibernate.HibernateException;
+import org.hibernate.proxy.AbstractSerializableProxy;
 import org.hibernate.proxy.HibernateProxy;
 import org.hibernate.type.AbstractComponentType;
 
 /**
  * Serializable placeholder for <tt>CGLIB</tt> proxies
  */
-public final class SerializableProxy implements Serializable {
+public final class SerializableProxy extends AbstractSerializableProxy {
 
-	private String entityName;
 	private Class persistentClass;
 	private Class[] interfaces;
-	private Serializable id;
-	private boolean readOnly;
 	private Class getIdentifierMethodClass;
 	private Class setIdentifierMethodClass;
 	private String getIdentifierMethodName;
@@ -55,16 +53,14 @@
 		final Class persistentClass,
 		final Class[] interfaces,
 		final Serializable id,
-		final boolean readOnly,
+		final Boolean readOnly,
 		final Method getIdentifierMethod,
 		final Method setIdentifierMethod,
 		AbstractComponentType componentIdType
 	) {
-		this.entityName = entityName;
+		super( entityName, id, readOnly );
 		this.persistentClass = persistentClass;
 		this.interfaces = interfaces;
-		this.id = id;
-		this.readOnly = readOnly;
 		if (getIdentifierMethod!=null) {
 			getIdentifierMethodClass = getIdentifierMethod.getDeclaringClass();
 			getIdentifierMethodName = getIdentifierMethod.getName();
@@ -79,8 +75,8 @@
 
 	private Object readResolve() {
 		try {
-			return CGLIBLazyInitializer.getProxy(
-				entityName,
+			HibernateProxy proxy = CGLIBLazyInitializer.getProxy(
+				getEntityName(),
 				persistentClass,
 				interfaces,
 				getIdentifierMethodName==null ?
@@ -90,12 +86,15 @@
 					null :
 					setIdentifierMethodClass.getDeclaredMethod(setIdentifierMethodName, setIdentifierMethodParams),
 					componentIdType,
-				id,
+				getId(),
 				null
 			);
+
+			setReadOnlyBeforeAttachedToSession( ( CGLIBLazyInitializer ) proxy.getHibernateLazyInitializer() );
+			return proxy;
 		}
 		catch (NoSuchMethodException nsme) {
-			throw new HibernateException("could not create proxy for entity: " + entityName, nsme);
+			throw new HibernateException("could not create proxy for entity: " + getEntityName(), nsme);
 		}
 	}
 

Modified: core/trunk/core/src/main/java/org/hibernate/proxy/pojo/javassist/JavassistLazyInitializer.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/proxy/pojo/javassist/JavassistLazyInitializer.java	2010-02-05 02:42:55 UTC (rev 18698)
+++ core/trunk/core/src/main/java/org/hibernate/proxy/pojo/javassist/JavassistLazyInitializer.java	2010-02-05 04:00:04 UTC (rev 18699)
@@ -34,6 +34,7 @@
 import javassist.util.proxy.ProxyObject;
 
 import org.slf4j.LoggerFactory;
+
 import org.hibernate.HibernateException;
 import org.hibernate.engine.SessionImplementor;
 import org.hibernate.proxy.pojo.BasicLazyInitializer;
@@ -229,7 +230,7 @@
 		        persistentClass,
 		        interfaces,
 		        getIdentifier(),
-		        ( getSession() != null && getSession().isOpen() ? isReadOnly() : false ),
+		        ( isReadOnlySettingAvailable() ? Boolean.valueOf( isReadOnly() ) : isReadOnlyBeforeAttachedToSession() ),
 		        getIdentifierMethod,
 		        setIdentifierMethod,
 		        componentIdType

Modified: core/trunk/core/src/main/java/org/hibernate/proxy/pojo/javassist/SerializableProxy.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/proxy/pojo/javassist/SerializableProxy.java	2010-02-05 02:42:55 UTC (rev 18698)
+++ core/trunk/core/src/main/java/org/hibernate/proxy/pojo/javassist/SerializableProxy.java	2010-02-05 04:00:04 UTC (rev 18699)
@@ -28,19 +28,17 @@
 import java.lang.reflect.Method;
 
 import org.hibernate.HibernateException;
+import org.hibernate.proxy.AbstractSerializableProxy;
 import org.hibernate.proxy.HibernateProxy;
 import org.hibernate.type.AbstractComponentType;
 
 /**
  * Serializable placeholder for Javassist proxies
  */
-public final class SerializableProxy implements Serializable {
+public final class SerializableProxy extends AbstractSerializableProxy {
 
-	private String entityName;
 	private Class persistentClass;
 	private Class[] interfaces;
-	private Serializable id;
-	private boolean readOnly;
 	private Class getIdentifierMethodClass;
 	private Class setIdentifierMethodClass;
 	private String getIdentifierMethodName;
@@ -55,16 +53,14 @@
 	    final Class persistentClass,
 	    final Class[] interfaces,
 	    final Serializable id,
-	    final boolean readOnly,
+	    final Boolean readOnly,
 	    final Method getIdentifierMethod,
 	    final Method setIdentifierMethod,
 	    AbstractComponentType componentIdType
 	) {
-		this.entityName = entityName;
+		super( entityName, id, readOnly );
 		this.persistentClass = persistentClass;
 		this.interfaces = interfaces;
-		this.id = id;
-		this.readOnly = readOnly;
 		if (getIdentifierMethod!=null) {
 			getIdentifierMethodClass = getIdentifierMethod.getDeclaringClass();
 			getIdentifierMethodName = getIdentifierMethod.getName();
@@ -79,8 +75,8 @@
 
 	private Object readResolve() {
 		try {
-			return JavassistLazyInitializer.getProxy(
-				entityName,
+			HibernateProxy proxy = JavassistLazyInitializer.getProxy(
+				getEntityName(),
 				persistentClass,
 				interfaces,
 				getIdentifierMethodName==null ?
@@ -90,13 +86,14 @@
 					null :
 					setIdentifierMethodClass.getDeclaredMethod(setIdentifierMethodName, setIdentifierMethodParams),
 					componentIdType,
-				id,
+				getId(),
 				null
 			);
+			setReadOnlyBeforeAttachedToSession( ( JavassistLazyInitializer ) proxy.getHibernateLazyInitializer() );
+			return proxy;
 		}
 		catch (NoSuchMethodException nsme) {
-			throw new HibernateException("could not create proxy for entity: " + entityName, nsme);
+			throw new HibernateException("could not create proxy for entity: " + getEntityName(), nsme);
 		}
 	}
-
 }

Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/nonflushedchanges/GetLoadTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/nonflushedchanges/GetLoadTest.java	2010-02-05 02:42:55 UTC (rev 18698)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/nonflushedchanges/GetLoadTest.java	2010-02-05 04:00:04 UTC (rev 18699)
@@ -185,7 +185,7 @@
 		SimpleJtaTransactionManagerImpl.getInstance().commit();
 	}
 
-	public void testLoadReadOnlyFailureExpected() throws Exception {
+	public void testLoadReadOnly() throws Exception {
 		clearCounts();
 
 		SimpleJtaTransactionManagerImpl.getInstance().begin();

Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/proxy/ProxyTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/proxy/ProxyTest.java	2010-02-05 02:42:55 UTC (rev 18698)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/proxy/ProxyTest.java	2010-02-05 04:00:04 UTC (rev 18699)
@@ -123,6 +123,31 @@
 		s.close();
 	}
 
+	public void testInitializedProxySerializationAfterSessionClosed() {
+		Session s = openSession();
+		Transaction t = s.beginTransaction();
+		DataPoint dp = new DataPoint();
+		dp.setDescription("a data point");
+		dp.setX( new BigDecimal(1.0) );
+		dp.setY( new BigDecimal(2.0) );
+		s.persist(dp);
+		s.flush();
+		s.clear();
+
+		dp = (DataPoint) s.load( DataPoint.class, new Long( dp.getId() ) );
+		assertFalse( Hibernate.isInitialized(dp) );
+		Hibernate.initialize( dp );
+		assertTrue( Hibernate.isInitialized(dp) );
+		s.close();
+		SerializationHelper.clone( dp );
+
+		s = openSession();
+		t = s.beginTransaction();
+		s.delete( dp );
+		t.commit();
+		s.close();
+	}
+
 	public void testProxySerialization() {
 		Session s = openSession();
 		Transaction t = s.beginTransaction();

Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyProxyTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyProxyTest.java	2010-02-05 02:42:55 UTC (rev 18698)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/readonly/ReadOnlyProxyTest.java	2010-02-05 04:00:04 UTC (rev 18699)
@@ -1328,6 +1328,7 @@
 		}
 		catch ( SessionException ex) {
 			// expected
+			assertFalse( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().isReadOnlySettingAvailable() );
 		}
 		finally {
 			s = openSession();
@@ -1360,6 +1361,7 @@
 		}
 		catch ( TransientObjectException ex) {
 			// expected
+			assertFalse( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().isReadOnlySettingAvailable() );
 		}
 		finally {
 			s = openSession();
@@ -1393,6 +1395,7 @@
 		}
 		catch ( TransientObjectException ex) {
 			// expected
+			assertFalse( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().isReadOnlySettingAvailable() );
 		}
 		finally {
 			s.delete( dp );
@@ -1421,6 +1424,7 @@
 		}
 		catch ( TransientObjectException ex) {
 			// expected
+			assertFalse( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().isReadOnlySettingAvailable() );
 		}
 		finally {
 			s.beginTransaction();
@@ -1450,6 +1454,7 @@
 		}
 		catch ( SessionException ex) {
 			// expected
+			assertFalse( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().isReadOnlySettingAvailable() );
 		}
 		finally {
 			s = openSession();
@@ -1482,6 +1487,7 @@
 		}
 		catch ( TransientObjectException ex) {
 			// expected
+			assertFalse( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().isReadOnlySettingAvailable() );
 		}
 		finally {
 			s = openSession();
@@ -1492,7 +1498,40 @@
 		}
 	}
 
+	public void testSetClosedSessionInLazyInitializer() {
+		DataPoint dpOrig = createDataPoint( CacheMode.IGNORE );
 
+		Session s = openSession();
+		s.setCacheMode(CacheMode.IGNORE);
+
+		s.beginTransaction();
+		DataPoint dp = ( DataPoint ) s.load( DataPoint.class, new Long( dpOrig.getId() ) );
+		assertTrue( dp instanceof HibernateProxy );
+		assertFalse( Hibernate.isInitialized( dp ) );
+		checkReadOnly( s, dp, false );
+		s.getTransaction().commit();
+		assertTrue( s.contains( dp ) );
+		s.close();
+
+		assertNull( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().getSession() );
+		assertTrue( ( ( SessionImplementor ) s ).isClosed() );
+		try {
+			( ( HibernateProxy ) dp ).getHibernateLazyInitializer().setSession( ( SessionImplementor ) s );			
+			fail( "should have failed because session was closed" );
+		}
+		catch ( SessionException ex) {
+			// expected
+			assertFalse( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().isReadOnlySettingAvailable() );
+		}
+		finally {
+			s = openSession();
+			s.beginTransaction();
+			s.delete( dp );
+			s.getTransaction().commit();
+			s.close();
+		}
+	}
+
 	public void testDetachedSetReadOnlyAfterEvictViaSession() {
 		DataPoint dpOrig = createDataPoint( CacheMode.IGNORE );
 
@@ -1515,6 +1554,7 @@
 		}
 		catch ( TransientObjectException ex) {
 			// expected
+			assertFalse( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().isReadOnlySettingAvailable() );
 		}
 		finally {
 			s.delete( dp );
@@ -1543,6 +1583,7 @@
 		}
 		catch ( TransientObjectException ex) {
 			// expected
+			assertFalse( ( ( HibernateProxy ) dp ).getHibernateLazyInitializer().isReadOnlySettingAvailable() );
 		}
 		finally {
 			s.beginTransaction();



More information about the hibernate-commits mailing list