Search code examples
javajaxbeclipselinkmoxy

JAXB/MOXy: Wrong namespace for element


I am using MOXy and classes which belong to different namespaces, but MOXy always adds the wrong namespace to the referenced object. Why is this simple example not working as expected?

AtomLink.java:

package org.atom;

@XmlAccessorType(XmlAccessType.NONE)
public class AtomLink {

    @XmlAttribute
    protected String rel;
    @XmlAttribute(required = true)
    @XmlSchemaType(name = "anyURI")
    protected String href;

    public AtomLink() {
    }

    public AtomLink(String rel, String href) {
        this.rel = rel;
        this.href = href;
    }

}

Person.java

package org.example;

import org.atom.AtomLink;

@XmlRootElement(name = "person")
@XmlAccessorType(XmlAccessType.NONE)
public class Person {

    @XmlElement
    protected String name;
    @XmlElement
    protected AtomLink link;

    public Person() {
    }

    public Person(String name, AtomLink link) {
        this.name = name;
        this.link = link;
    }

}

package-info.java

@XmlSchema(namespace = "http://www.w3.org/2005/Atom", xmlns={
    @XmlNs(namespaceURI = "http://www.w3.org/2005/Atom", prefix = "atom")}, elementFormDefault = XmlNsForm.QUALIFIED, attributeFormDefault = XmlNsForm.QUALIFIED) 
package org.atom;

package-info.java

@XmlSchema(namespace = "http://www.test.org", xmlns={
    @XmlNs(namespaceURI = "http://www.test.org", prefix = "test")}, elementFormDefault = XmlNsForm.QUALIFIED, attributeFormDefault = XmlNsForm.UNQUALIFIED) 
package org.example;

Test-Code:

Person person = new Person("Test", new AtomLink("self", "http://www.test.org/person/Test"));
try {
    JAXBContext context = JAXBContextFactory.createContext(new Class[] { Person.class }, null);
    Marshaller marshaller = context.createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    marshaller.marshal(person, System.out);
} catch (JAXBException e) {
    e.printStackTrace();
}

The result:

<?xml version="1.0" encoding="UTF-8"?>
<test:person xmlns:atom="http://www.w3.org/2005/Atom" xmlns:test="http://www.test.org">
    <test:name>Test</test:name>
    <test:link atom:rel="self" atom:href="http://www.test.org/person/Test"/>
</test:person>

But I am expecting:

...
    <atom:link atom:rel="self" atom:href="http://www.test.org/person/Test"/>
...

Why is MOXy not recognising that the class AtomLink belongs to a different namespace? As you can see, only the element's namespace is wrong, but its attributes are assigned to the right namespace.

Update

I have done the following changes as proposed. The classes look as follows:

AtomLink.java

@XmlRootElement(name = "link")
@XmlAccessorType(XmlAccessType.NONE)
public class AtomLink {

    @XmlAttribute
    protected String rel;
    @XmlAttribute(required = true)
    @XmlSchemaType(name = "anyURI")
    protected String href;

    public AtomLink() {
    }

}

Person.java:

@XmlRootElement(name = "person")
@XmlAccessorType(XmlAccessType.NONE)
public class Person {

    @XmlElement
    private String name;
    @XmlElementRef
    private AtomLink link;

    public Person() {
    }

    public Person(String name, AtomLink link) {
        this.name = name;
        this.link = link;
    }

}

The result is an invalid XML document, which defines n0 as the targetNamespace for the link element, but its attributes are assigned to my atom-prefix.

<?xml version="1.0" encoding="UTF-8"?>
<test:person xmlns:test="http://www.test.org" xmlns:ns0="http://www.w3.org/2005/Atom>
    <test:name>Test</test:name>
    <ns0:link atom:rel="self" atom:href="http://www.test.org/person/Test"/>
</test:person>

Extending the "http://www.test.org" namespace with an atom-entry is not a solution, because that results always in a namespace declaration even if no atom-element is present in the XML document.

Update2

If I use the Java internal JAXB-Implementation everythings works as expected... There must be an error in the MOXy implementation.


Solution

  • What you were experiencing was a bug in MOXy that has now been fixed in the EclipseLink 2.4.2 and 2.5.0 streams. You can download a nightly build from the following location as of February 13th 2013.

    In terms of the correct mapping see the answer given by Michał Politowski.