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

后端 未结 4 1706
天涯浪人
天涯浪人 2020-12-09 10:36

I\'m migrating a project from JAXB 1.0 to JAXB 2.1 and I\'m having problems with the datatype mapping.

I\'m using the Ant xjc binding compiler, and I\'ve su

相关标签:
4条回答
  • 2020-12-09 10:44

    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

    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"));
        }
    
    0 讨论(0)
  • 2020-12-09 10:47

    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.

    0 讨论(0)
  • 2020-12-09 10:47

    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)
    
    0 讨论(0)
  • 2020-12-09 10:56

    Problem

    The reason you are getting Boolean instead of boolean is that you have minOccurs="0" in your element definition. A null value will be stored for an absent element.

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

    <?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 binding.xml my-schema.xsd
    

    Why That Solution Does Not Work

    The following bugs have been opened to track the issue with optionalProperty="primitive".

    • https://github.com/javaee/jaxb-v2/issues/510
    • https://github.com/javaee/jaxb-v2/issues/926

    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.

    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

    Create this class with the methods as you want them.

    XJC Call

    Use the -b flag on the XJC call to specify the binding.xml file

    xjc -b binding.xml my-schema.xsd
    

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

    I'm the EclipseLink JAXB (MOXy) lead. I have reached out to my colleagues who do the JAXB reference implementation (they also work for 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.

    0 讨论(0)
提交回复
热议问题