| Summary: | MethodAttributeAccessor getAttributeValueFromObject() throws NPE in error handling for a null object | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| Product: | z_Archived | Reporter: | David Minsky <david.minsky> | ||||||
| Component: | Eclipselink | Assignee: | David Minsky <david.minsky> | ||||||
| Status: | RESOLVED FIXED | QA Contact: | Project Inbox <eclipselink.foundation-inbox> | ||||||
| Severity: | normal | ||||||||
| Priority: | P3 | ||||||||
| Version: | unspecified | ||||||||
| Target Milestone: | --- | ||||||||
| Hardware: | All | ||||||||
| OS: | All | ||||||||
| Whiteboard: | |||||||||
| Attachments: |
|
||||||||
|
Description
David Minsky
This error may occur when two parent objects are (incorrectly) referencing the same aggregate object. Resolving this issue will contribute to how diagnosable this potential problem is in the long run. Created attachment 197547 [details]
Proposed fix
Proposed fix.
Follows same pattern as the implementation of the same superclass method in InstanceVariableAttributeAccessor.
"reproduced" the incorrect scenario of sharing aggregate objects in EL trunk: Local Exception Stack: Exception [EclipseLink-69] (Eclipse Persistence Services - @VERSION@.@QUALIFIER@): org.eclipse.persistence.exceptions.DescriptorException Exception Description: A NullPointerException was thrown while extracting a value from the instance variable [endDate] in the object [null]. Internal Exception: java.lang.NullPointerException Mapping: org.eclipse.persistence.mappings.DirectToFieldMapping[endDate-->EMPLOYEE.END_DATE] Descriptor: RelationalDescriptor(examples.sessions.threetier.model.EmploymentPeriod --> [DatabaseTable(EMPLOYEE), DatabaseTable(SALARY)]) at org.eclipse.persistence.exceptions.DescriptorException.nullPointerWhileGettingValueThruInstanceVariableAccessor(DescriptorException.java:1263) at org.eclipse.persistence.internal.descriptors.InstanceVariableAttributeAccessor.getAttributeValueFromObject(InstanceVariableAttributeAccessor.java:88) at org.eclipse.persistence.mappings.DatabaseMapping.getAttributeValueFromObject(DatabaseMapping.java:516) at org.eclipse.persistence.mappings.foundation.AbstractDirectMapping.compareObjects(AbstractDirectMapping.java:455) at org.eclipse.persistence.mappings.foundation.AbstractDirectMapping.compareForChange(AbstractDirectMapping.java:407) at org.eclipse.persistence.descriptors.changetracking.DeferredChangeDetectionPolicy.createObjectChangeSetThroughComparison(DeferredChangeDetectionPolicy.java:165) at org.eclipse.persistence.descriptors.changetracking.DeferredChangeDetectionPolicy.createObjectChangeSet(DeferredChangeDetectionPolicy.java:137) at org.eclipse.persistence.descriptors.changetracking.DeferredChangeDetectionPolicy.calculateChanges(DeferredChangeDetectionPolicy.java:89) at org.eclipse.persistence.internal.descriptors.ObjectBuilder.compareForChange(ObjectBuilder.java:1964) at org.eclipse.persistence.mappings.AggregateMapping.compareForChange(AggregateMapping.java:313) at org.eclipse.persistence.descriptors.changetracking.DeferredChangeDetectionPolicy.createObjectChangeSetThroughComparison(DeferredChangeDetectionPolicy.java:165) at org.eclipse.persistence.descriptors.changetracking.DeferredChangeDetectionPolicy.createObjectChangeSet(DeferredChangeDetectionPolicy.java:137) at org.eclipse.persistence.descriptors.changetracking.DeferredChangeDetectionPolicy.calculateChanges(DeferredChangeDetectionPolicy.java:89) 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.UnitOfWorkImpl.commitRootUnitOfWork(UnitOfWorkImpl.java:1317) at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commit(UnitOfWorkImpl.java:1079) The following Employee demo-based example was used:
UnitOfWork uow = getSession().acquireUnitOfWork();
Employee employee1Original = new Employee();
Employee employee2Original = new Employee();
Employee employee1Clone = (Employee) uow.registerObject(employee1Original);
Employee employee2Clone = (Employee) uow.registerObject(employee2Original);
employee1Clone.setMale();
employee1Clone.setFirstName("Joe");
employee1Clone.setLastName("Someone");
employee1Clone.setSalary(1234);
employee1Clone.setPeriod(new EmploymentPeriod()); // not null
employee2Clone.setFemale();
employee2Clone.setFirstName("Jill");
employee2Clone.setLastName("Someone");
employee2Clone.setSalary(1234);
employee2Clone.setPeriod(null); // deliberately null
uow.commit();
uow = getSession().acquireUnitOfWork();
employee1Clone = (Employee)uow.registerObject(employee1Original);
// UoW backup clone's 'period' attribute is null
employee2Clone = (Employee)uow.registerObject(employee2Original);
employee2Clone.setPeriod(employee1Clone.getPeriod()); // 1. share the aggregate
uow.commit();
Created attachment 198561 [details]
Proposed fix
Aggregate sharing testcase no longer reproduces with the changes from: Revision: 9610 Author: gyorke Date: 2:47:23 PM, June 22, 2011 Message: Bug 300108 - Any changes that reference detached object will cause detached to be inserted I've attached the exception fix I was working on, for brevity. This exception would be thrown, instead of an NPE when the attribute accessor attempted to invoke on a null object. The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink |