Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 322561 - Issues with AbstractTransformationMapping when mixing transformer class and method name
Summary: Issues with AbstractTransformationMapping when mixing transformer class and m...
Status: RESOLVED FIXED
Alias: None
Product: z_Archived
Classification: Eclipse Foundation
Component: Eclipselink (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Nobody - feel free to take it CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks: 322562
  Show dependency tree
 
Reported: 2010-08-12 13:12 EDT by David McCann CLA
Modified: 2022-06-09 10:23 EDT (History)
2 users (show)

See Also:


Attachments
Contains proposed fix (3.00 KB, patch)
2010-08-13 10:37 EDT, David McCann CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description David McCann CLA 2010-08-12 13:12:03 EDT
A null pointer occurs when a transformation mapping is configured with a method name for that attribute transformer and a transformer class for the field transformer:

    XMLTransformationMapping mapping = new XMLTransformationMapping();
    mapping.setAttributeName("normalHours");
    mapping.setAttributeTransformation("myMethod");
    mapping.addFieldTransformer("start/text()", 
                                 new StartTransformer());      


The exception is:
___________________________________________________________________________

javax.xml.bind.JAXBException: 
Descriptor Exceptions: 
---------------------------------------------------------

Exception [EclipseLink-182] (Eclipse Persistence Services - 2.2.0.qualifier): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: The class, [org.example.StartTimeTransformer] cannot be used as a FieldTransformer.
Internal Exception: java.lang.NullPointerException
Mapping: org.eclipse.persistence.oxm.mappings.XMLTransformationMapping[normalHours]
Descriptor: XMLDescriptor(org.example.Employee --> [DatabaseTable(employee)])

Runtime Exceptions: 
---------------------------------------------------------

 - with linked exception:
[Exception [EclipseLink-0] (Eclipse Persistence Services - 2.2.0.qualifier): org.eclipse.persistence.exceptions.IntegrityException
Descriptor Exceptions: 
---------------------------------------------------------

Exception [EclipseLink-182] (Eclipse Persistence Services - 2.2.0.qualifier): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: The class, [org.example.StartTimeTransformer] cannot be used as a FieldTransformer.
Internal Exception: java.lang.NullPointerException
Mapping: org.eclipse.persistence.oxm.mappings.XMLTransformationMapping[normalHours]
Descriptor: XMLDescriptor(org.example.Employee --> [DatabaseTable(employee)])

Runtime Exceptions: 
---------------------------------------------------------
]
	at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:247)
	at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:207)
	at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:104)
	at org.eclipse.persistence.testing.jaxb.externalizedmetadata.ExternalizedMetadataTestCases.createContext(ExternalizedMetadataTestCases.java:576)
	at org.eclipse.persistence.testing.jaxb.externalizedmetadata.mappings.xmltransformation.XmlTransformationTestCases.testMethodSetOnType(XmlTransformationTestCases.java:147)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at junit.framework.TestCase.runTest(TestCase.java:168)
	at junit.framework.TestCase.runBare(TestCase.java:134)
	at junit.framework.TestResult$1.protect(TestResult.java:110)
	at junit.framework.TestResult.runProtected(TestResult.java:128)
	at junit.framework.TestResult.run(TestResult.java:113)
	at junit.framework.TestCase.run(TestCase.java:124)
	at junit.framework.TestSuite.runTest(TestSuite.java:232)
	at junit.framework.TestSuite.run(TestSuite.java:227)
	at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:79)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: Exception [EclipseLink-0] (Eclipse Persistence Services - 2.2.0.qualifier): org.eclipse.persistence.exceptions.IntegrityException
Descriptor Exceptions: 
---------------------------------------------------------

Exception [EclipseLink-182] (Eclipse Persistence Services - 2.2.0.qualifier): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: The class, [org.example.StartTimeTransformer] cannot be used as a FieldTransformer.
Internal Exception: java.lang.NullPointerException
Mapping: org.eclipse.persistence.oxm.mappings.XMLTransformationMapping[normalHours]
Descriptor: XMLDescriptor(org.example.Employee --> [DatabaseTable(employee)])

Runtime Exceptions: 
---------------------------------------------------------

	at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:471)
	at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.initializeDescriptors(DatabaseSessionImpl.java:406)
	at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.postConnectDatasource(DatabaseSessionImpl.java:667)
	at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.login(DatabaseSessionImpl.java:628)
	at org.eclipse.persistence.oxm.XMLContext.<init>(XMLContext.java:213)
	at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:336)
	at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:245)
	... 23 more

___________________________________________________________________________

The issue occurs due to the following check in the convertClassNamesToClasses method:

...
if (this.attributeTransformerClassName == null) {
    return;
}
...

This check prevents the field transformers from having their class names converted to classes if the attribute transformer class name is null (which it is in this case), which leads to the null pointer mentioned above.

One possible solution follows:

    public void convertClassNamesToClasses(ClassLoader classLoader){
        super.convertClassNamesToClasses(classLoader);

        if (this.attributeTransformerClassName != null) {
            Class attributeTransformerClass = null;
            try{
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        attributeTransformerClass = (Class)AccessController.doPrivileged(new PrivilegedClassForName(attributeTransformerClassName, true, classLoader));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(attributeTransformerClassName, exception.getException());
                    }
                } else {
                    attributeTransformerClass = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(attributeTransformerClassName, true, classLoader);
                }
            } catch (ClassNotFoundException exc){
                throw ValidationException.classNotFoundWhileConvertingClassNames(attributeTransformerClassName, exc);
            }
            this.setAttributeTransformerClass(attributeTransformerClass);
        }
        
        for (Enumeration stream = getFieldTransformations().elements(); stream.hasMoreElements();) {
            FieldTransformation transformation = (FieldTransformation)stream.nextElement();
            if (transformation instanceof TransformerBasedFieldTransformation) {
                TransformerBasedFieldTransformation transformer = (TransformerBasedFieldTransformation)transformation;
                String transformerClassName = transformer.getTransformerClassName(); 
                if (transformerClassName == null) {
                    return;
                }
                Class transformerClass = null;
                try{
                    if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                        try {
                            transformerClass = (Class)AccessController.doPrivileged(new PrivilegedClassForName(transformerClassName, true, classLoader));
                        } catch (PrivilegedActionException exception) {
                            throw ValidationException.classNotFoundWhileConvertingClassNames(transformerClassName, exception.getException());
                        }
                    } else {
                        transformerClass = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(transformerClassName, true, classLoader);
                    }
                } catch (ClassNotFoundException exc){
                    throw ValidationException.classNotFoundWhileConvertingClassNames(transformerClassName, exc);
                }
                transformer.setTransformerClass(transformerClass);
            }
        }
    }

Note that this suggested change has not been fully tested.
Comment 1 David McCann CLA 2010-08-13 10:37:12 EDT
Created attachment 176561 [details]
Contains proposed fix

The fix is to NOT break out of the convertClassNamesToClasses method if attributeTransformerClassName is null (breaking out here prevents the field transformer(s) class names being converted to classes).  If attributeTransformerClassName is non null then it will be converted to a class, otherwise it will not.  The field transformer(s) will be processed regardless of whether attributeTransformerClassName is null/non-null.
Comment 2 Guy Pelletier CLA 2010-11-12 14:49:09 EST
Patch provided by Dave has been submitted.

Reviewed by: Guy Pelletier, Andrei Ilitchev, Tom Ware

Tests: JPA Fullregression tests continue to pass successfully.
Comment 3 Eclipse Webmaster CLA 2022-06-09 10:16:15 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink
Comment 4 Eclipse Webmaster CLA 2022-06-09 10:23:00 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink