使用MOXy抛出异常的继承映射 [英] Inheritance mapping throwing an exception with MOXy
问题描述
我按照 MOXY中的JAXB继承中提到的第二个选项来映射我的父类和下面列出的儿童班。 MOXy抛出以下异常并且不确定问题是什么
I followed the second option mentioned in JAXB inheritance in MOXY to map my parent class and child class listed below. MOXy is throwing the below exception and not sure what the issue is
父类
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;
}
}
儿童类
public class TokenizedUnitedStatesAddressData extends UnitedStatesAddressData implements TokenizedUnitedStatesAddress,
CloneableAddress
{
private String houseNumber;
private String preDirectional;
private String streetName;
private String streetType;
//getters and setters ignored
}
外部绑定文件
<?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>
错误
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
更新
我通过删除prop-order测试了这个除了我不能再控制生成的XML中元素的顺序之外,这种方式工作正常。我相信这是代码中的一个错误。
I've tested this by removing "prop-order" and this works fine except that I can no longer control the order of the elements in generated XML. I believe this is a bug in the code.
推荐答案
原因是子类重写了父类的方法如下所示,但由于父类已定义为xml-transient =true,因此TypeInfo中的以下检查失败。
The cause for this is that the child class overrides the method from parent class as sown below but since the parent class has been defined to be xml-transient="true", the below check from TypeInfo is failing.
子类覆盖getPrimaryAddress
public class TokenizedUnitedStatesAddressData extends UnitedStatesAddressData implements TokenizedUnitedStatesAddress,
CloneableAddress
{
@override
public String getPrimaryAddress()
{
return primaryAddress;
}
}
TypeInfo.java违规代码
if (p.isTransient() && propOrderList.contains(p.getPropertyName()))
{
throw org.eclipse.persistence.exceptions.JAXBException.transientInProporder(p.getPropertyName());
}
更新2
问题不在于AbstractAddress。经过一些调试后,问题似乎是 AnnotationProcessor.getPropertyPropertiesForClass中的以下逻辑(最终的JavaClass cls,最终的TypeInfo信息,最终的boolean onlyPublic,最后的boolean onlyExplicit)
The issue is not with the AbstractAddress. After some debugging, the issue seems to be with the below logic in the AnnotationProcessor.getPropertyPropertiesForClass(final JavaClass cls, final TypeInfo info, final boolean onlyPublic, final boolean onlyExplicit)
if ((setMethod == null) && !(hasJAXBAnnotations(getMethod)))
{
// if there's no corresponding setter, and not explicitly
// annotated, don't process
isPropertyTransient = true;
}
此方法将标记任何无法使用的方法将两者定义为瞬态的get / set方法。在我的例子中,我只重写 TokenizedUnitedStatesAddressData
类中的 getPrimaryAddress()
方法,而不是相应的setter。因此 Annotationprocessor
将其指定为 transient 属性,忽略了重写此方法的事实。
This method will tag any method that doesn't have both the get/set methods defined as "transient". In my case, I override just the getPrimaryAddress()
method in TokenizedUnitedStatesAddressData
class and not the corresponding setter. And hence the Annotationprocessor
is designating it as a transient property neglecting the fact that this method is being overridden.
FIX
确认被覆盖的方法是在瞬态检查中正确处理,如下所示
The issue is fixed after making sure that the overridden methods are properly handled in the transient check as shown below
if ((setMethod == null) && !(hasJAXBAnnotations(getMethod)))
{
if (!isMethodOverrriden(cls.getQualifiedName(), getMethod.getName()))
{
// if there's 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;
}
}
这篇关于使用MOXy抛出异常的继承映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!