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

Bug 352533

Summary: Relationship between Cacheable and Non-cacheable entity not properly retrieved from shared cache
Product: z_Archived Reporter: Markus KARG <karg>
Component: EclipselinkAssignee: Nobody - feel free to take it <nobody>
Status: CLOSED FIXED QA Contact:
Severity: critical    
Priority: P3 CC: eclipselink.orm-inbox, mitesh.meswani, muriloq, tom.ware
Version: unspecified   
Target Milestone: ---   
Hardware: PC   
OS: Windows 7   
Whiteboard:
Attachments:
Description Flags
Complete Eclipse project demonstrating the bug
none
proposed fix none

Description Markus KARG CLA 2011-07-20 02:56:42 EDT
Build Identifier: GFv3.1.1_b11

An entity created via entity manager A having a non-NULL ManyToOne reference contains NULL in that same reference after find() by entity manager B under certain circumstances unless @Cacheable(false) is used. The following code produces this problem (this creates a row in AmountManufactured correctly pointing to a row in Part, but the second EntityManager find()s an AmountManufactured having NULL in the reference to Part):

EntityManagerFactory emf = Persistence.createEntityManagerFactory("test");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
Part part = em.find(Part.class, new PartPrimaryKey(PART_ID, PART_VERSION));
if (part != null) {
  final ManufacturedAmount manufacturedAmountToSaved = new ManufacturedAmount(part, YEAR);
  em.persist(manufacturedAmountToSaved);
  System.out.println("\nAmount saved.\n");
} else {
  System.out.println("\nPart not found.\n");
  tx.rollback();
  return;
}

tx.commit();
em.close();
em = emf.createEntityManager();
tx = em.getTransaction();
tx.begin();
final ManufacturedAmount amount = em.find(ManufacturedAmount.class, new ManufacturedAmountPk(PART_ID, PART_VERSION, YEAR));
if (amount == null)
  System.out.println("\nAmount = NULL.\n");
else
  System.out.println(String.format("\n Part = %s\n", amount.getPart() == null ? "NULL" : part.toString()));
tx.commit();

This is a showstopper for GlassFish 3.1.1_b11 as it prevents failure-free EARs from running correctly without getting modified (here: without switching off the cache). As such, it should get fixed ASAP.

Reproducible: Always

Steps to Reproduce:
Execute attached code.
Comment 1 Markus KARG CLA 2011-07-20 03:03:19 EDT
The attached software will create the following output which proofs that the created AmountManufactured contains a non-NULL reference to Part, but after find() it registers an instance where that reference IS NULL: "Register the existing object entities.ManufacturedAmount@11e9c82e(pk=(part='null, 'year='1900'))". When using @Cacheable(false) at AmountManufactured this does not happen, as it does not register an existing (obviously broken) instance then but loads all data (incl. reference to Part) from the database. So it seems the problem is that multiply mapped fields do not get updated correctly in the cache.

