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

Bug 312253

Summary: No-Weaving: Using an Entity mapped as a subclass as @MapKey exceptions thrown on flush when persisting a new Map Element
Product: z_Archived Reporter: Tom Ware <tom.ware>
Component: EclipselinkAssignee: Tom Ware <tom.ware>
Status: CLOSED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: eclipselink.foundation-inbox, ljnelson
Version: unspecified   
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   
Whiteboard:
Attachments:
Description Flags
Proposed changes none

Description Tom Ware CLA 2010-05-10 09:30:04 EDT
If you use @MapKey to define a Map key relationship and use an Entity with an Entity superclass as the key of the map, there is some non determinism in the UOW change set calculation that can cause one of the following exceptions:

1. javax.persistence.RollbackException: Exception [EclipseLink-6150] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.ValidationException
Exception Description: A null value can not be used as a key in a container of type [class org.eclipse.persistence.indirection.IndirectMap]. Ensure your key values for the objects of type [class <class>] can not be null.

2. javax.persistence.PersistenceException: Exception [EclipseLink-34] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: This class does not define a public default constructor, or the constructor raised an exception.
Internal Exception: java.lang.InstantiationException
Descriptor: RelationalDescriptor(<class>--> [DatabaseTable(<table>)])

Example Object Model:

- Name is an Entity
- AtomicName is a subclass of Name that is also an Entity
- Name has a 1-1 relationship to Type
- Person has a Map of Name and uses Type as the @MapKey

Do the following:

- Create, persist and Flush a person
- Create an AtomicName, add it to the person's map of name and flush

Behavior will either be success or one of the exceptions above

To work around, flush between creating the AtomicName and associating it with the Person

The reason for this issue is there is some non determinism in UOW change set calculations as it iterates through the Set of changed objects.  Depending on the order that change sets are calculated one of the 3 possible results can occur.

The ValidationException occurs because MapContainerPolicy is not rewrapping the Map.Entry as a Map.Entry in CollectionMapping.mergeINto object when containerPolicy.createWrappedObjectFromExistingWrappedObject is called.

The DescriptorException occurs because the target descriptor for the relationship mapping is used for the ChangeSet for AtomicName instead of the descriptor for AtomicName itself (i.e. we get the superclass descriptor instead of the subclass descriptor)
Comment 1 Tom Ware CLA 2010-05-10 11:11:29 EDT
Note: This issue does not occur with weaving enabled.
Comment 2 Tom Ware CLA 2010-05-10 11:48:09 EDT
Created attachment 167735 [details]
Proposed changes
Comment 3 Tom Ware CLA 2010-05-10 15:56:45 EDT
Fixed in the trunk stream.

Reviewed by Chris Delahunt

The fix does two things:

1. When looking for the descriptor to create a change set for a Map, look for the descriptor of the actual target value instead of the reference descriptor for the mapping

2. Ensure that the values we merge are wrapped as Map.Entries when building that change set.

Added a test to InheritenceTestModel.  That test creates a situation where the issue will be recreated when weaving is disabled and hence will only recrate the problem when these tests are run without weaving.  Since this issue is non-deterministic, this test will act differently depending on the path that gets followed.  It does, however, recreate the above situation when weaving is disabled.
Comment 4 Laird Nelson CLA 2010-05-11 15:04:05 EDT
Incidentally, the workaround suggested does not work; I still (intermittently) get the first exception after inserting the flush() as recommended.
Comment 5 Eclipse Webmaster CLA 2022-06-09 10:05:05 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink