zwei
zwei

Reputation: 57

JAXB forcing namespace URI - why does it expect certain namespace even when it was not defined?

I have mystery when trying to unmashall XML document:

unexpected element (uri:"http://www.xxx/xsd/ems/batchreq", local:"batchParams"). Expected elements are <{}msgCollection>,<{}batchParams>]

Element should not come with namespace - it does not have in in xml, nor in java class, yet it seems that when it is parsed, it gets namespace uri - and for bigger mystery, elements that have namespace do not seem to expect it.

Why?

Adding namespace to @XmlElement helps, but then it seems that it would have to be defined for every single element - that is unacceptable solution. Why is namespace not inherited by child elements?

Root class is:

@XmlRootElement(name = "batch", namespace = "http://www.xxx/xsd/ems/batchreq")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "batch", namespace = "http://www.xxx/xsd/ems/batchreq", propOrder = { "batchParams", "msgCollection" })
public class Batch {

    @XmlAttribute(required = true)
    private String batchName;


    @XmlElement(name = "batchParams", required = true)
    private BatchParams batchParams;

    @XmlElement(name = "msgCollection", required = true)
    private Msgs msgCollection;
...

Offending member class is:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "batchParams", namespace = "http://www.xxx/xsd/ems/batchreq", propOrder = { "msgCount", "dateCreated" })
public class BatchParams {

    @XmlElement()
    private Long msgCount;

    @XmlElement()
    private Date dateCreated;

    public Long getMsgCount() {
...

Xml document is:

<?xml version="1.0" encoding="UTF-8"?>
<batch xmlns="http://www.xxx/xsd/ems/batchreq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.xxx/xsd/ems/batchreq ./ems_msg_batchreq.xsd" batchName="d" msgType="ems_sendemsg_batchreq" sourceSystem="1">
  <batchParams>
    <msgCount>1</msgCount>
    <dateCreated>2014-12-03T12:00:00</dateCreated>
  </batchParams>
  <msgCollection xmlns="http://www.xxx/xsd/ems/req">
    <msg msgType="ems_sendemsg_msg" sourceSystem="1" dataSourceSystem="1">
...
    </msg>
  </msgCollection>
</batch>

Upvotes: 1

Views: 1139

Answers (1)

bdoughan
bdoughan

Reputation: 148977

Element should not come with namespace - it does not have in in xml, nor in java class, yet it seems that when it is parsed, it gets namespace uri - and for bigger mystery, elements that have namespace do not seem to expect it.

The XML in your question declares http://www.xxx/xsd/ems/batchreq as the default namespace. This means that each element in your XML that isn't assigned to a different namespace wil be part of that one.

<?xml version="1.0" encoding="UTF-8"?>
<batch xmlns="http://www.xxx/xsd/ems/batchreq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.xxx/xsd/ems/batchreq ./ems_msg_batchreq.xsd" batchName="d" msgType="ems_sendemsg_batchreq" sourceSystem="1">
  <batchParams>
    <msgCount>1</msgCount>
    <dateCreated>2014-12-03T12:00:00</dateCreated>
  </batchParams>
  <msgCollection xmlns="http://www.xxx/xsd/ems/req">
    <msg msgType="ems_sendemsg_msg" sourceSystem="1" dataSourceSystem="1">
...
    </msg>
  </msgCollection>
</batch>

Adding namespace to @XmlElement helps, but then it seems that it would have to be defined for every single element - that is unacceptable solution.

You can use the package level @XmlSchema annotation to map a default namespace qualification. This goes on a source file called package-info.java with only the content shown below. You will need to change the package name to match your domain model.

@XmlSchema(
    namespace = "http://www.xxx/xsd/ems/batchreq",
    elementFormDefault = XmlNsForm.QUALIFIED)
package example;

import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;

Why is namespace not inherited by child elements?

Namespace specification in JAXB does get inherited, just not in the way that you tried.

  1. The package level @XmlSchema annotation provides a way to specify the default namespace that should be inherited by all elements corresponding to classes and properties within that package.
  2. The type level @XmlType annotation provides a way to specify the namespace inherited by all properties on this class. This over rides the namespace information specified on the @XmlSchema annotation.
  3. Finally namespace can be specified on the @XmlRootElement, @XmlElement annotations (and some others). The namespaces specified here are for that element only.

For More Information

I have written more about this use case on my blog:

Upvotes: 1

Related Questions