[EL Finest]: 2011-07-20 08:58:55.773--ServerSession(449348672)--Thread(Thread[main,5,main])--Begin predeploying Persistence Unit test; session file:/C:/Users/Karg/workspace/EclipseLinkCacheBug/_test; state Initial; factoryCount 0
[EL Finest]: 2011-07-20 08:58:55.789--ServerSession(449348672)--Thread(Thread[main,5,main])--property=eclipselink.orm.throw.exceptions; default value=true
[EL Finest]: 2011-07-20 08:58:55.789--ServerSession(449348672)--Thread(Thread[main,5,main])--property=eclipselink.multitenant.tenants-share-cache; default value=false
[EL Finest]: 2011-07-20 08:58:55.805--ServerSession(449348672)--Thread(Thread[main,5,main])--property=eclipselink.metadata-source; default value=null
[EL Finest]: 2011-07-20 08:58:55.805--ServerSession(449348672)--Thread(Thread[main,5,main])--property=eclipselink.jpa.uppercase-column-names; default value=false
[EL Finer]: 2011-07-20 08:58:55.805--ServerSession(449348672)--Thread(Thread[main,5,main])--Searching for default mapping file in file:/C:/Users/Karg/workspace/EclipseLinkCacheBug/
[EL Finer]: 2011-07-20 08:58:55.805--ServerSession(449348672)--Thread(Thread[main,5,main])--Searching for default mapping file in file:/C:/Users/Karg/workspace/EclipseLinkCacheBug/
[EL Config]: 2011-07-20 08:58:55.898--ServerSession(449348672)--Thread(Thread[main,5,main])--The access type for the persistent class [class entities.Part] is set to [FIELD].
[EL Config]: 2011-07-20 08:58:55.929--ServerSession(449348672)--Thread(Thread[main,5,main])--The access type for the persistent class [class entities.ManufacturedAmount] is set to [FIELD].
[EL Config]: 2011-07-20 08:58:55.945--ServerSession(449348672)--Thread(Thread[main,5,main])--The target entity (reference) class for the many to one mapping element [field part] is being defaulted to: class entities.Part.
[EL Config]: 2011-07-20 08:58:55.945--ServerSession(449348672)--Thread(Thread[main,5,main])--The access type for the persistent class [class entities.PartPrimaryKey] is set to [FIELD].
[EL Config]: 2011-07-20 08:58:55.945--ServerSession(449348672)--Thread(Thread[main,5,main])--The access type for the persistent class [class entities.ManufacturedAmountPk] is set to [FIELD].
[EL Config]: 2011-07-20 08:58:55.945--ServerSession(449348672)--Thread(Thread[main,5,main])--The alias name for the entity class [class entities.Part] is being defaulted to: Part.
[EL Config]: 2011-07-20 08:58:55.976--ServerSession(449348672)--Thread(Thread[main,5,main])--The alias name for the entity class [class entities.ManufacturedAmount] is being defaulted to: ManufacturedAmount.
[EL Config]: 2011-07-20 08:58:55.976--ServerSession(449348672)--Thread(Thread[main,5,main])--The table name for entity [class entities.ManufacturedAmount] is being defaulted to: MANUFACTUREDAMOUNT.
[EL Config]: 2011-07-20 08:58:55.976--ServerSession(449348672)--Thread(Thread[main,5,main])--The column name for element [amountOctober] is being defaulted to: AMOUNTOCTOBER.
[EL Config]: 2011-07-20 08:58:55.976--ServerSession(449348672)--Thread(Thread[main,5,main])--The column name for element [amountNovember] is being defaulted to: AMOUNTNOVEMBER.
[EL Config]: 2011-07-20 08:58:55.976--ServerSession(449348672)--Thread(Thread[main,5,main])--The column name for element [amountFebruary] is being defaulted to: AMOUNTFEBRUARY.
[EL Config]: 2011-07-20 08:58:55.976--ServerSession(449348672)--Thread(Thread[main,5,main])--The column name for element [amountDecember] is being defaulted to: AMOUNTDECEMBER.
[EL Config]: 2011-07-20 08:58:55.976--ServerSession(449348672)--Thread(Thread[main,5,main])--The column name for element [version] is being defaulted to: VERSION.
[EL Config]: 2011-07-20 08:58:55.976--ServerSession(449348672)--Thread(Thread[main,5,main])--The column name for element [amountJanuary] is being defaulted to: AMOUNTJANUARY.
[EL Config]: 2011-07-20 08:58:55.976--ServerSession(449348672)--Thread(Thread[main,5,main])--The column name for element [amountMay] is being defaulted to: AMOUNTMAY.
[EL Config]: 2011-07-20 08:58:55.976--ServerSession(449348672)--Thread(Thread[main,5,main])--The column name for element [amountJune] is being defaulted to: AMOUNTJUNE.
[EL Config]: 2011-07-20 08:58:55.976--ServerSession(449348672)--Thread(Thread[main,5,main])--The column name for element [amountSeptember] is being defaulted to: AMOUNTSEPTEMBER.
[EL Config]: 2011-07-20 08:58:55.976--ServerSession(449348672)--Thread(Thread[main,5,main])--The column name for element [amountApril] is being defaulted to: AMOUNTAPRIL.
[EL Config]: 2011-07-20 08:58:55.976--ServerSession(449348672)--Thread(Thread[main,5,main])--The column name for element [amountAugust] is being defaulted to: AMOUNTAUGUST.
[EL Config]: 2011-07-20 08:58:55.976--ServerSession(449348672)--Thread(Thread[main,5,main])--The column name for element [amountMarch] is being defaulted to: AMOUNTMARCH.
[EL Config]: 2011-07-20 08:58:55.976--ServerSession(449348672)--Thread(Thread[main,5,main])--The column name for element [amountJuly] is being defaulted to: AMOUNTJULY.
[EL Config]: 2011-07-20 08:58:55.976--ServerSession(449348672)--Thread(Thread[main,5,main])--The column name for element [year] is being defaulted to: YEAR.
[EL Finest]: 2011-07-20 08:58:55.992--ServerSession(449348672)--Thread(Thread[main,5,main])--End predeploying Persistence Unit test; session file:/C:/Users/Karg/workspace/EclipseLinkCacheBug/_test; state Predeployed; factoryCount 0
[EL Finer]: 2011-07-20 08:58:55.992--Thread(Thread[main,5,main])--JavaSECMPInitializer - transformer is null.
[EL Finest]: 2011-07-20 08:58:55.992--ServerSession(449348672)--Thread(Thread[main,5,main])--Begin predeploying Persistence Unit test; session file:/C:/Users/Karg/workspace/EclipseLinkCacheBug/_test; state Predeployed; factoryCount 0
[EL Finest]: 2011-07-20 08:58:55.992--ServerSession(449348672)--Thread(Thread[main,5,main])--End predeploying Persistence Unit test; session file:/C:/Users/Karg/workspace/EclipseLinkCacheBug/_test; state Predeployed; factoryCount 1
[EL Finest]: 2011-07-20 08:58:55.992--ServerSession(449348672)--Thread(Thread[main,5,main])--Begin deploying Persistence Unit test; session file:/C:/Users/Karg/workspace/EclipseLinkCacheBug/_test; state Predeployed; factoryCount 1
[EL Finer]: 2011-07-20 08:58:56.007--ServerSession(449348672)--Thread(Thread[main,5,main])--Could not initialize Validation Factory. Encountered following exception: java.lang.NoClassDefFoundError: javax/validation/Validation
[EL Finest]: 2011-07-20 08:58:56.007--ServerSession(449348672)--Thread(Thread[main,5,main])--property=eclipselink.logging.level; value=ALL; translated value=ALL
[EL Finest]: 2011-07-20 08:58:56.007--ServerSession(449348672)--Thread(Thread[main,5,main])--property=eclipselink.logging.level; value=ALL; translated value=ALL
[EL Finest]: 2011-07-20 08:58:56.007--ServerSession(449348672)--Thread(Thread[main,5,main])--property=javax.persistence.jdbc.driver; value=ianywhere.ml.jdbcodbc.jdbc3.IDriver
[EL Finest]: 2011-07-20 08:58:56.007--ServerSession(449348672)--Thread(Thread[main,5,main])--property=javax.persistence.jdbc.url; value=jdbc:ianywhere:dsn=QUIPSY 4 DBFile
[EL Info]: 2011-07-20 08:58:56.007--ServerSession(449348672)--Thread(Thread[main,5,main])--EclipseLink, version: Eclipse Persistence Services - 2.3.0.v20110604-r9504
[EL Finest]: 2011-07-20 08:58:56.054--Thread(Thread[main,5,main])--DBPlatform: org.eclipse.persistence.platform.database.HSQLPlatform, RegularExpression: (?i)hsql.*.
[EL Finest]: 2011-07-20 08:58:56.054--Thread(Thread[main,5,main])--DBPlatform: org.eclipse.persistence.platform.database.InformixPlatform, RegularExpression: (?i)informix.*.
[EL Finest]: 2011-07-20 08:58:56.054--Thread(Thread[main,5,main])--DBPlatform: org.eclipse.persistence.platform.database.PointBasePlatform, RegularExpression: (?i)pointbase.*.
[EL Finest]: 2011-07-20 08:58:56.054--Thread(Thread[main,5,main])--DBPlatform: org.eclipse.persistence.platform.database.DB2Platform, RegularExpression: (?i).*db2.*.
[EL Finest]: 2011-07-20 08:58:56.054--Thread(Thread[main,5,main])--DBPlatform: org.eclipse.persistence.platform.database.SQLServerPlatform, RegularExpression: (?i)microsoft.*.
[EL Finest]: 2011-07-20 08:58:56.054--Thread(Thread[main,5,main])--DBPlatform: org.eclipse.persistence.platform.database.PostgreSQLPlatform, RegularExpression: (?i)postgresql.*.
[EL Finest]: 2011-07-20 08:58:56.054--Thread(Thread[main,5,main])--DBPlatform: org.eclipse.persistence.platform.database.MaxDBPlatform, RegularExpression: SAP DB.
[EL Finest]: 2011-07-20 08:58:56.054--Thread(Thread[main,5,main])--DBPlatform: org.eclipse.persistence.platform.database.H2Platform, RegularExpression: (?i)h2.*.
[EL Finest]: 2011-07-20 08:58:56.054--Thread(Thread[main,5,main])--DBPlatform: org.eclipse.persistence.platform.database.SybasePlatform, RegularExpression: (?i)(sybase.*)|(adaptive server enterprise.*)|(SQL Server).
[EL Finest]: 2011-07-20 08:58:56.07--Thread(Thread[main,5,main])--DBPlatform: org.eclipse.persistence.platform.database.FirebirdPlatform, RegularExpression: (?i)firebird.*.
[EL Finest]: 2011-07-20 08:58:56.07--Thread(Thread[main,5,main])--DBPlatform: org.eclipse.persistence.platform.database.JavaDBPlatform, RegularExpression: (?i).*derby.
[EL Finest]: 2011-07-20 08:58:56.07--Thread(Thread[main,5,main])--DBPlatform: org.eclipse.persistence.platform.database.AccessPlatform, RegularExpression: (?i)access.*.
[EL Finest]: 2011-07-20 08:58:56.07--Thread(Thread[main,5,main])--DBPlatform: org.eclipse.persistence.platform.database.SymfowarePlatform, RegularExpression: (?i).*symfoware.*.
[EL Finest]: 2011-07-20 08:58:56.07--Thread(Thread[main,5,main])--DBPlatform: org.eclipse.persistence.platform.database.oracle.Oracle10Platform, RegularExpression: (?i)oracle.*.
[EL Finest]: 2011-07-20 08:58:56.07--Thread(Thread[main,5,main])--DBPlatform: org.eclipse.persistence.platform.database.MySQLPlatform, RegularExpression: (?i)mysql.*.
[EL Finest]: 2011-07-20 08:58:56.07--Thread(Thread[main,5,main])--DBPlatform: org.eclipse.persistence.platform.database.SQLAnywherePlatform, RegularExpression: SQL Anywhere.
[EL Fine]: 2011-07-20 08:58:56.07--Thread(Thread[main,5,main])--Detected Vendor platform: org.eclipse.persistence.platform.database.SQLAnywherePlatform
[EL Config]: 2011-07-20 08:58:56.085--ServerSession(449348672)--Connection(1872474714)--Thread(Thread[main,5,main])--connecting(DatabaseLogin(
	platform=>SQLAnywherePlatform
	user name=> ""
	datasource URL=> "jdbc:ianywhere:dsn=QUIPSY 4 DBFile"
))
[EL Config]: 2011-07-20 08:58:56.101--ServerSession(449348672)--Connection(1457155060)--Thread(Thread[main,5,main])--Connected: jdbc:ianywhere:dsn=QUIPSY 4 DBFile
	User: QADMIN
	Database: SQL Anywhere  Version: 11.0.1.2550
	Driver: DBODBC11.DLL  Version: 11.00.0001
