Inheritance mapping throws an exception with MOXy

I followed the second option mentioned in JAXB's inheritance in MOXY to map my parent class and child class listed below. MOXy throws the following exception and is not sure if the problem is

Parent class

public class UnitedStatesAddressData extends AbstractAddress implements UnitedStatesAddress, Serializable, Cloneable { private String primaryAddress; public String getPrimaryAddress() { return primaryAddress; } public void setPrimaryAddress(final String primaryAddress) { this.primaryAddress = primaryAddress; } } 

Kids class

 public class TokenizedUnitedStatesAddressData extends UnitedStatesAddressData implements TokenizedUnitedStatesAddress, CloneableAddress { private String houseNumber; private String preDirectional; private String streetName; private String streetType; //getters and setters ignored } 

external binding file

 <?xml version="1.0" encoding="UTF-8"?> <xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eclipse.org/eclipselink/xsds/persistence/oxm http://www.eclipse.org/eclipselink/xsds/eclipselink_oxm_2_4.xsd" version="2.4" package-name="com.abc.ic.domain.impl.country.us" xml-accessor-type="PROPERTY"> <xml-schema element-form-default="QUALIFIED" namespace="http://xml.abc.com/XMLSchema/InterConnect"> <!-- Do not specify 'prefix'. We doesn't want the namespace prefix in our instance documents as they increase the payload size. --> <xml-ns namespace-uri="http://xml.abc.com/XMLSchema/InterConnect" /> </xml-schema> <java-types> <java-type name="TokenizedUnitedStatesAddressData"> <xml-root-element name="USAddress" /> <xml-type prop-order="preDirectional houseNumber streetName streetType postDirection unitDesignator apartmentNumber primaryAddress secondaryAddress cityName stateAbbreviation zipCode" /> <java-attributes> <xml-element name="StreetPreDirection" java-attribute="preDirectional" /> <xml-element name="StreetNumber" java-attribute="houseNumber" /> <xml-element name="StreetName" java-attribute="streetName" /> <xml-element name="StreetType" java-attribute="streetType" /> <xml-element name="StreetPostDirection" java-attribute="postDirection" /> <xml-element name="UnitDesignator" java-attribute="unitDesignator" /> <xml-element name="UnitNumber" java-attribute="apartmentNumber" /> <xml-element name="AddressLine1" java-attribute="primaryAddress" /> <xml-element name="AddressLine2" java-attribute="secondaryAddress" /> <xml-element name="City" java-attribute="cityName" /> <xml-element name="State" java-attribute="stateAbbreviation" /> <xml-element name="PostalCode" java-attribute="zipCode" /> </java-attributes> </java-type> <java-type name="UnitedStatesAddressData" xml-transient="true"> <xml-root-element /> </java-type> </java-types> </xml-bindings> 

Error

 javax.xml.bind.JAXBException: Exception Description: The property or field primaryAddress is annotated to be transient so can not be included in the proporder annotation. - with linked exception: [Exception [EclipseLink-50009] (Eclipse Persistence Services - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.JAXBException Exception Description: The property or field primaryAddress is annotated to be transient so can not be included in the proporder annotation.] at org.eclipse.persistence.jaxb.JAXBContext$TypeMappingInfoInput.createContextState(JAXBContext.java:908) at org.eclipse.persistence.jaxb.JAXBContext.<init>(JAXBContext.java:157) at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:170) at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:157) at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:117) at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:107) 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 javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:202) at javax.xml.bind.ContextFinder.find(ContextFinder.java:331) at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:574) at com.abc.ic.platform.sts.domain.transformation.response.JaxbTest.beforeClass(JaxbTest.java:31) 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 org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27) at org.junit.runners.ParentRunner.run(ParentRunner.java:236) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49) 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-50009] (Eclipse Persistence Services - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.JAXBException Exception Description: The property or field primaryAddress is annotated to be transient so can not be included in the proporder annotation. at org.eclipse.persistence.exceptions.JAXBException.transientInProporder(JAXBException.java:225) at org.eclipse.persistence.jaxb.compiler.TypeInfo.setProperties(TypeInfo.java:342) at org.eclipse.persistence.jaxb.compiler.AnnotationsProcessor.buildTypeInfo(AnnotationsProcessor.java:755) at org.eclipse.persistence.jaxb.compiler.AnnotationsProcessor.postBuildTypeInfo(AnnotationsProcessor.java:669) at org.eclipse.persistence.jaxb.compiler.XMLProcessor.processXML(XMLProcessor.java:344) at org.eclipse.persistence.jaxb.compiler.Generator.<init>(Generator.java:145) at org.eclipse.persistence.jaxb.JAXBContext$TypeMappingInfoInput.createContextState(JAXBContext.java:904) ... 28 more 

UPDATE

I checked this by removing the "prop-order", and it works fine , except that I can no longer control the order of the elements in the generated XML . I believe this is a mistake in the code.

+1
source share
2 answers

The reason for this is that the child class overrides the method from the parent class, as shown below, but since the parent class was defined as xml-transient = "true", the check below from TypeInfo fails.

child class overrides getPrimaryAddress

 public class TokenizedUnitedStatesAddressData extends UnitedStatesAddressData implements TokenizedUnitedStatesAddress, CloneableAddress { @override public String getPrimaryAddress() { return primaryAddress; } } 

Code violation TypeInfo.java

 if (p.isTransient() && propOrderList.contains(p.getPropertyName())) { throw org.eclipse.persistence.exceptions.JAXBException.transientInProporder(p.getPropertyName()); } 

UPDATE 2

The problem is not with AbstractAddress. After some debugging, the problem seems to be related to the logic below in AnnotationProcessor.getPropertyPropertiesForClass(final JavaClass cls, final TypeInfo info, final boolean onlyPublic, final boolean onlyExplicit)

 if ((setMethod == null) && !(hasJAXBAnnotations(getMethod))) { // if there no corresponding setter, and not explicitly // annotated, don't process isPropertyTransient = true; } 

This method will tag any method that does not have both get / set methods defined as "transitional". In my case, I override only the getPrimaryAddress() method in the TokenizedUnitedStatesAddressData class, and not the corresponding installer. And therefore, the Annotationprocessor designates it as a transition property, ignoring the fact that this method is overridden.

Fix

The problem is fixed after verifying the correct processing of overridden methods when checking the transient process, as shown below.

 if ((setMethod == null) && !(hasJAXBAnnotations(getMethod))) { if (!isMethodOverrriden(cls.getQualifiedName(), getMethod.getName())) { // if there no corresponding setter, and not explicitly // annotated, don't process isPropertyTransient = true; } } public static boolean isMethodOverrriden(final String classQualifiedName, final String methodName) { Method myMethod; try { myMethod = Class.forName(classQualifiedName).getMethod(methodName, null); } catch (Exception e1) { return false; } Class<?> declaringClass = myMethod.getDeclaringClass(); if (declaringClass.equals(Object.class)) { return false; } Class<?> superclass = declaringClass.getSuperclass(); if (superclass == null) { return false; } else { try { superclass.getMethod(myMethod.getName(), myMethod.getParameterTypes()); } catch (NoSuchMethodException e) { // recursively check all super classes isMethodOverrriden(superclass.getName(), methodName); } return true; } } 
+1
source

Even if you marked UnitedStatesAddressData as @XmlTransient (using the MOXy external mapping document), the AbstractAddress superclass is still a mapped class. Since such properties from AbstractAddress cannot be specified in the propOrder setting for TokenizedUnitedStatesAddressData . The solution would also be AbstractAddress @XmlTransient .

Fix

I modified your mapping document to do this below, assuming the AbstractAddress class is in the same package as the rest of your domain model.

 <?xml version="1.0" encoding="UTF-8"?> <xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eclipse.org/eclipselink/xsds/persistence/oxm http://www.eclipse.org/eclipselink/xsds/eclipselink_oxm_2_4.xsd" version="2.4" package-name="com.abc.ic.domain.impl.country.us" xml-accessor-type="PROPERTY"> <xml-schema element-form-default="QUALIFIED" namespace="http://xml.abc.com/XMLSchema/InterConnect"> <!-- Do not specify 'prefix'. We doesn't want the namespace prefix in our instance documents as they increase the payload size. --> <xml-ns namespace-uri="http://xml.abc.com/XMLSchema/InterConnect" /> </xml-schema> <java-types> <java-type name="TokenizedUnitedStatesAddressData"> <xml-root-element name="USAddress" /> <xml-type prop-order="preDirectional houseNumber streetName streetType postDirection unitDesignator apartmentNumber primaryAddress secondaryAddress cityName stateAbbreviation zipCode" /> <java-attributes> <xml-element name="StreetPreDirection" java-attribute="preDirectional" /> <xml-element name="StreetNumber" java-attribute="houseNumber" /> <xml-element name="StreetName" java-attribute="streetName" /> <xml-element name="StreetType" java-attribute="streetType" /> <xml-element name="StreetPostDirection" java-attribute="postDirection" /> <xml-element name="UnitDesignator" java-attribute="unitDesignator" /> <xml-element name="UnitNumber" java-attribute="apartmentNumber" /> <xml-element name="AddressLine1" java-attribute="primaryAddress" /> <xml-element name="AddressLine2" java-attribute="secondaryAddress" /> <xml-element name="City" java-attribute="cityName" /> <xml-element name="State" java-attribute="stateAbbreviation" /> <xml-element name="PostalCode" java-attribute="zipCode" /> </java-attributes> </java-type> <java-type name="UnitedStatesAddressData" xml-transient="true"> <xml-root-element /> </java-type> <java-type name="AbstractAddress" xml-transient="true"> <xml-root-element /> </java-type> </java-types> </xml-bindings> 

Additional Information

0
source

Source: https://habr.com/ru/post/1415876/


All Articles