使用MOXy抛出异常的继承映射 [英] Inheritance mapping throwing an exception with MOXy

查看:105
本文介绍了使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