[EL Finest]: 2011-07-20 08:58:56.101--ServerSession(449348672)--Connection(1457155060)--Thread(Thread[main,5,main])--Connection acquired from connection pool [default].
[EL Finest]: 2011-07-20 08:58:56.101--ServerSession(449348672)--Connection(1457155060)--Thread(Thread[main,5,main])--Connection released to connection pool [default].
[EL Info]: 2011-07-20 08:58:56.304--ServerSession(449348672)--Thread(Thread[main,5,main])--file:/C:/Users/Karg/workspace/EclipseLinkCacheBug/_test login successful
[EL Finer]: 2011-07-20 08:58:56.319--ServerSession(449348672)--Thread(Thread[main,5,main])--Canonical Metamodel class [entities.ManufacturedAmount_] not found during initialization.
[EL Finer]: 2011-07-20 08:58:56.319--ServerSession(449348672)--Thread(Thread[main,5,main])--Canonical Metamodel class [entities.ManufacturedAmountPk_] not found during initialization.
[EL Finer]: 2011-07-20 08:58:56.319--ServerSession(449348672)--Thread(Thread[main,5,main])--Canonical Metamodel class [entities.Part_] not found during initialization.
[EL Finer]: 2011-07-20 08:58:56.319--ServerSession(449348672)--Thread(Thread[main,5,main])--Canonical Metamodel class [entities.PartPrimaryKey_] not found during initialization.
[EL Finest]: 2011-07-20 08:58:56.319--ServerSession(449348672)--Thread(Thread[main,5,main])--End deploying Persistence Unit test; session file:/C:/Users/Karg/workspace/EclipseLinkCacheBug/_test; state Deployed; factoryCount 1
[EL Finer]: 2011-07-20 08:58:56.335--ServerSession(449348672)--Thread(Thread[main,5,main])--client acquired: 2061720503
[EL Finer]: 2011-07-20 08:58:56.335--ClientSession(2061720503)--Thread(Thread[main,5,main])--acquire unit of work: 1903483194
[EL Finest]: 2011-07-20 08:58:56.351--UnitOfWork(1903483194)--Thread(Thread[main,5,main])--Execute query ReadObjectQuery(name="readObject" referenceClass=Part sql="SELECT angelegt_am, bezeichnung, gesperrt, zeichnungsindex, zeichnungsnr, infofeld_1, infofeld_10, infofeld_2, infofeld_3, infofeld_4, infofeld_5, infofeld_6, infofeld_7, infofeld_8, infofeld_9, werkstoff, geaendert_am, notiz, bilddokument, id_bild, stueckgut, id_produktionseinheit, ist_bemustert, wert_pro_stueck, ID_TEIL, ID_TEILEVERSION FROM t_tl WHERE ((ID_TEIL = ?) AND (ID_TEILEVERSION = ?))")
[EL Finest]: 2011-07-20 08:58:56.351--ServerSession(449348672)--Connection(1457155060)--Thread(Thread[main,5,main])--Connection acquired from connection pool [default].
[EL Fine]: 2011-07-20 08:58:56.351--ServerSession(449348672)--Connection(1457155060)--Thread(Thread[main,5,main])--SELECT angelegt_am, bezeichnung, gesperrt, zeichnungsindex, zeichnungsnr, infofeld_1, infofeld_10, infofeld_2, infofeld_3, infofeld_4, infofeld_5, infofeld_6, infofeld_7, infofeld_8, infofeld_9, werkstoff, geaendert_am, notiz, bilddokument, id_bild, stueckgut, id_produktionseinheit, ist_bemustert, wert_pro_stueck, ID_TEIL, ID_TEILEVERSION FROM t_tl WHERE ((ID_TEIL = ?) AND (ID_TEILEVERSION = ?))
	bind => [D-0077, 1]
