JAXB 生成不需要的 @XMLValue
JAXB generating unwanted @XMLValue
现在已经解决了大约半个星期的问题,需要帮助,因为我似乎无法取得任何进展。
我继承了一个 8 年没有得到很好对待的应用程序....仍然在 Java 1.4,Maven1 构建,8 年没有新的单元测试...
目前升级到 Java 1.6(Java 1.8 分支也同时完成,将测试两者)和 Maven 3.3.3 正在顺利进行 - 取得了很好的进展。
现在碰壁了,暂时没有突破
旧源使用本地 JAXB 1.3 jar 从大型 XSD.
生成 classes
我不得不从 JAXB1.3 迁移到 JAXB2.1 - 这也意味着随着命名约定的改变,我不得不花费大量时间重写对生成的 classes 的所有引用。
总之,编译代码花了很多时间。
最后,它编译了,我尝试了一个单元测试,看看它是如何工作的。
这是我遇到问题的地方。
大多数 classes 编译工作正常,但当我尝试生成 JAXBContext 时,其中三个包抛出异常:
派生另一个 class. 的 class 不允许 @XmlValue
我已将问题缩小为出现在几个生成的 classes 中的模式。
导致异常的class在schema中定义如下:
<xs:element name="ContactName">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="First" type="xs:string"/>
<xs:attribute name="Middle" type="xs:string"/>
<xs:attribute name="Last" type="xs:string"/>
<xs:attribute name="Name" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
然后这个元素在另一个中引用如下:
<xs:element name="ContactInfo">
<xs:complexType>
<xs:annotation>
<xs:documentation>Common contact information</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element ref="ContactName" minOccurs="0" maxOccurs="unbounded"/>
<xs:element ref="ContactID" minOccurs="0"/>
<xs:element ref="ContactDivision" minOccurs="0" maxOccurs="unbounded"/>
.....
生成为:
联系人姓名:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"value"
})
@XmlRootElement(name = "ContactName")
public class ContactName
extends BaseJaxbDoc
implements Serializable, Cloneable, CopyTo
{
private final static long serialVersionUID = 47110815L;
@XmlValue
protected String value;
@XmlAttribute(name = "First")
protected String first;
@XmlAttribute(name = "Middle")
protected String middle;
@XmlAttribute(name = "Last")
protected String last;
@XmlAttribute(name = "Name")
protected String name;
然后在ContactInfo中声明如下:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"contactName",
"contactID",
"contactDivision",
"contactPhone",
"contactPhoneHome",
"contactPhoneMobile",
"contactFax",
"contactEmail",
"contactEmail2"
})
@XmlRootElement(name = "ContactInfo")
public class ContactInfo
extends BaseJaxbDoc
implements Serializable, Cloneable, CopyTo
{
private final static long serialVersionUID = 47110815L;
@XmlElement(name = "ContactName")
protected List<ContactName> contactName;
抛出的异常在:
this problem is related to the following location:
at protected java.lang.String xxx.xx.xxxx.xxxx.orders.jaxb.ContactName.value
at xxx.xx.xxxx.xxxx.orders.jaxb.ContactName
at protected java.util.List xxx.xx.xxxx.xxxx.orders.jaxb.ContactInfo.contactName
at xxx.xx.xxxx.xxxx.orders.jaxb.ContactInfo
at protected java.util.List xxx.xx.xxxx.xxxx.orders.jaxb.CustomerReference.contactInfo
at xxx.xx.xxxx.xxxx.orders.jaxb.CustomerReference
at protected java.util.List xxx.xx.xxxx.xxxx.orders.jaxb.Item.customerReference
at xxx.xx.xxxx.xxxx.orders.jaxb.Item
at public xxx.xx.xxxx.xxxx.orders.jaxb.Item xxx.xx.xxxx.xxxx.orders.jaxb.ObjectFactory.createItem()
at xxx.xx.xxxx.xxxx.orders.jaxb.ObjectFactory
对原始模式进行了 XML 转换,删除了注释并创建了 jaxb:typesafeEnum 类型。然后将转换后的模式与 jxb 绑定文件一起使用,将所有内容绑定到内部 jaxb 助手 superclass - BaseJaxbDoc
<jaxb:globalBindings generateIsSetMethod="true">
<xjc:serializable uid="47110815"/>
<xjc:superClass name="xxx.xx.xxxx.xxxx.helpers.BaseJaxbDoc"/>
<jaxb:javaType name="java.math.BigDecimal" xmlType="xs:decimal"
parseMethod="xxx.xx.xxxx.xxxx.helpers.AmountConverter.parseAmount"
printMethod="xxx.xx.xxxx.xxxx.helpers.AmountConverter.printAmount"/>
</jaxb:globalBindings>
这是因为我在 9 个不同的模式上使用 xjc,所有模式都生成 classes 的 JAXB 包。
classes 都有相同的 superclass(在每个模式的绑定文件中定义)只实现 JAXB marshall/unmarshallclasses 一次,以及其他一些辅助功能。
所以我的问题是当我无法修改模式时如何解决这个异常?
XSLT 中的内容或绑定文件中的内容?
我的 Maven 依赖项:
对于 JAXB:
org.jvnet.jaxb2.maven2
maven-jaxb21-插件
0.13.0
JAXB 运行时:
org.glassfish.jaxb
jaxb 运行时
2.2.11
尝试用 @XmlTransient
注释 BaseJaxbDoc
。
你遇到的问题产生了here:
if(getBaseClass()!=null) {
builder.reportError(new IllegalAnnotationException(
Messages.XMLVALUE_IN_DERIVED_TYPE.format(), p ));
}
JAXB 认为您的 BaseJaxbDoc
是一个基础 class。因此,您应该删除 xjc:superClass
或让 JAXB 认为您的 class 没有基础 class.
当我在 ModelBuilder
中查看 this part of the code 时:
if(reader.hasClassAnnotation(clazz,XmlTransient.class) || isReplaced) {
// handle it as if the base class was specified
r = getClassInfo( nav.getSuperClass(clazz), searchForSuperClass,
new ClassLocatable<C>(upstream,clazz,nav) );
}
似乎 ModelBuilder
在 class 上识别了 @XmlTransient
而没有考虑它们。因此,在您的 BaseJaxbDoc
上分配 @XmlTransient
可能会有所帮助。
另一种选择是放弃 BaseJaxbDoc
结构。您使用 class 继承将 marshal/unmarshal 功能添加到模式派生的 classes。我宁愿将此功能移出到某些外部服务中。这可能不是一个选项,因为您可能面临很多遗留代码。
另一种选择是在运行时尝试使用 MOXy 而不是 JAXB RI。
现在已经解决了大约半个星期的问题,需要帮助,因为我似乎无法取得任何进展。
我继承了一个 8 年没有得到很好对待的应用程序....仍然在 Java 1.4,Maven1 构建,8 年没有新的单元测试...
目前升级到 Java 1.6(Java 1.8 分支也同时完成,将测试两者)和 Maven 3.3.3 正在顺利进行 - 取得了很好的进展。
现在碰壁了,暂时没有突破
旧源使用本地 JAXB 1.3 jar 从大型 XSD.
生成 classes我不得不从 JAXB1.3 迁移到 JAXB2.1 - 这也意味着随着命名约定的改变,我不得不花费大量时间重写对生成的 classes 的所有引用。 总之,编译代码花了很多时间。
最后,它编译了,我尝试了一个单元测试,看看它是如何工作的。 这是我遇到问题的地方。
大多数 classes 编译工作正常,但当我尝试生成 JAXBContext 时,其中三个包抛出异常:
派生另一个 class. 的 class 不允许@XmlValue
我已将问题缩小为出现在几个生成的 classes 中的模式。 导致异常的class在schema中定义如下:
<xs:element name="ContactName">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="First" type="xs:string"/>
<xs:attribute name="Middle" type="xs:string"/>
<xs:attribute name="Last" type="xs:string"/>
<xs:attribute name="Name" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
然后这个元素在另一个中引用如下:
<xs:element name="ContactInfo">
<xs:complexType>
<xs:annotation>
<xs:documentation>Common contact information</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element ref="ContactName" minOccurs="0" maxOccurs="unbounded"/>
<xs:element ref="ContactID" minOccurs="0"/>
<xs:element ref="ContactDivision" minOccurs="0" maxOccurs="unbounded"/>
.....
生成为:
联系人姓名:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"value"
})
@XmlRootElement(name = "ContactName")
public class ContactName
extends BaseJaxbDoc
implements Serializable, Cloneable, CopyTo
{
private final static long serialVersionUID = 47110815L;
@XmlValue
protected String value;
@XmlAttribute(name = "First")
protected String first;
@XmlAttribute(name = "Middle")
protected String middle;
@XmlAttribute(name = "Last")
protected String last;
@XmlAttribute(name = "Name")
protected String name;
然后在ContactInfo中声明如下:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"contactName",
"contactID",
"contactDivision",
"contactPhone",
"contactPhoneHome",
"contactPhoneMobile",
"contactFax",
"contactEmail",
"contactEmail2"
})
@XmlRootElement(name = "ContactInfo")
public class ContactInfo
extends BaseJaxbDoc
implements Serializable, Cloneable, CopyTo
{
private final static long serialVersionUID = 47110815L;
@XmlElement(name = "ContactName")
protected List<ContactName> contactName;
抛出的异常在:
this problem is related to the following location:
at protected java.lang.String xxx.xx.xxxx.xxxx.orders.jaxb.ContactName.value
at xxx.xx.xxxx.xxxx.orders.jaxb.ContactName
at protected java.util.List xxx.xx.xxxx.xxxx.orders.jaxb.ContactInfo.contactName
at xxx.xx.xxxx.xxxx.orders.jaxb.ContactInfo
at protected java.util.List xxx.xx.xxxx.xxxx.orders.jaxb.CustomerReference.contactInfo
at xxx.xx.xxxx.xxxx.orders.jaxb.CustomerReference
at protected java.util.List xxx.xx.xxxx.xxxx.orders.jaxb.Item.customerReference
at xxx.xx.xxxx.xxxx.orders.jaxb.Item
at public xxx.xx.xxxx.xxxx.orders.jaxb.Item xxx.xx.xxxx.xxxx.orders.jaxb.ObjectFactory.createItem()
at xxx.xx.xxxx.xxxx.orders.jaxb.ObjectFactory
对原始模式进行了 XML 转换,删除了注释并创建了 jaxb:typesafeEnum 类型。然后将转换后的模式与 jxb 绑定文件一起使用,将所有内容绑定到内部 jaxb 助手 superclass - BaseJaxbDoc
<jaxb:globalBindings generateIsSetMethod="true">
<xjc:serializable uid="47110815"/>
<xjc:superClass name="xxx.xx.xxxx.xxxx.helpers.BaseJaxbDoc"/>
<jaxb:javaType name="java.math.BigDecimal" xmlType="xs:decimal"
parseMethod="xxx.xx.xxxx.xxxx.helpers.AmountConverter.parseAmount"
printMethod="xxx.xx.xxxx.xxxx.helpers.AmountConverter.printAmount"/>
</jaxb:globalBindings>
这是因为我在 9 个不同的模式上使用 xjc,所有模式都生成 classes 的 JAXB 包。
classes 都有相同的 superclass(在每个模式的绑定文件中定义)只实现 JAXB marshall/unmarshallclasses 一次,以及其他一些辅助功能。 所以我的问题是当我无法修改模式时如何解决这个异常? XSLT 中的内容或绑定文件中的内容?
我的 Maven 依赖项: 对于 JAXB: org.jvnet.jaxb2.maven2 maven-jaxb21-插件 0.13.0
JAXB 运行时: org.glassfish.jaxb jaxb 运行时 2.2.11
尝试用 @XmlTransient
注释 BaseJaxbDoc
。
你遇到的问题产生了here:
if(getBaseClass()!=null) {
builder.reportError(new IllegalAnnotationException(
Messages.XMLVALUE_IN_DERIVED_TYPE.format(), p ));
}
JAXB 认为您的 BaseJaxbDoc
是一个基础 class。因此,您应该删除 xjc:superClass
或让 JAXB 认为您的 class 没有基础 class.
当我在 ModelBuilder
中查看 this part of the code 时:
if(reader.hasClassAnnotation(clazz,XmlTransient.class) || isReplaced) {
// handle it as if the base class was specified
r = getClassInfo( nav.getSuperClass(clazz), searchForSuperClass,
new ClassLocatable<C>(upstream,clazz,nav) );
}
似乎 ModelBuilder
在 class 上识别了 @XmlTransient
而没有考虑它们。因此,在您的 BaseJaxbDoc
上分配 @XmlTransient
可能会有所帮助。
另一种选择是放弃 BaseJaxbDoc
结构。您使用 class 继承将 marshal/unmarshal 功能添加到模式派生的 classes。我宁愿将此功能移出到某些外部服务中。这可能不是一个选项,因为您可能面临很多遗留代码。
另一种选择是在运行时尝试使用 MOXy 而不是 JAXB RI。