3

JAXB seems not to be able to set a fixed attribute value by default. Is this expected behavior, or something I'm doing wrong?

I have an xsd like:

<element name="AccountCategory" type="tns:Integer"></element>
<xs:complexType name="Integer">
    <xs:simpleContent>
        <xs:extension base="xs:int">
            <xs:attribute name="e-dtype" fixed="int"/>
        </xs:extension>
    </xs:simpleContent>
</xs:complexType>

Marshalling a java object created with new produces:

<AccountCategory>5</AccountCategory>

Java:

com.sample.Integer val = new com.sample.Integer();
val.setValue(5);
parentObject.setAccountCategory(val);

I am able to manually set the attribute value and it works fine. Also if I just reset it to its own value it also works. Seems like the marshaller is not using the get method when generating the XML?

val.setEDtype(val.getEDtype());

Results in

<AccountCategory e-dtype="int">5</AccountCategory>

The generated .java below:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Integer", propOrder = {
    "value"
})
public class Integer {

@XmlValue
protected int value;
@XmlAttribute(name = "e-dtype")
@XmlSchemaType(name = "anySimpleType")
protected String eDtype;

/**
 * Gets the value of the value property.
 * 
 */
public int getValue() {
    return value;
}

/**
 * Sets the value of the value property.
 * 
 */
public void setValue(int value) {
    this.value = value;
}

/**
 * Gets the value of the eDtype property.
 * 
 * @return
 *     possible object is
 *     {@link String }
 *     
 */
public String getEDtype() {
    if (eDtype == null) {
        return "int";
    } else {
        return eDtype;
    }
}

/**
 * Sets the value of the eDtype property.
 * 
 * @param value
 *     allowed object is
 *     {@link String }
 *     
 */
public void setEDtype(String value) {
    this.eDtype = value;
}
mrcrabs
  • 141
  • 2
  • 7

2 Answers2

4

Quoting XML Schema Part 0 - 2.2.1 Occurrence Constraints:

The fixed attribute is used in both attribute and element declarations to ensure that the attributes and elements are set to particular values. For example, po.xsd contains a declaration for the country attribute, which is declared with a fixed value US. This declaration means that the appearance of a country attribute in an instance document is optional (the default value of use is optional), although if the attribute does appear, its value must be US, and if the attribute does not appear, the schema processor will provide a country attribute with the value US.

So, as you can see, because your attribute is optional, it will not be generated unless you give a value, but that value must be int to be schema compliant.

Calling get will give you the default/fixed value, as it should,
and generation will omit attribute if not set, as it should.

And no, the marshaller is not using the get method, because @XmlAccessorType is XmlAccessType.FIELD.

Andreas
  • 154,647
  • 11
  • 152
  • 247
  • OK makes sense. But if I update the xsd to make the attribute required the same behavior persists. Something else I miss? – mrcrabs Oct 09 '15 at 07:08
  • Yes, you're missing the fact that XML *generation* doesn't enforce the XML schema, so you can generate XML that is not compliant with the schema, including occurrence constraints (`use`, `minOccurs`, `maxOccurs`). See section "Validation and Well-Formedness" in the [javadoc](http://docs.oracle.com/javase/7/docs/api/javax/xml/bind/Marshaller.html) – Andreas Oct 09 '15 at 07:15
  • 1
    Thanks. I was able to use fixedAttributeAsConstantProperty xjc binding to resolve the issue. – mrcrabs Oct 09 '15 at 07:45
3

Try with jaxb binding fixedAttributeAsConstantProperty like here.

<schema targetNamespace="https://stackoverflow.com/example" 
        xmlns="http://www.w3.org/2001/XMLSchema" 
        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
        xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
        jaxb:version="2.0">
  <annotation>
    <appinfo>
      <jaxb:globalBindings fixedAttributeAsConstantProperty="true" />
    </appinfo>
  </annotation>
  ...
</schema>
Community
  • 1
  • 1
gabrielgiussi
  • 9,245
  • 7
  • 41
  • 71