[EL Finest]: 2011-07-20 08:58:56.366--ServerSession(449348672)--Connection(1457155060)--Thread(Thread[main,5,main])--Connection released to connection pool [default].
[EL Finest]: 2011-07-20 08:58:56.366--UnitOfWork(1903483194)--Thread(Thread[main,5,main])--persist() operation called on: entities.ManufacturedAmount@112c3327(pk=(part='entities.Part@53ce669e(pk=entities.PartPrimaryKey@38ef39be(id='D-0077', version='1')), 'year='1900')).

Amount saved.

[EL Finer]: 2011-07-20 08:58:56.366--UnitOfWork(1903483194)--Thread(Thread[main,5,main])--begin unit of work commit
[EL Finest]: 2011-07-20 08:58:56.366--UnitOfWork(1903483194)--Thread(Thread[main,5,main])--Execute query InsertObjectQuery(entities.ManufacturedAmount@112c3327(pk=(part='entities.Part@53ce669e(pk=entities.PartPrimaryKey@38ef39be(id='D-0077', version='1')), 'year='1900')))
[EL Finest]: 2011-07-20 08:58:56.366--ServerSession(449348672)--Connection(1457155060)--Thread(Thread[main,5,main])--Connection acquired from connection pool [default].
[EL Finer]: 2011-07-20 08:58:56.366--ClientSession(2061720503)--Connection(1457155060)--Thread(Thread[main,5,main])--begin transaction
[EL Fine]: 2011-07-20 08:58:56.366--ClientSession(2061720503)--Connection(1457155060)--Thread(Thread[main,5,main])--INSERT INTO MANUFACTUREDAMOUNT (AMOUNTAPRIL, AMOUNTAUGUST, AMOUNTDECEMBER, AMOUNTFEBRUARY, AMOUNTJANUARY, AMOUNTJULY, AMOUNTJUNE, AMOUNTMARCH, AMOUNTMAY, AMOUNTNOVEMBER, AMOUNTOCTOBER, AMOUNTSEPTEMBER, VERSION, YEAR, partId, partVersion) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
	bind => [null, null, null, null, null, null, null, null, null, null, null, null, 1, 1900, D-0077, 1]
