简体   繁体   English

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

[英]JAXB compiler is binding xs:boolean to Java Boolean wrapper class, instead of boolean primitive type

I'm migrating a project from JAXB 1.0 to JAXB 2.1 and I'm having problems with the datatype mapping. 我正在将项目从JAXB 1.0迁移到JAXB 2.1,我遇到了数据类型映射问题。

I'm using the Ant xjc binding compiler, and I've successfully configured the global bindings such that (for example) xs:date maps to java.util.Calendar . 我正在使用Ant xjc绑定编译器,并且我已经成功配置了全局绑定,例如xs:date映射到java.util.Calendar

However I'm getting generated methods which return Boolean , whereas I want boolean . 但是我得到的生成方法返回Boolean ,而我想要boolean

Here is the complex type: 这是复杂的类型:

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

And the generated class looks like this: 生成的类看起来像这样:

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

The problem is that although boxing will work, if the supplied XML doesn't contain a value for pricepoint_custom_fields_required , the class's Boolean field is null, instead of false. 问题是虽然装箱会起作用,但如果提供的XML不包含pricepoint_custom_fields_required的值,则类的布尔字段为空,而不是false。 So I get NullPointerExceptions when doing something like this: 这样做的时候我得到NullPointerExceptions

methodWhichTakesPrimitiveBooleanArg(myUsageAuthRateChargeInstance.isPricepointCustomFieldsRequired());

because it tries to unbox the Boolean passed in - except it's null. 因为它试图取消传入的布尔值 - 除了它为空。


I can't change the schema, and I can't adjust all the client code to do the null checks. 我无法更改架构,我无法调整所有客户端代码来执行空检查。

I've set the optionalProperty attribute in my binding.xml as follows: 我在binding.xml中设置了optionalProperty属性,如下所示:

<globalBindings optionalProperty="primitive">

In the spec, it says: "If the attribute's value is "primitive", it binds as it did in JAXB 1.0" 在规范中,它说:“如果属性的值是”原始的“,它会像在JAXB 1.0中那样绑定”

Yet this is clearly not happening. 然而,这显然没有发生。

How can I solve this problem? 我怎么解决这个问题?

UPDATE: 更新:

This is now fixed in jaxb 2.2.9: https://java.net/jira/browse/JAXB/fixforversion/16850 这现在在jaxb 2.2.9中修复: https ://java.net/jira/browse/JAXB/fixforversion/16850

Problem 问题

The reason you are getting Boolean instead of boolean is that you have minOccurs="0" in your element definition. 获得Boolean而不是boolean的原因是元素定义中有minOccurs="0" A null value will be stored for an absent element. 将为缺席元素存储null值。

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

What the Solution Should Be 解决方案应该是什么

The solution should be an external binding file that indicates that a primitive type should be used for optional values (see section 7.5.1 of the JAXB 2.2 specification). 解决方案应该是一个外部绑定文件,指示应该将基本类型用于可选值(请参阅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>

The external binding file is specified using the -b option with XJC. 使用带有XJC的-b选项指定外部绑定文件。

xjc -b binding.xml my-schema.xsd

Why That Solution Does Not Work 为什么该解决方案不起作用

The following bugs have been opened to track the issue with optionalProperty="primitive" . 已打开以下错误以跟踪optionalProperty="primitive"

Workaround 解决方法

If you don't like the way a class is generated in JAXB, then you can create a class yourself and have JAXB pull it in as part of the schema to class generation. 如果您不喜欢在JAXB中生成类的方式,那么您可以自己创建一个类,并让JAXB将其作为模式的一部分引入类生成。

binding.xml 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 UsageAuthRateCharge

Create this class with the methods as you want them. 使用您想要的方法创建此类。

XJC Call XJC电话

Use the -b flag on the XJC call to specify the binding.xml file 在XJC调用上使用-b标志来指定binding.xml文件

xjc -b binding.xml my-schema.xsd

UPDATE UPDATE

What I was really hoping was that one of the readers might be a jaxb dev team member who could do the change easily in jaxb. 我真正希望的是,其中一位读者可能是一名jaxb开发团队成员,可以轻松地在jaxb中进行更改。 User archenroot offered a possible solution in his comments on jaxb issue 927 (a duplicate of 926) which leads me to think that for the right person, it would be a simple job to fix jaxb 用户archenroot在他对jaxb issue 927(926的重复)的评论中提供了一个可能的解决方案,这使我认为对于合适的人来说,修复jaxb将是一项简单的工作

I'm the EclipseLink JAXB (MOXy) lead. 我是EclipseLink JAXB(MOXy)的领导者。 I have reached out to my colleagues who do the JAXB reference implementation (they also work for Oracle). 我已经联系了执行JAXB参考实现的同事(他们也适用于Oracle)。 Below is the reply I got from them: 以下是我从他们那里得到的答复:

I've tested in trunk - and the problem exists. 我已经在后备箱测试了 - 问题就存在了。 I'll check code how easy is to fix it. 我会检查代码修复它有多容易。

Hopefully you will be able to get a real fix for this issue. 希望你能够真正解决这个问题。

Try this... 试试这个...

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

I found your question as I was looking how to do the exact opposite thing you were doing. 我找到了你的问题,因为我正在寻找如何做你正在做的事情。 I had a boolean attribute that would only generate code that had the attribute as a primitive boolean value. 我有一个布尔属性,只生成具有该属性作为原始布尔值的代码。 To make jaxb generate this attribute as a Boolean object instead of a boolean primitive, I just removed the use="required" portion of my attribute's definition in the xsd. 为了使jaxb生成此属性作为布尔对象而不是布尔基元,我只是删除了xsd中属性定义的use =“required”部分。

I got bored of waiting for a fix from the dev team so I rolled up my sleeves and did it myself. 我厌倦了等待开发团队的修复,所以我卷起袖子自己做了。

I'm including the code below to help people for whom this is also an issue. 我将下面的代码包括在内,以帮助那些也是问题的人。

Disclaimer : my code probably isn't the best way to solve the problem but it works for me. 免责声明 :我的代码可能不是解决问题的最佳方法,但它对我有用。

The generated code now looks like this: 生成的代码现在看起来像这样:

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

And the modification is as follows: 修改如下:

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

After the line 行后

types.addTo(prop);

insert the following code: 插入以下代码:

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"));
    }

Just to make it complete 只是为了完成它

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM