Bug 413206 - NullPointerException downstream of DirectMapMapping for New Objects
Summary: NullPointerException downstream of DirectMapMapping for New Objects
Status: NEW
Alias: None
Product: z_Archived
Classification: Eclipse Foundation
Component: Eclipselink (show other bugs)
Version: unspecified   Edit
Hardware: All All
: P2 blocker (vote)
Target Milestone: ---   Edit
Assignee: Nobody - feel free to take it CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-07-17 17:52 EDT by Steve Neely CLA
Modified: 2022-06-09 10:18 EDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Steve Neely CLA 2013-07-17 17:52:19 EDT
In v2.4.2 of EclipseLink the class org.eclipse.persistence.mappings.DirectMapMapping was refactored. It looks like an if-guard was missed in the refactoring.

Looking at method compareForChange in DirectMapMapping in v2.4.0:

    public ChangeRecord compareForChange(Object clone, Object backUp, ObjectChangeSet owner, AbstractSession session) {
	
	// [SNIP]
    
        Map backUpCollection = null;
        if (!owner.isNew()) {
            backUpAttribute = getAttributeValueFromObject(backUp);
            if ((backUpAttribute == null) && (cloneAttribute == null)) {
                return null;
            }
            backUpCollection = (Map)getRealCollectionAttributeValueFromObject(backUp, session);
            Object backUpIter = containerPolicy.iteratorFor(backUpCollection);
            while (containerPolicy.hasNext(backUpIter)) {// Make a lookup of the objects
                Map.Entry entry = (Map.Entry)containerPolicy.nextEntry(backUpIter, session);
                originalKeyValues.put(entry.getKey(), backUpCollection.get(entry.getKey()));
            }
        }
     	// [SNIP]
    }


The code "if (!owner.isNew())" was checking the call to this line:

	Object backUpIter = containerPolicy.iteratorFor(backUpCollection);

This is important because if the OwnerChangeSet is new there will be no backupCollection (it'll be null). Downstream this would cause an NPE.

----------------------------------

Looking at same method (compareForChange in DirectMapMapping) in v2.4.2:

    public ChangeRecord compareForChange(Object clone, Object backUp, ObjectChangeSet owner, AbstractSession session) {

    	// [SNIP]

        Map backUpCollection = null;
        
        if (!owner.isNew()) {
            backUpAttribute = getAttributeValueFromObject(backUp);
            if ((backUpAttribute == null) && (cloneAttribute == null)) {
                return null;
            }
            backUpCollection = (Map)getRealCollectionAttributeValueFromObject(backUp, session);
        }

        DirectMapChangeRecord changeRecord = new DirectMapChangeRecord(owner);
        changeRecord.setAttribute(getAttributeName());
        changeRecord.setMapping(this);
        compareCollectionsForChange(backUpCollection, cloneObjectCollection, changeRecord, session);

    	// [SNIP]
    }


    public void compareCollectionsForChange(Object oldCollection, Object newCollection, ChangeRecord changeRecord, AbstractSession session) {      
        HashMap originalKeyValues = new HashMap(10);
        HashMap cloneKeyValues = new HashMap(10);

        Map backUpCollection = (Map)oldCollection;
        Object backUpIter = containerPolicy.iteratorFor(backUpCollection);
        while (containerPolicy.hasNext(backUpIter)) {// Make a lookup of the objects
            Map.Entry entry = (Map.Entry)containerPolicy.nextEntry(backUpIter, session);
            originalKeyValues.put(entry.getKey(), backUpCollection.get(entry.getKey()));
        }
    	// [SNIP]
    }

The "compareCollectionsForChange" method was introduced in v2.4.2 to abstract the while-loops. The new method contains the following line of code that is *not* guarded:

        Object backUpIter = containerPolicy.iteratorFor(backUpCollection);

If you follow the code from "iteratorFor(backupCollection)" call, it'll null point. The backupCollection value is null and the MapContainerPolicyIterator has that null passed into it as "container":

        public MapContainerPolicyIterator(Map container) {
    	     this.iterator = container.entrySet().iterator();
	}
Comment 1 Tom Ware CLA 2013-08-15 08:33:21 EDT
Please provide a code example that shows the problem.
Comment 2 Tom Ware CLA 2013-08-19 10:11:29 EDT
Setting target and priority.  See the following page for the meanings of these fields:

http://wiki.eclipse.org/EclipseLink/Development/Bugs/Guidelines

Community: Please vote for this bug if it is important to you.  Votes are one of the main criteria we use to determine which bugs to fix next.
Comment 3 Eclipse Webmaster CLA 2022-06-09 10:18:50 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink