Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » Can not set ManyToOne field to inherited entity
Can not set ManyToOne field to inherited entity [message #901019] Thu, 09 August 2012 08:26 Go to next message
Markus KARG is currently offline Markus KARG
Messages: 28
Registered: June 2011
Junior Member
Scenario:

P is marked as @Entity @Inheritance

C1 extends P and is marked as @Entity

C2 extends P and is marked as @Entity and has @ManyToOne referencing P (named "parent")

Using this we can build trees, as C2 has a tree uplink that can point to either C1 or C2 thanks to the common ancestor P:

C1
!
+- C2 ("parent" points to C1 instance)
...!
...+- C2 ("parent" points to C2 instance)
......!
......+- C2
.........!
............

Accessing a collection that contains C2 instances failes with the following message:

"Trying to set value [C1] for instance variable [parent] of type [P] in the object. The specified object is not an instance of the class or interface declaring the underlying field, or an unwrapping conversion has failed."

Well, as C1 is a descendent of P, the above message is wrong!

We are totally stuck now as we may not change the table schema, but have to deliver a JPA based software which is able to reflect this flexible type of trees. Is there a workaround or patch we can apply to convince EclipseLink that a C1 instance is definitively a P due to the inheritance?

(Already filed in bugzilla https://bugs.eclipse.org/bugs/show_bug.cgi?id=386389, but no comments so far)

Thanks!
Markus
Re: Can not set ManyToOne field to inherited entity [message #901591 is a reply to message #901019] Mon, 13 August 2012 10:52 Go to previous messageGo to next message
Chris Delahunt is currently offline Chris Delahunt
Messages: 1018
Registered: July 2009
Senior Member
Markus,

Can you please show what you mean when you say parent points to C1/C2 and the stack trace for the exception? This seems like simple inheritance where P would have a OneToMany relationship to other P, and each P would have a ManyToOne back to P. Are you overriding this in the children classes somehow?

In the future it is also a good idea to upload code to bugs that can show how they are reproduced.

Best Regards,
Chris
Re: Can not set ManyToOne field to inherited entity [message #901769 is a reply to message #901591] Tue, 14 August 2012 09:50 Go to previous messageGo to next message
Markus KARG is currently offline Markus KARG
Messages: 28
Registered: June 2011
Junior Member
Chris Delahunt wrote on Mon, 13 August 2012 10:52

Can you please show what you mean when you say parent points to C1/C2 and the stack trace for the exception? This seems like simple inheritance where P would have a OneToMany relationship to other P, and each P would have a ManyToOne back to P. Are you overriding this in the children classes somehow?

In the future it is also a good idea to upload code to bugs that can show how they are reproduced.


Please find the maven based test I have attached to the issue: https://bugs.eclipse.org/bugs/attachment.cgi?id=219861

(Please check the JavaDocs and source of the test to understand the constraints that happen and to find the simple answer to your above question Smile -- checking the few source lines is much easier to understand than trying to make clear what "parent" means in this context... Inheritance is a bit more complex that your assumption: "parent" is NOT defined in P and NOT overridden in the descendants. Instead, C1 and C2 have "their own" filed "parent" pointing either to X or C1)

When you run this test using "mvn test" you will see the following:

Local Exception Stack:
Exception [EclipseLink-32] (Eclipse Persistence Services - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Trying to set value [C1@7b751a9e] for instance variable [parent] of type [P] in the object. The specified object is not an instance of the class or interface declaring the underlying field, or an unwrapping conversion has failed.
Internal Exception: java.lang.IllegalArgumentException: Can not set P field C2.parent to C1
Mapping: org.eclipse.persistence.mappings.ManyToOneMapping[parent]
Descriptor: RelationalDescriptor(C2 --> [DatabaseTable(P), DatabaseTable(C2)])
at org.eclipse.persistence.exceptions.DescriptorException.illegalArgumentWhileSettingValueThruInstanceVariableAccessor(DescriptorException.java:700)
at org.eclipse.persistence.internal.descriptors.InstanceVariableAttributeAccessor.setAttributeValueInObject(InstanceVariableAttributeAccessor.java:188)
at org.eclipse.persistence.mappings.DatabaseMapping.setAttributeValueInObject(DatabaseMapping.java:1532)
at org.eclipse.persistence.mappings.ForeignReferenceMapping.readFromRowIntoObject(ForeignReferenceMapping.java:1371)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildAttributesIntoObject(ObjectBuilder.java:447)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.refreshObjectIfRequired(ObjectBuilder.java:3668)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:829)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:605)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObjectsInto(ObjectBuilder.java:1087)
at org.eclipse.persistence.queries.ReadAllQuery.executeObjectLevelReadQuery(ReadAllQuery.java:436)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeDatabaseQuery(ObjectLevelReadQuery.java:1149)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:852)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1108)
at org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:392)
at org.eclipse.persistence.internal.sessions.AbstractSession.internalExecuteQuery(AbstractSession.java:2946)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1602)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1584)
at org.eclipse.persistence.internal.indirection.QueryBasedValueHolder.instantiate(QueryBasedValueHolder.java:112)
at org.eclipse.persistence.internal.indirection.QueryBasedValueHolder.instantiate(QueryBasedValueHolder.java:99)
at org.eclipse.persistence.internal.indirection.DatabaseValueHolder.getValue(DatabaseValueHolder.java:88)
at org.eclipse.persistence.internal.indirection.UnitOfWorkValueHolder.instantiateImpl(UnitOfWorkValueHolder.java:161)
at org.eclipse.persistence.internal.indirection.UnitOfWorkValueHolder.instantiate(UnitOfWorkValueHolder.java:222)
at org.eclipse.persistence.internal.indirection.DatabaseValueHolder.getValue(DatabaseValueHolder.java:88)
at org.eclipse.persistence.indirection.IndirectList.buildDelegate(IndirectList.java:244)
at org.eclipse.persistence.indirection.IndirectList.getDelegate(IndirectList.java:415)
at org.eclipse.persistence.indirection.IndirectList.get(IndirectList.java:402)
at Bug386389ReproductionTest.shouldFailWhenRunAsPartOfAllStepsExecution(Bug386389ReproductionTest.java:155)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
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)
Caused by: java.lang.IllegalArgumentException: Can not set P field C2.parent to C1
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150)
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:37)
at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:57)
at java.lang.reflect.Field.set(Field.java:657)
at org.eclipse.persistence.internal.descriptors.InstanceVariableAttributeAccessor.setAttributeValueInObject(InstanceVariableAttributeAccessor.java:141)
... 52 more

Re: Can not set ManyToOne field to inherited entity [message #905034 is a reply to message #901769] Wed, 29 August 2012 11:23 Go to previous message
James Sutherland is currently offline James Sutherland
Messages: 1939
Registered: July 2009
Location: Ottawa, Canada
Senior Member

Your issue seems to be class loader related.
JUnit does some odd class loader things depending on how you run it, you seem to be encounter this, but sharing your emf from previous tests.
You need to set JUnit to run the tests with the same class loader, or not share anything between them.


James : Wiki : Book : Blog : Twitter
Previous Topic:JPA-RS hooks and/or HATEOAS?
Next Topic:Anyone using EclipseLink-EIS
Goto Forum:
  


Current Time: Tue Sep 02 13:11:32 EDT 2014

Powered by FUDForum. Page generated in 0.02484 seconds