How to use namespaces in JAXB using EclipseLink MOXy?

eclipselink, java, jaxb, moxy

Solution

Below is an example of how you can map your use case with EclipseLink JAXB (MOXy).

package-info

First you need to set up the namespace information using the package level `@XmlSchema` annotation. We will leverage the namespace prefixes specified with the `@XmlNs` annotation later with the `@XmlPath` annotation.

@XmlSchema(
    namespace="http:// www.example.com/working/gtm",
    xmlns={
        @XmlNs(prefix="gtm", namespaceURI="http:// www.example.com/working/gtm")
    },
    elementFormDefault=XmlNsForm.UNQUALIFIED)
package forum10548370;

import javax.xml.bind.annotation.*; 

Message

The `@XmlPath` annotation is used to specify an XPath based mapping with MOXy. Since in the `@XmlSchema` annotation we specified `elementFormDefault=XmlNsForm.UNQUALIFIED`, the portions of the XPath without a prefix will not be namespace qualified.

package forum10548370;

import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlRootElement(name="message", namespace="")
@XmlAccessorType(XmlAccessType.FIELD)
public class Message {

    @XmlPath("gtm:header/someid/text()")
    private String id;

    @XmlPath("gtm:header/sometext/text()")
    private String text;

    @XmlElement(namespace="http:// www.example.com/working/gtm")
    private String customer;

}

jaxb.properties

To specify MOXy as your JAXB provider you need to add a file called `jaxb.properties` in the same package as your domain model with the following entry (see http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html):

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

Demo

package forum10548370;

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Message.class);

        File xml = new File("src/forum10548370/input.xml");
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Message message = (Message) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(message, System.out);
    }

}

input.xml/Output

<?xml version="1.0" encoding="UTF-8"?>
<message xmlns:gtm="http:// www.example.com/working/gtm">
   <gtm:header>
      <someid></someid>
      <sometext></sometext>
   </gtm:header>
   <gtm:customer>0123456789</gtm:customer>
</message>

For More Information

- http://blog.bdoughan.com/2010/09/xpath-based-mapping-geocode-example.html

- http://blog.bdoughan.com/2010/08/jaxb-namespaces.html

Problem

I have an XML like: ``` <message xmlns:gtm="http:// www.example.com/working/gtm"> <gtm:header> <someid></someid> <sometext></sometext> </gtm:header> <gtm:customer>0123456789</gtm:customer> </message> ``` I am using `@XmlPath` mappings. but when I run the code I get this error: ``` Exception [EclipseLink-25016] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.XMLMarshalException Exception Description: A namespace for the prefix gtm:header was not found in the namespace resolver. ``` I wonder what am I missing?

Original source