Facing issues with unmarshalling using JAXB. I need to use multiple namespaces. The Java classes are generated for the XSDs provided by a third party. So I do not want to specify the namespace at XMLRootElement in the Java classes and do not want to manually change multiple classes.
The marshalling logic as below:
private <R extends BasicResponseType, T extends BasicRequestType> R doPost(T request, String requestname) throws Exception {
if (jaxbContext == null)
jaxbContext = JAXBContext.newInstance(TokenRequest.class, TokenResponse.class,
BasicResponseType.class, GeneralErrorResponse.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
logXML(marshaller, request);
// POST to baseURL/requestname and show response
HttpURLConnection conn = openConnection("/" + requestname);
OutputStream os = conn.getOutputStream();
marshaller.marshal(request, os);
os.flush();
// Normaler Output oder Error liefern, je nach HTTP Response
InputStream is = null;
boolean ok = true;
if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
is = conn.getErrorStream();
ok = false;
} else {
is = conn.getInputStream();
}
R response = (R) unmarshaller.unmarshal(new StreamSource(is));
is.close();
conn.disconnect();
logXML(marshaller, response);
if (ok) {
return response;
} else {
throw new Exception(getMessages((GeneralErrorResponse) response));
}
}
The xmlelement class TokenRequest.java
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "")
@XmlRootElement(name = "TokenRequest")
public class TokenRequest
extends BasicInRequestType{ }
BasicInRequestType.java
package exp._3_0.api;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "BasicInRequestType", propOrder = {
"software"
})
@XmlSeeAlso({
TokenRequest.class
})
public class BasicInRequestType
extends BasicRequestType {
@XmlElement(required = true)
protected SoftwareType software;
/**
* Gets the value of the software property.
*
* @return
* possible object is
* {@link SoftwareType }
*
*/
public SoftwareType getSoftware() {
return software;
}
/**
* Sets the value of the software property.
*
* @param value
* allowed object is
* {@link SoftwareType }
*
*/
public void setSoftware(SoftwareType value) {
this.software = value;
}}
BasicRequestType.java
package exp._3_0.api;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
propOrder = {
"header",
"user"
})
@XmlSeeAlso({
BasicInRequestType.class
})
public class BasicRequestType {
@XmlElement(required = true)
protected BasicHeaderType header;
@XmlElement(required = true)
protected UserHeaderType user;
@XmlType(name = "BasicRequestType", namespace = "http://foo/1.0/common",
/**
* Gets the value of the header property.
*
* @return
* possible object is
* {@link BasicHeaderType }
*
*/
public BasicHeaderType getHeader() {
return header;
}
/**
* Sets the value of the header property.
*
* @param value
* allowed object is
* {@link BasicHeaderType }
*
*/
public void setHeader(BasicHeaderType value) {
this.header = value;
}
/**
* Gets the value of the user property.
*
* @return
* possible object is
* {@link UserHeaderType }
*
*/
public UserHeaderType getUser() {
return user;
}
/**
* Sets the value of the user property.
*
* @param value
* allowed object is
* {@link UserHeaderType }
*
*/
public void setUser(UserHeaderType value) {
this.user = value;
}}
XML Output :
<TokenRequest xmlns:common="http://foo/1.0/common" xmlns:ns4="http://foo/3.0/api" xmlns:base="http://foo/3.0/base">
<common:header>
<common:requestId></common:requestId>
<common:timestamp></common:timestamp>
</common:header>
<common:user>
<common:login></common:login>
<common:passwordHash></common:passwordHash>
</common:user>
<software>
<softwareId></softwareId>
<softwareName></softwareName>
</software>
</TokenRequest>
I have specifies the prefix in package-info.java
@javax.xml.bind.annotation.XmlSchema(elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED, xmlns = {
@javax.xml.bind.annotation.XmlNs(namespaceURI = "http://foo/3.0/api", prefix = ""),
@javax.xml.bind.annotation.XmlNs(namespaceURI = "http://foo/3.0/base", prefix = "base"),
@javax.xml.bind.annotation.XmlNs(namespaceURI = "http://foo/1.0/common", prefix = "common") })
package exp._3_0.api;
The TokenRequest element actually refers to the namespace = "http://foo/3.0/api". In the xml output the TokenRequest does not have the any prefix which is correct but the xmlns is set to ns4 which is causing the below error.
Request body contains on line: [1] and column: [182] error: [unexpected element (uri:"", local:"TokenRequest"). Expected elements are <{http://foo/3.0/api}TokenRequest>]
Even after specifying the prefix = "" for namespace "http://foo/3.0/api" in package-info, in the output its still appending as ns4. Please help how to fix remove the ns4.
@XmlRootElement(name = "TokenRequest", namespace="http://foo/3.0/api") public class TokenRequest ...
(?) (and parents!?) – xerx593namespace="http://foo/3.0/api"
to your@XmlSchema
annotation. In the current formTokenRequest
's namespace in""
(i.e. no namespace). – Piotr P. Karwaszpackage-info.java
? All we can see is@XmlNs(namespaceURI = "http://foo/3.0/api", prefix = "")
, which only sets the preferred prefix forhttp://foo/3.0/api
. There is nonamespace="..."
attribute (which sets the namespace for the whole package). – Piotr P. Karwasz