2012-08-10 121 views
1

我遵循JAXB inheritance in MOXY中提到的第二个选项来映射我的父类和子类。莫西抛出以下异常,并不能确定是什么问题继承映射抛出异常与MOXy

父类

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 

UPDATE

我已经通过去除“丙顺序”测试这一点,并能正常工作除了我不能再控制中产生的元素的顺序XML。我相信这是代码中的一个错误。

+0

- https://bugs.eclipse.org/bugs/show_bug.cgi?id= 387308 – 2012-08-15 17:57:47

回答

1

原因是子类重写了父类的方法,如下所示,但由于父类已被定义为xml-transient =“true”,因此TypeInfo的下面的检查失败。

子类中重写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(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将其指定为瞬态属性,忽略了这种方法被覆盖的事实。

FIX

问题是确保被覆盖的方法是在短暂的检查处理不当如下图所示

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; 
     } 
    } 
+0

这不是一个bug,问题是在你的模型中'AbstractAddress'仍然是一个映射类。请参阅:http://stackoverflow.com/a/11908405/383861 – 2012-08-11 11:26:21

0

即使您已标记后固定UnitedStatesAddressData@XmlTransient(使用莫西的外部映射文档),它的超类AbstractAddress仍然是映射类。由于AbstractAddress的此类属性无法在TokenizedUnitedStatesAddressDatapropOrder设置中指定。解决办法也是制作AbstractAddress@XmlTransient

修复

我已经修改了你的映象文件要做到这一点下面假设AbstractAddress类在同一个包中域模型的其余部分。

<?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> 

对于创建一个错误的的EclipseLink /莫西更多信息

+0

嗨,我用新的发现更新了我的答案。问题不在于AbstractAddress,而在于AnnotationProcessor忽略重写的方法 – 2012-08-16 16:37:05