MOXy creates different namespace prefix than JAXB RI

566 views Asked by At

I am trying to switch from JAXB RI 2.2.7 to MOXy JAXB 2.5.2 implementation. I notice the following difference in namespace and prefix in the generated XML output snippet:

JAXB RI:

<xbrli:xbrl xmlns:xbrli="http://www.xbrl.org/2003/instance" xmlns:bd-algemeen="http://www.nltaxonomie.nl/7.0/basis/bd/items/bd-algemeen" xmlns:iso4217="http://www.xbrl.org/2003/iso4217">
   <bd-algemeen:OperatingSystem contextRef="cc_131">W</bd-algemeen:OperatingSystem>
   <xbrli:unit id="uu_692">
        <xbrli:measure>iso4217:EUR</xbrli:measure>
    </xbrli:unit>
</xbrli:xbrl>

MOXy:

<xbrli:xbrl xmlns:xbrli="http://www.xbrl.org/2003/instance" xmlns:bd-algemeen="http://www.nltaxonomie.nl/7.0/basis/bd/items/bd-algemeen">
  <bd-algemeen:OperatingSystem contextRef="cc_131">W</bd-algemeen:OperatingSystem>
  <xbrli:unit id="uu_662">
    <xbrli:measure xmlns:ns0="http://www.xbrl.org/2003/iso4217">ns0:EUR</xbrli:measure>
   </xbrli:unit>
</xbrli:xbrl>

1) How do I configure MOXy to output the same as the RI? The MOXy output is valid but The XML (actually XBRL) document I create must have predefined prefixes.

2) I use a an instance of "com.sun.xml.bind.marshaller.NamespacePrefixMapper" to indicate the prefix that should be used. However MOXy doesn't call this in case of the iso4217 namespace, why (I debugged the MOXy namespace resolver but got a bit lost ;)? BTW: the prefixMapper is used by Moxy for other namespaces (like the "xbrli"), but not for this iso4217, what is the difference?

I haved added "bd-algemeen", as the prefix mapper is called for the prefix "bd-algemeen". This mapping doesn't use QName as used by iso4217.

3) I tried the @XmlSchema annotation in the pacakage-info.java in the generated iso4217 pacakge, to define the prefix, but no luck, neither do I want to use this as it concerns generated code that is easily overwritten.

The domain object:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = { "divide", "measures" })
@XmlRootElement(name = "unit")
public class Unit {
    protected Divide divide;

    @XmlElement(name = "measure")
    protected List<QName> measures;
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = { "operatingSystem"})
public static class TaxDataBedrijf  {

   @XmlElement(name = "OperatingSystem", namespace = "http://www.nltaxonomie.nl/7.0/basis/bd/items/bd-algemeen")
   protected Astring1ItemType operatingSystem;

The creation of the Unit instance:

final Unit item = new Unit();
item.getMeasures().add(new QName("http://www.xbrl.org/2003/iso4217", "EUR", "iso4217"));

taxData = new TaxDataBedrijf();
taxData.setOperatingSystem(createOperatingSystem(context, 'W'));

I thought it might be because of the QName usage, but this is also directly used in other places and is used correctly. For example, Moxy is able to generate this snippet:

<xbrli:xbrl xmlns:xbrli="http://www.xbrl.org/2003/instance" xmlns:bd-domains="http://www.nltaxonomie.nl/7.0/basis/bd/domains/bd-domains" xmlns:bd-axes="http://www.nltaxonomie.nl/7.0/domein/bd/axes/bd-axes">
  <xbrli:scenario>
     <xbrldi:explicitMember dimension="bd-axes:TimeDimension">bd-domains:Current</xbrldi:explicitMember>
  </xbrli:scenario>
</xbrli:xbrl>

And the corresponding java binding:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = { "value" })
@XmlRootElement(name = "explicitMember")
public class ExplicitMember {

    @XmlValue
    protected QName value;

    @XmlAttribute(name = "dimension")
    protected QName dimension;
}

And it's creation:

final ExplicitMember item = new ExplicitMember();
item.setDimension(new QName("http://www.nltaxonomie.nl/7.0/domein/bd/axes/bd-axes", "TimeDimension"));
item.setValue(new QName("http://www.nltaxonomie.nl/7.0/basis/bd/domains/bd-domains", "Current"));

Please some advice on how to solve this such that I can use MOXy instead of the RI (where to look in the Moxy code maybe?).

2

There are 2 answers

0
edbras On BEST ANSWER

I got it working with the correct namespace notation, that is, that it generates:

<xbrli:unit id="uu_382">
     <xbrli:measure>iso4217:EUR</xbrli:measure>
</xbrli:unit>

I spend some (lot ;) time debugging the Moxy code and comparing the namespaces that were correctly used and discovered that the ObjectFactory for the above snippet doesn't contain any @XmlElementDecl annotation like the ones that were working. When adding this, it works, namely:

private static final QName EUR_QNAME = new QName("http://www.xbrl.org/2003/iso4217", "EUR", "iso4217");

@XmlElementDecl(namespace = "http://www.xbrl.org/2003/iso4217", name = "EUR", substitutionHeadNamespace = "http://www.xbrl.org/2003/instance", substitutionHeadName = "item")
public JAXBElement<EUR> createEURO() {
    return new JAXBElement<EUR>(EUR_QNAME, EUR.class, null, createEUR());
}

I noticed that when the Xbrl (root tag) mapping is created, it will loop through the properties, and one of these properties is the property "itemsAndTuplesAndContexts". It then loop through the associated reference elements (Moxy code: MappingGenerator.generateMappingForReferenceProperty(..)) and will add them to it's namespace resolver map with generated prefix, that is stored in it's descriptor. During marshalling, it will use the prefix mapper to map it's stored namespaces. Because I added @XmlElementDecl declaration for the iso4217 element, it's found a referencing Element, and as such it's added to the namepace resolver map of the Xbrl root element, and as such used during marshalling in the prefix mapper.

A few questions I don't have very clear:

  1. Why is this @XmlElementDecl required in Moxy, and not by the JaxB RI?
  2. Why wasn't this @XmlElementDecl elements generated during the code generation with XJC?
  3. @Blaise: do you think it's a bug ?

property "itemsAndTuplesAndContexts" declaration:

@XmlElementRefs({ @XmlElementRef(name = "unit", namespace = "http://www.xbrl.org/2003/instance", type = Unit.class),
  @XmlElementRef(name = "context", namespace = "http://www.xbrl.org/2003/instance", type = Context.class),
  @XmlElementRef(name = "item", namespace = "http://www.xbrl.org/2003/instance", type = JAXBElement.class),
  @XmlElementRef(name = "tuple", namespace = "http://www.xbrl.org/2003/instance", type = JAXBElement.class),
  @XmlElementRef(name = "footnoteLink", namespace = "http://www.xbrl.org/2003/linkbase", type = JAXBElement.class) })
    protected List<Object> itemsAndTuplesAndContexts;
1
bdoughan On

The behaviour you are seeing is a bug, I have opened up the following issue for it: