XML Support Photo

XML Support

The MessageBodyWriters and MessageBodyReaders are used by Jersey to parse the incoming requests and create outgoing responses for custom user representations. But it is more convenient and recommended to use XML representations. Jersey supports low-level data types used for direct manipulation and JAXB XML entities.

1. Low-Level XML Support

Jersey supports such low-level data types: StreamSource, SAXSource, DOMSource, and Document.  These types can be used as the return type or as a method parameter.

Example 1.1. Low-level XML support

The following example resource has methods, which consumes and produces mentioned above types.

@Path("exams")
public class ExamService {
    @POST
    @Path("StreamSource")
    public StreamSource getStreamSource(StreamSource streamSource) {
        return streamSource;
    }

    @POST
    @Path("SAXSource")
    public SAXSource getSAXSource(SAXSource saxSource) {
        return saxSource;
    }

    @POST
    @Path("DOMSource")
    public DOMSource getDOMSource(DOMSource domSource) {
        return domSource;
    }

    @POST
    @Path("Document")
    public Document getDocument(Document document) {
        return document;
    }
}

Example 1.2. Jersey Client

The code demonstrates how to write jersey client to test the getStreamSource method from the previous example. The type should be set to APPLICATION_XML_TYPE. It is post very simple XML - "<exam/>". The same approach can be used to test getSAXSource, getDOMSource, and getDocument methods.

Client client = Client.create();
WebResource resource = client.resource(".../exams/StreamSource");
String result = resource.type(MediaType.APPLICATION_XML_TYPE).post(String.class, "<exam/>");
System.out.println(result);

The result is:

<?xml version="1.0" encoding="UTF-8"?><exam/>

2. JAXB Support

Example 2.1. Exam class

We will use a simple Exam class in our resource, which has just id and name. If non-default XML representation is required, other JAXB annotations should be used.

@XmlRootElement
public class Exam {
    public int id;
    public String name;
}

Example 2.2. Resource

@Path("exam")
public class ExamService {
    @GET
    @Produces(MediaType.APPLICATION_XML)
    public Exam getExam() {
        Exam exam = new Exam();
        exam.id = 3;
        exam.name = "OCEJWSD6";
        return exam;
    }
}

 The resource can be accessed by GET .../exam. The result will be:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<exam>
   <id>3</id>
   <name>OCEJWSD6</name>
</exam>

Example 2.3. Jersey Client

 It is possible to use Jersey client to test our resource, which gives the possibility to receive Exam object instead of String:

Client client = Client.create();
WebResource resource = client.resource("../exam");
Exam result = resource.accept(MediaType.APPLICATION_XML_TYPE).get(Exam.class);

3. POJOs

If there isn't a possibility to add JAXB annotations to the source, JAXBElement class can be used.

Example 3.1. Resource using JAXBElement class

The resource has get and set methods:

@Path("exam")
public class ExamService {
    @GET
    @Produces(MediaType.APPLICATION_XML)
    public JAXBElement<Exam> getExam() {
        Exam exam = new Exam();
        exam.id = 3;
        exam.name = "OCEJWSD6";
        return new JAXBElement<Exam>(new QName("exam"), Exam.class, exam);
    }

    @POST
    @Consumes(MediaType.APPLICATION_XML)
    public void setExam(JAXBElement<Exam> exam) {
        System.out.println("setExam " + exam.getValue().name);
        System.out.println("setExam " + exam.getValue().id);
    }
}

The resource can be accessed by GET .../exam. The result will be:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<exam>
   <id>3</id>
   <name>OCEJWSD6</name>
</exam>

Example 3.2. Jersey Client to test Resource with JAXBElement class

 The code shows how to test get and post requests of the resource from the previous example using the Jersey client:

Client client = Client.create();
WebResource resource = client.resource(".../exam");
// GET
GenericType<JAXBElement<Exam>> examType = new GenericType<JAXBElement<Exam>>() {};
Exam exam1 =  resource.accept(MediaType.APPLICATION_XML_TYPE).get(examType).getValue();
System.out.println(exam1.name);
System.out.println(exam1.id);

// POST
Exam exam2 = new Exam();
exam2.id = 1;
exam2.name = "OCJP 6";
resource.post(new JAXBElement<Exam>(new QName("exam"), Exam.class, exam2));

4. Using custom JAXBContext

Sometimes it is necessary to use custom JAXBContext to set some specific things, for example, to set different classloaders. Creating JAXBContext is an expensive operation, so it is advised to create one instance for Jersey.

Example 4.1. Using custom JAXBContext

The example demonstrates a simple JAXBContext creation.

@Provider
public class ExamJAXBContextProvider implements ContextResolver<JAXBContext> {
    private JAXBContext context = null;

    public JAXBContext getContext(Class<?> aClass) {
        if (aClass != Exam.class) {
            return null;
        }
        if (context == null) {
            try {
                context = JAXBContext.newInstance(Exam.class);
            } catch (JAXBException e) {
                System.out.println(e.getMessage());
            }
        }
        return context;
    }
}

Example 4.2. Using Provider with Jersey Client

The code below shows how to declare a provider in client config:

ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getClasses().add(ExamJAXBContextProvider.class);
Client client = Client.create(clientConfig);
Read also:
Trustpilot
Trustpilot
Comments