Creating a CXF client which can get JSON or XML

In the previous post we created a server which serves up JSON or XML via a REST style interface and whilst we also demonstrated calling it from a browser, we really now need to look at implementing a compatible client.

POM first

Create a pom.xml and copy the following into it (within your client project folder)

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.putridparrot.client</groupId>
    <artifactId>ppclient</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>ppclient</name>
    <url>http://maven.apache.org</url>

    <properties>
        <cxf.version>2.7.18</cxf.version>
        <httpclient.version>4.3.6</httpclient.version>
        <surefire.version>2.19.1</surefire.version>
        <jackson.version>1.9.13</jackson.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>${httpclient.version}</version>
            <exclusions>
                <exclusion>
                    <artifactId>commons-logging</artifactId>
                    <groupId>commons-logging</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-jaxrs</artifactId>
            <version>${jackson.version}</version>
        </dependency>
    </dependencies>
</project>

Now we create our folder structure, so create the following from the root folder

src/main/java

Select the java folder in IntelliJ and Mark Directory As Sources Root.

We also need to copy the previously generated Java files (via XJC) into our java folder.

Now we’re going to use a proxy to access our service, but we’ll still need a representation of the service. This is another good reason why we separated the interface for the service from the implementation, so copy the interface from the server into our java folder (here’s the code)


import com.putridparrot.sample.PurchaseOrderType;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.xml.bind.JAXBElement;

@Path("service")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public interface SampleService {
    @GET
    @Path("purchaseOrder")
    public PurchaseOrderType getPurchaseOrder();
}

Nothing new here, so let’s move onto the actual client code. Add a new class, mine’s ClientApplication and it’s listed below

import com.putridparrot.sample.PurchaseOrderType;
import org.apache.cxf.jaxrs.client.JAXRSClientFactory;
import org.apache.cxf.jaxrs.client.WebClient;
import org.apache.cxf.jaxrs.provider.JAXBElementProvider;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;

import javax.ws.rs.core.MediaType;
import javax.xml.bind.JAXBElement;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class ClientApplication {
    public static void main(String[] args) throws IOException {

        List<Object> providers = new ArrayList<Object>();
        providers.add(new JAXBElementProvider());
        providers.add(new JacksonJsonProvider());

        SampleService service = JAXRSClientFactory.create(
           "http://localhost:9000", 
           SampleService.class, 
           providers);

        WebClient.client(service)
           .type(MediaType.APPLICATION_XML_TYPE)
           .accept(MediaType.APPLICATION_XML_TYPE);

        PurchaseOrderType request = service.getPurchaseOrder();

        System.out.println(request.getBillTo().getName());
        System.in.read();
    }
}

Now, in the above we’re again supplying providers for the different types, but this is solely for us to test switching between them, if you’re solely interested in XML then remove the providers, but you’ll still need to specify XML as the accept type.

To switch to JSON as the type returned, we simply switch replace the WebClient code with

WebClient.client(service)
   .type(MediaType.APPLICATION_JSON_TYPE)
   .accept(MediaType.APPLICATION_JSON_TYPE);

Ofcourse, in reality we don’t care too much about the format of the message returned when using it with a proxy unless we’re constrained by the server.