(FTR, this is going to be a bit tricky since I'm using Blogger and thus don't have the best inline XML-and-code support). (Version notation: This is all valid for both 2.0 and 2.1 versions [up through 2.1.8], but is not valid for 1.x JAXB).
The Problem: Required Strings
Assume you have an XSD
complexType
which contains two elements:<xs:element name="foo" type="xs:double"/>
<xs:element name="bar" type="xs:string"/>
In your XJC-generated Java code, both the
Foo
and Bar
properties will be annotated with an @XmlElement(required=true)
annotation. In addition, Foo
will be declared as a double
rather than a Double
, so you'll always have a value of some form in the generated class. The problem is with bar
.bar
will be declared without any default value whatsoever (unless you're using the JAXB Default Value plugin). Even worse, if you run through a marshall/unmarshall pass on objects or XML that lack a bar
element at all, it works entirely fine (even with the default value plugin) and you'll be just fine consuming data without a bar
element whatsoever. So you can quite merrily generate XML which doesn't adhere to your XSD, and consume XML which also doesn't. (for the bar
element, you'll always have the default value of 0.0 if the XML you're unmarshalling lacks the element).In general, I'd consider code which is doing this to be bug-ridden, and in need of fixing: if your application knows that you need a
bar
, why aren't you adding one to your objects before marshalling them? Conversely, you should always try to make do with whatever crap someone barfs at you over the wire if you can (Postel's Law and all that). But it's still confusing behavior.Workaround One: Make It An Attribute
If you have control over your schema, making it an XML attribute will solve this problem immediately. They're handled differently by JAXB, so it always works as you'd expect.
Workaround Two: Explicitly Validate
At runtime, for performance reasons, JAXB by default doesn't actually have access to your XSD. All it works with are the (generated|hand-written) Java files with annotations (this is a difference to the way the old XMLBeans worked, where it would pre-process a binary form of your XSD for runtime validation). You can make JAXB perform strict validation, but for performance reasons it won't by default.
The problem is that it means that you have to ship your XSD files with your application and use SchemaFactory out of the
javax.xml.validation
package to load up the XSD into an in-memory Schema
instance, and pass that to your Marshaller
and Unmarshaller
's setSchema
methods. It'll slow you down, but you'll be guaranteed to be valid.A reasonable option at least to me would be to validate in debug cycles (using the assertions system) and turn it off when you know your applications actually all work together happily.
Reader Note: This was written largely because googling this topic never came up with any actual explaination. Therefore, I wanted this to be keyword google friendly. And since I was going to have to document this for other people at my company, I figured I'd document it for the world.