[EL Finer]: 2011-07-20 08:58:56.397--ClientSession(2061720503)--Connection(1457155060)--Thread(Thread[main,5,main])--commit transaction
[EL Finest]: 2011-07-20 08:58:56.397--ServerSession(449348672)--Connection(1457155060)--Thread(Thread[main,5,main])--Connection released to connection pool [default].
[EL Finer]: 2011-07-20 08:58:56.429--UnitOfWork(1903483194)--Thread(Thread[main,5,main])--end unit of work commit
[EL Finer]: 2011-07-20 08:58:56.429--UnitOfWork(1903483194)--Thread(Thread[main,5,main])--resume unit of work
[EL Finer]: 2011-07-20 08:58:56.429--UnitOfWork(1903483194)--Thread(Thread[main,5,main])--release unit of work
[EL Finer]: 2011-07-20 08:58:56.429--ClientSession(2061720503)--Thread(Thread[main,5,main])--client released
[EL Finer]: 2011-07-20 08:58:56.429--ServerSession(449348672)--Thread(Thread[main,5,main])--client acquired: 130672250
[EL Finer]: 2011-07-20 08:58:56.429--ClientSession(130672250)--Thread(Thread[main,5,main])--acquire unit of work: 1480218516
[EL Finest]: 2011-07-20 08:58:56.429--UnitOfWork(1480218516)--Thread(Thread[main,5,main])--Execute query ReadObjectQuery(name="readObject" referenceClass=ManufacturedAmount sql="SELECT AMOUNTAPRIL, AMOUNTAUGUST, AMOUNTDECEMBER, AMOUNTFEBRUARY, AMOUNTJANUARY, AMOUNTJULY, AMOUNTJUNE, AMOUNTMARCH, AMOUNTMAY, AMOUNTNOVEMBER, AMOUNTOCTOBER, AMOUNTSEPTEMBER, VERSION, YEAR, partId, partVersion FROM MANUFACTUREDAMOUNT WHERE (((YEAR = ?) AND (partId = ?)) AND (partVersion = ?))")
[EL Finest]: 2011-07-20 08:58:56.429--UnitOfWork(1480218516)--Thread(Thread[main,5,main])--Register the existing object entities.ManufacturedAmount@11e9c82e(pk=(part='null, 'year='1900'))

 Part = NULL

