Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 322679

Summary: Conflict between @IdClass and indirection
Product: z_Archived Reporter: Andrei Ilitchev <andrei.ilitchev>
Component: EclipselinkAssignee: Project Inbox <eclipselink.orm-inbox>
Status: CLOSED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: michael.f.obrien
Version: unspecified   
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   
Whiteboard:
Attachments:
Description Flags
Suggested patch none

Description Andrei Ilitchev CLA 2010-08-13 13:37:30 EDT
Happens when field name(s) are different in Entity and its IdClass and id is arelation that weaved for indirection.

To reproduce, in org.eclipse.persistence.testing.models.jpa.advanced.PartnerLink entity define both properties as lazy:

@Entity
@Table(name="MW")
@IdClass(org.eclipse.persistence.testing.models.jpa.advanced.PartnerLinkPK.class)
public class PartnerLink {
    private Man man;
    private Woman woman;

	public PartnerLink() {}
	@Id
    @OneToOne(cascade=PERSIST, fetch=LAZY)
	@JoinColumn(name="M")
	public Man getMan() { 
        return man; 
    }
    
    @Id
    @OneToOne(cascade=PERSIST, fetch=LAZY)
	@JoinColumn(name="W")
	public Woman getWoman() { 
        return woman; 
    }
...

Note that in the IdClass uses differently named fields:
public class PartnerLinkPK {
    private int manId;
    private Integer womanId;
...

Result: the persistence unit fails to deploy:
Errors:
TEST SUITE NAME: org.eclipse.persistence.testing.tests.jpa.advanced.EntityManagerJUnitTestSuite
TEST NAME: testSetup(org.eclipse.persistence.testing.tests.jpa.advanced.EntityManagerJUnitTestSuite)
##FAILURE##
RESULT:      FatalError (error)
javax.persistence.PersistenceException: Exception [EclipseLink-0] (Eclipse Persistence Services - @VERSION@.@QUALIFIER@): org.eclipse.persistence.exceptions.IntegrityException
Descriptor Exceptions: 
---------------------------------------------------------

Exception [EclipseLink-0] (Eclipse Persistence Services - @VERSION@.@QUALIFIER@): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: An internal error occurred accessing the primary key object [202].
Internal Exception: java.lang.NoSuchMethodException: org.eclipse.persistence.testing.models.jpa.advanced.PartnerLinkPK._persistence_get_woman_vh()
Descriptor: RelationalDescriptor(org.eclipse.persistence.testing.models.jpa.advanced.PartnerLink --> [DatabaseTable(MW)])

Runtime Exceptions: 
---------------------------------------------------------

java.lang.NullPointerException

	at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:408)
	at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.getServerSession(EntityManagerFactoryImpl.java:157)
	at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:214)
	at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:202)
	at org.eclipse.persistence.testing.framework.junit.JUnitTestCase.getServerSession(JUnitTestCase.java:373)
	at org.eclipse.persistence.testing.tests.jpa.advanced.EntityManagerJUnitTestSuite.testSetup(EntityManagerJUnitTestSuite.java:359)
	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 junit.framework.TestCase.runTest(TestCase.java:168)
	at junit.framework.TestCase.runBare(TestCase.java:134)
	at org.eclipse.persistence.testing.framework.junit.JUnitTestCase.runBare(JUnitTestCase.java:466)
	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 org.eclipse.persistence.testing.framework.TestExecutor.execute(TestExecutor.java:248)
	at org.eclipse.persistence.testing.framework.TestExecutor.runTest(TestExecutor.java:671)
	at org.eclipse.persistence.testing.framework.ui.SynchronizedTestExecutor.run(SynchronizedTestExecutor.java:61)
Caused by: Exception [EclipseLink-0] (Eclipse Persistence Services - @VERSION@.@QUALIFIER@): org.eclipse.persistence.exceptions.IntegrityException
Descriptor Exceptions: 
---------------------------------------------------------

Exception [EclipseLink-0] (Eclipse Persistence Services - @VERSION@.@QUALIFIER@): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: An internal error occurred accessing the primary key object [202].
Internal Exception: java.lang.NoSuchMethodException: org.eclipse.persistence.testing.models.jpa.advanced.PartnerLinkPK._persistence_get_woman_vh()
Descriptor: RelationalDescriptor(org.eclipse.persistence.testing.models.jpa.advanced.PartnerLink --> [DatabaseTable(MW)])

Runtime Exceptions: 
---------------------------------------------------------

java.lang.NullPointerException

	at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:471)
	at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:406)
	at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.postConnectDatasource(DatabaseSessionImpl.java:666)
	at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.login(DatabaseSessionImpl.java:628)
	at org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.login(EntityManagerFactoryProvider.java:230)
	at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:380)
	... 19 more
Comment 1 Andrei Ilitchev CLA 2010-08-13 13:53:02 EDT
Created attachment 176575 [details]
Suggested patch

Eclipselink needs to access the attribute of IdClass corresponding to entity's id attribute: it's required that either attribute names or property names must be the same.

First Eclipselink tries to invoke "woman" field on PartnerLinkPK - that doesn't work in this case. 
Next - in case of property access - it attempts to invoke "getWoman" property accessor on PartnerLinkPK. That should have worked, but LAZY fetch type was weaved into the entity and entity's accessor is no longer the original "getWoman" method, but the new Eclipselink-genarated "_persistence_getWoman_vh".

To fix the problem Eclipselink should keep somewhere the old method name and access here - so the patch adds this info to WeavedBasicIndirectionPolicy.

Changed the test class PartnerLink to use LAZY in both id attributes (to reproduce the problem), also altered getMsanId, getWomanId methods to be @Transient.
Comment 2 Andrei Ilitchev CLA 2010-08-13 15:17:36 EDT
The patch checked into trunk and 2.1.1
Reviewed by Chris.
Comment 3 Michael OBrien CLA 2010-08-23 17:31:53 EDT
>Note: the secondary NPE on missing _vh_ weaved functions is changed to a DescriptorException with suggestions in bug # 323403
Comment 4 Eclipse Webmaster CLA 2022-06-09 10:10:02 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink