8

Given the following example xsd snippet:

< xs:attribute name="SEGMENT"  default="" use="optional" type="xs:string"/ >

when xjc generates the class containing the SEGMENT bean attribute, the following getter is auto-generated:

public String getSEGMENT() {
    if (segment == null) {
        return "";
    } else {
        return segment;
    }
}

My question is how do you get it do the same for xs:element objects? In other words, given the following xsd snippet:

< xs:element name="NAME" default="" type="xs:string"/ >

I want to know if I can get xjc to generate the following:

public String getNAME() {
    if (name == null) {
        return "";
    } else {
        return name;
    }
}

How can this be done?

Cat
  • 66,919
  • 24
  • 133
  • 141
java luva
  • 111
  • 1
  • 2

1 Answers1

2

JAXB doesn't generate the same code for an element with default value as it does for an attribute with default value because the XML schema differentiates between element and attribute defaults:

Default values of both attributes and elements are declared using the default attribute, although this attribute has a slightly different consequence in each case. When an attribute is declared with a default value, the value of the attribute is whatever value appears as the attribute's value in an instance document; if the attribute does not appear in the instance document, the schema processor provides the attribute with a value equal to that of the default attribute. Note that default values for attributes only make sense if the attributes themselves are optional, and so it is an error to specify both a default value and anything other than a value of optional for use.

The schema processor treats defaulted elements slightly differently. When an element is declared with a default value, the value of the element is whatever value appears as the element's content in the instance document; if the element appears without any content, the schema processor provides the element with a value equal to that of the default attribute. However, if the element does not appear in the instance document, the schema processor does not provide the element at all. In summary, the differences between element and attribute defaults can be stated as: Default attribute values apply when attributes are missing, and default element values apply when elements are empty.

You can always count on the default value for a missing attribute (from here the special getter) but there is a catch with a missing element value.

Nonetheless, when you unmarshall an instance, the unmarshaller knows how to handle the default value. See here for details:

XJC won't add the getter code or initialize the fields with the default value, so if you need the "null safe check" you can either add it yourself manually after the code is generated by XJC or try to use some plugin to do it automatically:

Community
  • 1
  • 1
Bogdan
  • 23,890
  • 3
  • 69
  • 61
  • A field initializer would definitely be appropriate. The question now is How do I get xjc to add the empty String initializer to every String in every class? Perhaps in a separate bindings file? – java luva Dec 17 '12 at 23:03
  • @java luva: I added some more details to my answer and also found some plugins that look interesting. See if it helps. – Bogdan Dec 18 '12 at 21:16
  • Thanks for the additional info. I'm having one problem though. The links you sent involve setting up a maven or ant task. I don't use maven. And the problem when setting up the ant task is I'm getting a Linkage error stating that different classes are being loaded with the same name. The problem, I believe, is java 1.6 has xjc built in, and by adding jaxb-xjc-2.1.9.jar to my xjc taskdef classpath, they are clashing. My question is how can either get the ant script to ignore 1.6 (my JAVA_HOME is set to that) and use my taskdef classpath, or reference the 1.6 xjc jar instead in the taskdef? – java luva Dec 20 '12 at 17:57
  • @java luva: Have you tried to isolate the task and call it by itself? Assuming you have all your jars and schema file in `c:\temp` try something like this: `java -jar c:\temp\jaxb-xjc.jar -classpath c:\temp\jaxb-api.jar;c:\temp\jaxb-impl.jar;c:\temp\jaxb2-default-value-1.1.jar -d c:\temp -extension -Xdefault-value -verbose c:\temp\YourSchema.xsd` – Bogdan Dec 23 '12 at 11:48
  • I appreciate your feedback but your last suggestion doesn't work. If you use the "-jar" option with java, the classpath is ignored. I can use the -classpath attribute all by itself, but you then have to add every jar required to that path (for ant as well) and I still get "Error: Main method not found in class com.sun.tools.xjc.XJCTask" when I do try to run without the -jar option – java luva Dec 31 '12 at 20:02
  • Also, just found out even if you use the java command as you suggested, unless it's jdk 1.5, you will still end up with the Linkage error because post jdk 1.5, the jaxb jars are loaded automatically when the java command is used. I don't want to use 1.5 for 1.6 code. So I'll guess I'll continue searching for an answer – java luva Dec 31 '12 at 20:17
  • What would be ideal would be to reference the jaxb jars that are included in 1.6 in my commands classpath. That way, I wouldn't have to use another jaxb-xjc.jar, and hence the Linkage errors would go away. Thanks again for your help – java luva Dec 31 '12 at 20:24