[EL Finer]: 2011-07-20 08:58:56.444--UnitOfWork(1480218516)--Thread(Thread[main,5,main])--begin unit of work commit
[EL Warning]: 2011-07-20 08:58:56.46--UnitOfWork(1480218516)--Thread(Thread[main,5,main])--Local Exception Stack: 
Exception [EclipseLink-7197] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Null or zero primary key encountered in unit of work clone [entities.ManufacturedAmount@d3f136e(pk=(part='null, 'year='1900'))], primary key [[[1900, null, null]: 1900]]. Set descriptors IdValidation or the "eclipselink.id-validation" property.
	at org.eclipse.persistence.exceptions.ValidationException.nullPrimaryKeyInUnitOfWorkClone(ValidationException.java:1427)
	at org.eclipse.persistence.descriptors.changetracking.DeferredChangeDetectionPolicy.calculateChanges(DeferredChangeDetectionPolicy.java:107)
	at org.eclipse.persistence.descriptors.changetracking.DeferredChangeDetectionPolicy.calculateChangesForExistingObject(DeferredChangeDetectionPolicy.java:54)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.calculateChanges(UnitOfWorkImpl.java:636)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1482)
	at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:265)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1135)
	at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:84)
	at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:63)
	at Test.main(Test.java:51)

[EL Finer]: 2011-07-20 08:58:56.46--UnitOfWork(1480218516)--Thread(Thread[main,5,main])--release unit of work
[EL Finer]: 2011-07-20 08:58:56.46--ClientSession(130672250)--Thread(Thread[main,5,main])--client released
Exception in thread "main" javax.persistence.RollbackException: Exception [EclipseLink-7197] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Null or zero primary key encountered in unit of work clone [entities.ManufacturedAmount@d3f136e(pk=(part='null, 'year='1900'))], primary key [[[1900, null, null]: 1900]]. Set descriptors IdValidation or the "eclipselink.id-validation" property.
	at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:102)
	at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:63)
	at Test.main(Test.java:51)
