JAXB binding for xs:integer to Java Integer instead of BigInteger

7.2k views Asked by At

The following discussions should be avoided. What this question is NOT:

  • using xs:int instead of xs:integer.
  • using primitive int instead of Integer.
  • why do you need this.
  • what are you gonna do if etc.

QUESTION:

I would like an example of a jaxb binding declaration to override the default mapping of xs:integer to Java BigInteger, so that xjc would produce Java Integer instead.

e.g.

<xs:attribute name="id" type="xs:integer"/>

should produce

@XmlAttribute(name = "id")
Integer id;

and not

@XmlAttribute(name = "id")
BigInteger id;
4

There are 4 answers

0
Jeroen van Montfort On BEST ANSWER

You could add the following to your bindings file:

<globalBindings>
    <javaType xmlType="xs:integer" name="java.lang.Integer"/> 
</globalBindings>

This will produce, for example:

@XmlAttribute(name = "id")
@XmlJavaTypeAdapter(Adapter1 .class)
protected Integer id;

public int getId() {
    if (id == null) {
        return new Adapter1().unmarshal("0");
    } else {
        return id;
    }
}

public void setId(Integer value) {
    this.id = value;
}
0
Mubashar On

@JeroenVanMontfort's answer is a way to go however it would not work as is since the namespace deceleration and setup details are missing. So following is details if you are looking for more details about this.

There are multiple ways of creating binding files however you can also create embedded binding but I'll skip that part for the sake of this question. however if you like to read in details including what else you can achieve from binding files please see this blog by coderleaf

Following is a simple binding files creating global binding to ensure xs:integer is converted to java.lan.Integer instead of BigInteger and also it defines a specific binding of a enum value to be integer (this is not a part of question though however added just to depict mix bindings)

<jxb:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="https://java.sun.com/xml/ns/jaxb https://java.sun.com/xml/ns/jaxb/bindingschema_2_1.xsd"
    version="2.1">
        <jxb:globalBindings>
            <jxb:javaType xmlType="xs:integer" name="java.lang.Integer" />
        </jxb:globalBindings>
        <jxb:bindings schemaLocation="../xsd/myService.xsd">
            <jxb:bindings node="//xs:simpleType[@name='DayOfWeek']/xs:restriction/xs:enumeration[@value='1']">
                <jxb:typesafeEnumMember name="Monday" />
            </jxb:bindings>
            <jxb:bindings node="//xs:simpleType[@name='DayOfWeek']/xs:restriction/xs:enumeration[@value='2']">
                <jxb:typesafeEnumMember name="Tuesday" />
            </jxb:bindings>
        </jxb:bindings>
    </jxb:bindings>

Following is an example xsd (I just handcrafted it and may contain error so be aware)

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:tns="http://my.service.com/model"
    targetNamespace="http://my.service.com/model" elementFormDefault="qualified">

    <xs:element name="MyElement">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="field1" type="xs:integer"/>
                <xs:element name="field2" type="tns:DayOfWeek"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:simpleType name="DayOfWeek">
        <xs:restriction base="xs:string">
            <xs:enumeration value="1" />
            <xs:enumeration value="2" />
        </xs:restriction>
    </xs:simpleType>
</xs:schema>

Above will create classes something like this (I am not including toString, hash, equals and other functions to keep it slim)

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "MyElement", propOrder = {
    "field1",
    "field2"
})
public class MyElement implements Equals2, HashCode2, ToString2
{
    @XmlElement(required = true, type = String.class)
    @XmlJavaTypeAdapter(Adapter1 .class)
    @XmlSchemaType(name = "integer")
    protected Integer field1;
    
    @XmlElement(name = "DayOfWeek", required = true)
    @XmlSchemaType(name = "string")
    protected DayOfWeek field2;

    public Integer getField1() {
        return field1;
    }
    public DayOfWeek getField2() {
        return field2;
    }    
}

and also note the enum

@XmlType(name = "DayOfWeek")
@XmlEnum
public enum DayOfWeek {

    @XmlEnumValue("1")
    Monday("1"),
    @XmlEnumValue("2")
    Tuesday("2");
    private final String value;

    DayOfWeek(String v) {
        value = v;
    }

    public String value() {
        return value;
    }

    public static DayOfWeek fromValue(String v) {
        for (DayOfWeek c: DayOfWeek.values()) {
            if (c.value.equals(v)) {
                return c;
            }
        }
        throw new IllegalArgumentException(v);
    }
}
0
Martin On

For global overrides use this in your bindings file:

<bindings xmlns="http://java.sun.com/xml/ns/jaxb" version="2.1"
          xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <globalBindings>
        <javaType xmlType="xs:integer" name="java.lang.Integer"/> 
    </globalBindings>
</bindings>

To override specific type usages use something like this:

<bindings xmlns="http://java.sun.com/xml/ns/jaxb" version="2.1"
          xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <bindings schemaLocation="../xsd/foo.xsd">
        <bindings node="//xs:complexType[@name='bar']/xs:attribute[@name='id']">
            <property>
                <baseType>
                    <javaType name="java.lang.Integer"/>
                </baseType>
            </property>
        </bindings>
    </bindings>
</bindings>

By using the schemaLocation and the XPath expression in the node attribute you can restrict the override as needed.

1
Matteo A. Sorrenti On

For attribute:

<xs:attribute name="id" type="xs:int" />

For element:

<xs:element name="id" type="xs:int" minOccurs="0" />