How can I use same JAXB class to marshall and unmarshall into different namespaces?



Note: this is with Java 7. Also, I am not using JAXB to generate anything from a schema. I only/merely want to use JAXB to deserialize pieces of existing SOAP messages. So the JAXB beans are "hand-written".


I am trying to deserialize the following XML with JAXB. I do not have access to it as a string. Rather, I am getting it as an org.w3c.dom.Element object:



<SynchInfo xmlns="urn:InitronSOAPService">
<HandshakeInfo>
<dnsName>foo.bar</dnsName>
<ip>1.2.3.4</ip>
<id>TheId</id>
<key>SomeKey</key>
<version>1.0</version>
</HandshakeInfo>
</SynchInfo>


And then I would like to marshall that back into a different Node that is part of a message belonging to a different namespace.


I first tried to write a HandshakeInfo class that didn't mention namespaces at all:



@XmlRootElement(name = "HandshakeInfo")
@XmlAccessorType(XmlAccessType.NONE)
final private static class HandshakeInfo
{
private String version;
private String id;
private String key;
private String ip;
private String dnsName;

public String getVersion() {
return version;
}

@XmlElement(name = "version")
public void setVersion(String version) {
this.version = version;
}

public String getId() {
return id;
}

@XmlElement(name = "id")
public void setId(String id) {
this.id = id;
}

public String getKey() {
return key;
}

@XmlElement(name = "key")
public void setKey(String key) {
this.key = key;
}

public String getIp() {
return ip;
}

@XmlElement(name = "ip")
public void setIp(String ip) {
this.ip = ip;
}

public String getDnsName() {
return dnsName;
}

@XmlElement(name = "dnsName")
public void setDnsName(String dnsName) {
this.dnsName = dnsName;
}
}


But when I used that to try to deserialize the Element object containing the HandshakeInfo element, I got the following exception:



javax.xml.bind.UnmarshalException: unexpected element (uri:"urn:InitronSOAPService", local:"HandshakeInfo"). Expected elements are <{}HandshakeInfo>
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:647)
...


So then I tried adding , namespace="urn:InitronSOAPService" to all the element and attribute (in this case none) annotations in the class. (Or, alternatively, used an @XmlSchema annotation in a package-info.java file.) That worked for deserializing that element in that namespace.


But when I tried to use the class to serialize into a different namespace I (not entirely unexpectedly) get stuff like this:



<SomeMessage xmlns="urn:differentNamespace">
<ns5:HandshakeInfo xmlns:ns5="urn:InitronSOAPService">
<ns5:dnsName>foo.bar</ns5:dnsName>
<ns5:ip>1.2.3.4</ns5:ip>
<ns5:id>TheId</ns5:id>
<ns5:key>SomeKey</ns5:key>
<ns5:version>1.0</ns5:version>
</ns5:HandshakeInfo>
</SomeMessage>


That's not what I want. I want the serialized thing to be part of the urn:differentNamespace.


So is there any way to use the same JAXB class in multiple namespaces? Or am I stuck with having to multiple copies of classes with each one annotated to be in the appropriate namespace?


I have seen some tricks using filters, etc. but those tricks seem to be assuming the XML is being read from or written to a stream or a file. Again, for both unmarshalling and marshalling I am working with org.w3c.dom.Element objects.


No comments:

Post a Comment