Caused by: Exception [EclipseLink-7197] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Null or zero primary key encountered in unit of work clone [entities.ManufacturedAmount@d3f136e(pk=(part='null, 'year='1900'))], primary key [[[1900, null, null]: 1900]]. Set descriptors IdValidation or the "eclipselink.id-validation" property.
	at org.eclipse.persistence.exceptions.ValidationException.nullPrimaryKeyInUnitOfWorkClone(ValidationException.java:1427)
	at org.eclipse.persistence.descriptors.changetracking.DeferredChangeDetectionPolicy.calculateChanges(DeferredChangeDetectionPolicy.java:107)
	at org.eclipse.persistence.descriptors.changetracking.DeferredChangeDetectionPolicy.calculateChangesForExistingObject(DeferredChangeDetectionPolicy.java:54)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.calculateChanges(UnitOfWorkImpl.java:636)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1482)
	at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:265)
	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1135)
	at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:84)
	... 2 more
Comment 2 Markus KARG CLA 2011-07-20 03:08:04 EDT
Created attachment 199953 [details]
Complete Eclipse project demonstrating the bug

This ZIP file contains a complete Eclipse project demonstrating the bug. It contains all source code including the used entities and persistence.xml files.
Comment 3 Markus KARG CLA 2011-07-20 03:09:51 EDT
This bug is a showstopper for GlassFish v3.1.1_b11 as http://java.net/jira/browse/GLASSFISH-17036 bug is dependent of this problem.
Comment 4 Tom Ware CLA 2011-07-21 08:58:39 EDT
When you say "failure-free EARs" what does that mean?
Comment 5 Tom Ware CLA 2011-07-21 09:31:23 EDT
I am trying to triage this issue, but cannot run the recreation because I do not have data in my local database.

