We're updating the issue view to help you get more done. 

ClassCastException inside proxy without explicit casting in application code

Description

Noticed that an lazily-loaded entity was getting a ClassCastException inside the proxy method without any explicit casting in the application code. I've pared down the issue to a minimal example and attached a FunctionalTestCase. See:

BaseClass.java

1 2 3 4 public abstract class BaseClass { public abstract SubClass toSubClass(); }

SubClass.java

1 2 3 4 5 6 public class SubClass extends BaseClass { public Subclass toSubClass() { return this; } }

ProxySubclassTest.java

1 2 3 4 5 6 7 8 9 10 11 public void testProxySubclass() throws Exception { s = this.openSession(); tx = s.beginTransaction(); LazyReferenceToBaseClass lazyReferenceToBaseClass = (LazyReferenceToBaseClass) s.load(LazyReferenceToBaseClass.class, lazyReferenceToBaseClassId); BaseClass baseClass = lazyReferenceToBaseClass.getBaseClass(); SubClass subClass = baseClass.toSubClass(); // Throws // java.lang.ClassCastException: BaseClass_$$_javassist_1 cannot be cast to SubClass // at BaseClass_$$_javassist_1.toSubClass(BaseClass_$$_javassist_1.java) }

This is clearly related to "the dreaded proxy problem" with its variety of solutions/workarounds(http://community.jboss.org/wiki/ProxyVisitorPattern) but in those cases the application code makes a mistaken assumption that it can downcast a proxy. In this example, there is no explicit downcasting, although I suppose SubClass.toSubClass() could be considered "implicit downcasting". Within SubClass, "this" must refer to an instance of SubClass, and it presumably should be returnable as such.

I haven't checked what's going on in the proxy code, but I presume that it sees that it is trying to return the item corresponding to the proxy itself, and attempts to return that proxy. However the proxy is not an instance of SubClass and there is a ClassCastException.

I'd suggest one of the following solutions:

  • have the proxy return the unproxied (already initialized) object if it cannot cast it appropriately

  • have the proxy re-proxy the already initialized object into an instance of the appropriate class

  • have some explicit documentation as to why this cannot be expected to work and why domain classes need to avoid this behavior.

In any case it seems poor that even improperly written entity code can cause an exception inside the proxy-specific code.

Environment

Hibernate version 3.6.6
database-independent
JDK 1.6
Windows 7 and Linux
CGLib and javassist

Status

Assignee

Brett Meyer

Reporter

Joseph Calzaretta

Fix versions

backPortable

None

Suitable for new contributors

None

Requires Release Note

None

Pull Request

None

backportDecision

None

Components

Affects versions

3.6.6

Priority

Major