Community
Participate
Working Groups
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)
Note: This issue does not occur with weaving enabled.
Created attachment 167735 [details] Proposed changes
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.
Incidentally, the workaround suggested does not work; I still (intermittently) get the first exception after inserting the flush() as recommended.
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink