| Summary: | Issues with AbstractTransformationMapping when mixing transformer class and method name | ||||||
|---|---|---|---|---|---|---|---|
| Product: | z_Archived | Reporter: | David McCann <david.mccann> | ||||
| Component: | Eclipselink | Assignee: | Nobody - feel free to take it <nobody> | ||||
| Status: | RESOLVED FIXED | QA Contact: | |||||
| Severity: | normal | ||||||
| Priority: | P3 | CC: | eclipselink.foundation-inbox, guy.pelletier | ||||
| Version: | unspecified | ||||||
| Target Milestone: | --- | ||||||
| Hardware: | PC | ||||||
| OS: | Windows XP | ||||||
| Whiteboard: | |||||||
| Bug Depends on: | |||||||
| Bug Blocks: | 322562 | ||||||
| Attachments: |
|
||||||
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.
Patch provided by Dave has been submitted. Reviewed by: Guy Pelletier, Andrei Ilitchev, Tom Ware Tests: JPA Fullregression tests continue to pass successfully. The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink |
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.