I am totally a newbie to to JAXB architecture. But here is what i am trying to do do and where is am stuck in a nutshell.
I am creating a web application where the client will first register his xsd and then subsequently send his xml/json data as per the xsd.
For the registration of the xsd, i am using XJC (not as a maven plugin, but instead from java code itself :
SchemaCompiler sc = XJC.createSchemaCompiler();
File schemaFile = new File(schemaPath);
InputSource is = new InputSource(new FileInputStream(schemaFile));
is.setSystemId(schemaFile.getAbsolutePath());
sc.parseSchema(is);
S2JJAXBModel model = sc.bind();
JCodeModel jCodeModel = model.generateCode(null, null);
jCodeModel.build(new File(outputDirectory));
By XSD looks like:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Metadata" type="Metadata" />
<xsd:complexType name="Metadata">
<xsd:sequence>
<xsd:element name="MicroscopeStagePosition"
type="MicroscopeStagePosition" maxOccurs="1" minOccurs="1">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="MicroscopeStagePosition">
<xsd:sequence>
<xsd:element name="Start" type="xsd:string"/>
<xsd:element name="End" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
I am creating the JAXB annoted POJO classes from the above and the 2 classes created are :
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Metadata", propOrder = {
"microscopeStagePosition"
})
public class Metadata {
@XmlElement(name = "MicroscopeStagePosition", required = true)
protected MicroscopeStagePosition microscopeStagePosition;
public MicroscopeStagePosition getMicroscopeStagePosition() {
return microscopeStagePosition;
}
public void setMicroscopeStagePosition(MicroscopeStagePosition value) {
this.microscopeStagePosition = value;
}
}
And
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "MicroscopeStagePosition", propOrder = {
"start",
"end"
})
public class MicroscopeStagePosition {
@XmlElement(name = "Start", required = true)
protected String start;
@XmlElement(name = "End", required = true)
protected String end;
public String getStart() {
return start;
}
public void setStart(String value) {
this.start = value;
}
public String getEnd() {
return end;
}
public void setEnd(String value) {
this.end = value;
}
}
Now my idea to have a generic annotated class that will wrapper around this above classes that will be created in real time (this class is created in real and hence can have anything that needs to be).
The problem is that i do not which xsd will come and hence the rootelement is not going to help. So i thought creating a wrapper around the created JAXB class and then only deal with this one wrapper class in all API.
i have created the below class in real time :
public class MyModel {
@XmlElement(required = true)
protected Metadata Metadata;
@XmlElement(required = true)
protected MicroscopeStagePosition MicroscopeStagePosition;
}
Is it possible to Unmarshell a incoming XML based on this wrapper class . Note the incoming XML cannot be forced to have the root element of MyModel in it. So i try to create root JAXBElement and then assign it to the wrapper class:
MyModel je = new MyModel();
JAXBContext jaxbContext = JAXBContextFactory.createContext(new Class[] {MyModel.class}, null);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
InputStream is = new ByteArrayInputStream(sIncomingMetadataXML.getBytes());
JAXBElement<MyModel> root = jaxbUnmarshaller.unmarshal(new StreamSource(
is), MyModel.class);
je = root.getValue();
if i annotate MyModel with @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) and return je from my api its a null child object xml :
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<MyModel/>
and if not there is an error :
A message body writer for Java class aand MIME media type application/xml was not found.
So can i create a wrapper class like above and if so how?, or have i missed totally something here