I also do not have an IAnywhere JDBC driver (in case the data in the initial test case is publicly available)
Comment 6 Markus KARG CLA 2011-07-21 10:21:57 EDT
(In reply to comment #4)
> When you say "failure-free EARs" what does that mean?

I mean that EclipseLink does not complaint about bugs in this persistence unit configuration at deployment or runtime (as it would do e. g. when there are typos in column names etc.).
Comment 7 Markus KARG CLA 2011-07-21 10:25:40 EDT
(In reply to comment #5)
> I am trying to triage this issue, but cannot run the recreation because I do
> not have data in my local database.
> 
> I also do not have an IAnywhere JDBC driver (in case the data in the initial
> test case is publicly available)

The only thing you need is one row in the Part table that has the primary key of id_teil="D-0077" and id_teileversion="1". No other existing data is needed.

IAnywhere is not needed as this is not specific to that particular database (I assume), so you can just replace driver and url entries in persistence.xml to run it with any other database. In case it will work (and you assume that it is IAnywhere related) I can send you a download link for an unlimited free developer's licence of that and provide a ready-to-use database including the above data.
Comment 8 Tom Ware CLA 2011-07-21 13:22:07 EDT
To elaborate on the workarounds.  There are 2.

1. Make both entities cacheable
2. Make both entities non-cacheable
Comment 9 Tom Ware CLA 2011-07-21 13:57:56 EDT
Setting initial target to 2.3.1 - although I do not agree this is a showstopper, we should do our best to address this by 2.3.1.

The recreation needs code similar to the following close the the beginning of the main method to populate the data

        EntityManager em = emf.createEntityManager();

        EntityTransaction tx = em.getTransaction();
        tx.begin();
        Part part1 = new Part();
        PartPrimaryKey pk = new PartPrimaryKey();
        pk.setId("D-0077");
        pk.setVersion("1");
        part1.setPrimaryKey(pk);
        em.persist(part1);
        tx.commit();
        em.clear();
        JpaHelper.getServerSession(emf).getIdentityMapAccessor().initializeAllIdentityMaps();

The issue occur because of the relationship between cacheable and non-cacheable entities.

The code in question is the combination of this code in UnitOfWork.registerExistingObject

                if (registeredObject == null) {
                    // This is a case where the object is not in the session cache,
                    // so a new cache-key is used as there is no original to use for locking.
                    // It read time must be set to avoid it being invalidated.
                    CacheKey cacheKey = new CacheKey(primaryKey);
                    cacheKey.setReadTime(System.currentTimeMillis());
                    cacheKey.setIsolated(true); // if the cache does not have a version then this must be built from the supplied version
                    registeredObject = cloneAndRegisterObject(objectToRegister, cacheKey, descriptor);
                }

And this code in ForeirnReferenceMapping.buildClone

        if (!this.isCacheable && (cacheKey != null && !cacheKey.isIsolated())){
            ReadObjectQuery query = new ReadObjectQuery(descriptor.getJavaClass());
            query.setSession(cloningSession);
            attributeValue = valueFromRow(cacheKey.getProtectedForeignKeys(), null, query, cacheKey, cloningSession, true, null);
        }

Notice, the cache key we build is set to isolated and the condition on the if statement prevents us from using protecteForeignKeys if the cache key is isolated
Comment 10 Markus KARG CLA 2011-07-22 02:44:10 EDT
(In reply to comment #8)
> To elaborate on the workarounds.  There are 2.
> 
> 1. Make both entities cacheable
> 2. Make both entities non-cacheable

Tom, thanks for this, but we already know that. The problem is that this is not an acceptable workaround as it enforces a change of the EAR. But see, the vendor of the EAR is an ISV so he (= we) will not switch off a WORA EAR just to run correct in GlassFish, while the same source change is not needed to run in any other application server (here: other JPA prodivers). The only accepted solution is to fix it, and the only accepted workaround is one that does not break WORA of the packaged EAR product (i. e. for example, changing some options at the GlassFish administration console at deployment or later).
Comment 11 Markus KARG CLA 2011-07-22 02:46:30 EDT
(In reply to comment #9)
> Setting initial target to 2.3.1 - although I do not agree this is a
> showstopper, we should do our best to address this by 2.3.1.

As I explained above, as an ISV we must not change our packaged product (= EAR) just to allow some of our customers to run it on GlassFish (= EclipseLink), while it works unchanged in other servers. This breaks WORA and such is not acceptable.
Comment 12 Markus KARG CLA 2011-07-25 05:13:25 EDT
Any solutions available which will not enforce source code changes and such break the WORA principle?
Comment 13 Tom Ware CLA 2011-08-11 11:49:21 EDT
Another workaround: Avoid the find call, do the following instead:

        final ManufacturedAmount amount = (ManufacturedAmount)em.createQuery("select m from ManufacturedAmount m where m.pk.year = :year and m.pk.partId = :id and m.pk.partVersion = :version").setParameter("year", YEAR).setParameter("id", part.getId()).setParameter("version", part.getVersion()).getResultList().get(0);
Comment 14 Tom Ware CLA 2011-08-11 15:52:04 EDT
Created attachment 201350 [details]
proposed fix
Comment 15 Tom Ware CLA 2011-08-12 09:28:01 EDT
Fix checked in to trunk and 2.3.1

The fix makes use of the primary key that is available in a finder to do a cache lookup while we are registering the object.  This allows cloning to occur when we know about the protected relationship.

Reviewed by Gordon Yorke

Test added to our Cacheable model

Tested with JPA and Core LRG
Comment 16 Eclipse Webmaster CLA 2022-06-09 10:24:20 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink