I have re-formatted the question to hopefully make my intentions clearer.
Architecture
I\'m writing some web services that I will be publishing
For
@XmlElementRef(name="foo", required=false)
protected JAXBElement foo;
An absent node in the document will correspond to this field being null. An XML element present in the document with xsi:nil="true" will correspond to the value being an instance of JAXBElement with a value of null.
You can also provide an XML schema instead of having JAXB generate one using the location property on the package level @XmlSchema annotation.
@XmlSchema(
...
location="http://www.example.com/schema/root.xsd")
package forum19665550;
import javax.xml.bind.annotation.XmlSchema;
Root
This is an object with two fields that can represent optional and nillable data.
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
@XmlElementRef(name="foo", required=false)
protected JAXBElement foo;
@XmlElementRef(name="bar", required=false)
protected JAXBElement bar;
}
ObjectFactory
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;
@XmlRegistry
public class ObjectFactory {
@XmlElementDecl(name="foo")
public JAXBElement createFoo(String foo) {
return new JAXBElement(new QName("foo"), String.class, foo);
}
@XmlElementDecl(name="bar")
public JAXBElement createBar(String bar) {
return new JAXBElement(new QName("bar"), String.class, bar);
}
}
Demo
The demo code below will investigate the differences in the values for foo and bar. You can use the JAXBIntrospector class to get the real value for an instance of JAXBElement. There is a bug in EclipseLink JAXB (MOXy) related to unmarshalling an instance of JAXBElement wrapping a null value (see: http://bugs.eclipse.org/420746).
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class, ObjectFactory.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum19665550/input.xml");
Root root = (Root) unmarshaller.unmarshal(xml);
System.out.println("foo was set: " + (root.foo != null));
System.out.println("bar was set: " + (root.bar != null));
System.out.println("foo value: " + root.foo);
System.out.println("bar value: " + root.bar);
System.out.println("foo unwrapped value: " + JAXBIntrospector.getValue(root.foo));
System.out.println("bar unwrapped value: " + JAXBIntrospector.getValue(root.bar));
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
input.xml/Output
In the resulting output we see that we can differentiate between an element being absent from the document and an element with `xsi:nil="true" and still have the resulting value be null.
foo was set: false
bar was set: true
foo value: null
bar value: javax.xml.bind.JAXBElement@4af42ea0
foo unwrapped value: null
bar unwrapped value: null
GenerateSchema
Below is some JAXB code that will generate an XML Schema from the annotated model.
import java.io.IOException;
import javax.xml.bind.*;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamResult;
public class GenerateSchema {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
jc.generateSchema(new SchemaOutputResolver() {
@Override
public Result createOutput(String namespaceUri,
String suggestedFileName) throws IOException {
StreamResult result = new StreamResult(System.out);
result.setSystemId(suggestedFileName);
return result;
}
});
}
}
Output
Here is the resulting XML Schema. You are correct that it doesn't indicate that the foo and bar elements are nillable.
Instead of having JAXB derive an XML Schema from your model, you can point to your existing one that will contain more information.
package-info
This is done by specifying the location property on the package level @XmlSchema annotation.
@XmlSchema(
...
location="http://www.example.com/schema/root.xsd")
package forum19665550;
import javax.xml.bind.annotation.XmlSchema;