JAXB编译器将xs:boolean绑定到Java布尔包装类,而不是布尔基元类型

时间:2012-10-23 17:25:54

标签: java xml xsd jaxb xjc

我正在将项目从JAXB 1.0迁移到JAXB 2.1,我遇到了数据类型映射问题。

我正在使用Ant xjc 绑定编译器,并且我已成功配置全局绑定,以便(例如) xs:date 映射到 java.util.Calendar中

但是我得到的生成方法返回Boolean,而我想要boolean

以下是复杂类型:

<xs:element name="usage-auth-rate-charge">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="service-id" type="xs:string"/>
            <xs:element name="pricepoint_custom_fields_required" type="xs:boolean" minOccurs="0"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>

生成的类看起来像这样:

public class UsageAuthRateCharge {
........
public Boolean isPricepointCustomFieldsRequired() {
    return pricepointCustomFieldsRequired;
}

问题是尽管装箱会起作用,但如果提供的XML不包含pricepoint_custom_fields_required的值,则类的布尔字段为空,而不是false。在做这样的事情时我得到 NullPointerExceptions

methodWhichTakesPrimitiveBooleanArg(myUsageAuthRateChargeInstance.isPricepointCustomFieldsRequired());

因为它试图取消传入的布尔值 - 除了它为空。


我无法更改架构,我无法调整所有客户端代码来进行空检查。

我在 binding.xml 中设置了 optionalProperty 属性,如下所示:

<globalBindings optionalProperty="primitive">

在规范中,它说:“如果属性的值是”原始的“,它会像在JAXB 1.0中那样绑定”

然而,这显然没有发生。

我该如何解决这个问题?

更新

现在已在jaxb 2.2.9中修复: https://java.net/jira/browse/JAXB/fixforversion/16850

4 个答案:

答案 0 :(得分:27)

问题

您获得Boolean而不是boolean的原因是您的元素定义中包含minOccurs="0"。将为缺席元素存储null值。

<xs:element name="pricepoint_custom_fields_required" type="xs:boolean" minOccurs="0"/>

解决方案应该是什么

解决方案应该是一个外部绑定文件,指示应该将基本类型用于可选值(请参阅JAXB 2.2规范的第7.5.1节)。

<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    version="2.1">
    <jaxb:globalBindings optionalProperty="primitive"/>
</jaxb:bindings>

使用带有XJC的-b选项指定外部绑定文件。

xjc -b binding.xml my-schema.xsd

为什么该解决方案不起作用

已打开以下错误以跟踪optionalProperty="primitive"的问题。

解决方法

如果您不喜欢在JAXB中生成类的方式,那么您可以自己创建一个类,让JAXB将其作为模式的一部分引入类生成。

<强> binding.xml

<jxb:bindings 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
    version="2.1">

    <jxb:bindings schemaLocation="my-schema.xsd">
        <jxb:bindings node="//xs:element[@name='usage-auth-rate-charge']/complexType">
            <jxb:class ref="com.example.foo.UsageAuthRateCharge"/>
        </jxb:bindings>
    </jxb:bindings>
</jxb:bindings>

<强> UsageAuthRateCharge

使用您想要的方法创建此类。

XJC致电

使用XJC调用上的-b标志指定binding.xml文件

xjc -b binding.xml my-schema.xsd

更新

  

我真正希望的是其中一位读者可能是jaxb   能够在jaxb中轻松完成更改的开发团队成员。用户   archenroot在他对jaxb问题的评论中提供了一个可能的解决方案   927(926的重复)让我认为是正确的   对于修复jaxb来说,这将是一项简单的工作

我是EclipseLink JAXB (MOXy)领导。我已经联系了执行JAXB参考实现的同事(他们也适用于Oracle)。以下是我从他们那里得到的答复:

  

我在后备箱中测试过 - 问题就存在了。   我会检查代码修复它是多么容易。

希望你能够真正解决这个问题。

答案 1 :(得分:3)

试试这个......

<xs:element name="usage-auth-rate-charge">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="service-id" type="xs:string"/>
        </xs:sequence>
        <xs:attribute name="chosen" type="xs:boolean" use="required"/>
    </xs:complexType>
</xs:element>

我找到了你的问题,因为我正在寻找如何做你正在做的事情。我有一个布尔属性,只生成具有该属性作为原始布尔值的代码。为了使jaxb生成此属性作为布尔对象而不是布尔基元,我只是删除了xsd中属性定义的use =“required”部分。

答案 2 :(得分:0)

我厌倦了等待开发团队的修复,所以我卷起袖子自己做了。

我包括以下代码,以帮助这也是一个问题的人。

免责声明:我的代码可能不是解决问题的最佳方法,但它对我有用。

生成的代码现在看起来像这样:

public boolean isPricepointCustomFieldsRequired() {
    if (pricepointCustomFieldsRequired == null) {
        return false;
    } else {
        return pricepointCustomFieldsRequired;
    }
}

修改如下:

com.sun.tools.xjc.reader.xmlschema.bindinfo.BIProperty:createElementProperty,line~358

types.addTo(prop);

之后

插入以下代码:

if (prop.isOptionalPrimitive() && getOptionalPropertyMode() == OptionalPropertyMode.PRIMITIVE &&
    !prop.getTypes().isEmpty() && "boolean".equals(prop.getTypes().get(0).getTypeName().getLocalPart()) )   {
        prop.defaultValue= CDefaultValue.create(CBuiltinLeafInfo.BOOLEAN, new XmlString("false"));
    }

答案 3 :(得分:0)

只是为了使其完整

type="xs:boolean" minOccurs="0" maxOccurs="1"                   == Boolean value (object)

type="xs:boolean" minOccurs="0" maxOccurs="1" nillable="true"   == JAXBElement<Boolean> value (object)

type="xs:boolean" minOccurs="1" maxOccurs="1"                   == boolean value (primitive)

type="xs:boolean" minOccurs="1" maxOccurs="1" nillable="true"   == Boolean value (object)