Pages

  • Home
  • Contact Me
spacer

March 15, 2012

MOXy as Your JAX-RS JSON Provider - Client Side

Recently I posted how to leverage EclipseLink JAXB (MOXy)'s JSON binding to create a RESTful service.  In this post I will demonstrate how easy it is to take advantage of MOXy's JSON binding on the client side.
  • MOXy as Your JAX-RS JSON Provider - Server Side
  • MOXy as Your JAX-RS JSON Provider - Client Side

URI

This post will focus on the following URI from the service we declared in the previous post.  The following call will return a list of customers that live in "Any Town".

localhost:8080/CustomerService/rest/customers/findCustomersByCity/Any%20Town

Java SE Client APIs

In the first example we will use the standard Java SE 6 APIs.  Some interesting items to note:
  • MOXy can directly marshal (line 35) and unmarshal (line 28) collections to/from JSON arrays without requiring a wrapper object.
  • There are no compile time dependencies on MOXy (it is a run time dependency).
  • The eclipselink.media-type property is used to enable JSON binding on the unmarshaller (line 25) and marshaller (line 33).
  • The eclipselink.json.include-root property is used to indicate that the @XmlRootElement annotation should be ignored in the JSON binding (lines 26 and 34).

package example;

import java.io.InputStream;
import java.net.*;
import java.util.List;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
import org.example.Customer;

public class JavaSEClient {

    private static final String MEDIA_TYPE = "application/json";

    public static void main(String[] args) throws Exception {
        String uri = "localhost:8080/CustomerService/rest/customers/findCustomersByCity/Any%20Town";
        URL url = new URL(uri);
        HttpURLConnection connection =
            (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.setRequestProperty("Accept", MEDIA_TYPE);

        JAXBContext jc = JAXBContext.newInstance(Customer.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        unmarshaller.setProperty("eclipselink.media-type", MEDIA_TYPE);
        unmarshaller.setProperty("eclipselink.json.include-root", false);
        InputStream xml = connection.getInputStream();
        List<Customer> customers = (List<Customer>) unmarshaller.unmarshal(new StreamSource(xml), Customer.class).getValue();
        connection.disconnect();

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setProperty("eclipselink.media-type", MEDIA_TYPE);
        marshaller.setProperty("eclipselink.json.include-root", false);
        marshaller.marshal(customers, System.out);
    }

}

Output

Below is the output from running the Java SE client.  For those that may have used a JAXB (JSR-222) implementation with something like Jettison to produce/consume JSON, the following are some interesting items to note:
  • MOXy renders collections as JSON arrays.
  • MOXy represents the numeric values correctly without quotes (line 26).
  • MOXy surrounds collections of size 1 correctly with square brackets (lines 28 and 32).
    [ {
       "address" : {
          "city" : "Any Town",
          "id" : 1,
          "street" : "1 A Street"
       },
       "firstName" : "Jane",
       "id" : 1,
       "lastName" : "Doe",
       "phoneNumbers" : [ {
          "id" : 2,
          "num" : "555-2222",
          "type" : "HOME"
       }, {
          "id" : 1,
          "num" : "555-1111",
          "type" : "WORK"
       } ]
    }, {
       "address" : {
          "city" : "Any Town",
          "id" : 10,
          "street" : "456 Another Road"
       },
       "firstName" : "Sue",
       "id" : 10,
       "lastName" : "Jones",
       "phoneNumbers" : [ {
          "id" : 10,
          "num" : "555-3333",
          "type" : "WORK"
       } ]
    } ]
    

    Jersey Client APIs

    JAX-RS 2.0 (JSR-339) is working on standardizing the client APIs.  With JAX-RS 1.0 many of the implementations provide their own version.  Below is an example using the client APIs provided by Jersey.  Note how we can leverage the exact same MessageBodyReader/Writer that we used on the server side (line 14, refer to MOXy as Your JAX-RS JSON Provider - Server Side).  I have also specified the LoggingFilter (line 17) so we can take a closer look at the message.

    package example;
    
    import java.util.List;
    import org.example.Customer;
    import org.example.MOXyJSONProvider;
    import com.sun.jersey.api.client.*;
    import com.sun.jersey.api.client.config.*;
    import com.sun.jersey.api.client.filter.LoggingFilter;
    
    public class JerseyClient {
    
        public static void main(String[] args) {
            ClientConfig cc = new DefaultClientConfig();
            cc.getClasses().add(MOXyJSONProvider.class);
    
            Client client = Client.create(cc);
            client.addFilter(new LoggingFilter());
    
            WebResource resource = client.resource("localhost:8080/CustomerService/rest/customers");
            List<Customer> customers = resource.path("/findCustomersByCity/Any%20Town").accept("application/json").get(new GenericType<List<Customer>>(){});
    
            for(Customer customer : customers) {
                System.out.println(customer.getFirstName());
            }
        }
    
    }
    

    Output

    Below is the output from running the Jersey client.

    14-Mar-2012 4:08:12 PM com.sun.jersey.api.client.filter.LoggingFilter log
    INFO: 1 * Client out-bound request
    1 > GET localhost:8080/CustomerService/rest/customers/findCustomersByCity/Any%20Town
    1 > Accept: application/json
    1 > 
    
    14-Mar-2012 4:08:12 PM com.sun.jersey.api.client.filter.LoggingFilter log
    INFO: 1 * Client in-bound response
    1 < 200
    1 < Transfer-Encoding: chunked
    1 < Date: Wed, 14 Mar 2012 20:08:12 GMT
    1 < Content-Type: application/json
    1 < X-Powered-By: Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 3.1.1 Java/Oracle Corporation/1.7)
    1 < Server: GlassFish Server Open Source Edition 3.1.1
    1 < 
    [{"address" : {"city" : "Any Town", "id" : 1, "street" : "1 A Street"}, "firstName" : "Jane", "id" : 1, "lastName" : "Doe", "phoneNumbers" : [{"id" : 1, "num" : "555-1111", "type" : "WORK"}, {"id" : 2, "num" : "555-2222", "type" : "HOME"}]}, {"address" : {"city" : "Any Town", "id" : 10, "street" : "456 Another Road"}, "firstName" : "Sue", "id" : 10, "lastName" : "Jones", "phoneNumbers" : [{"id" : 10, "num" : "555-3333", "type" : "WORK"}]}]
    
    Doe, Jane
    Jones, Sue
    

    Further Reading

    If you enjoyed this post then you may also be interested in:
    • RESTful Services
      • MOXy as Your JAX-RS JSON Provider  - Server Side
      • Creating a RESTful Service
        • Part 1 - The Database
        • Part 2 - Mapping the Database to JPA Entities
        • Part 3 - Mapping JPA entities to XML (using JAXB)
        • Part 4 - The RESTful Service
        • Part 5 - The Client
      • MOXy's XML Metadata in a JAX-RS Service 
    • JSON Binding
      • JSON Binding with EclipseLink MOXy - Twitter Example
      • Binding to JSON & XML - Geocode Example

    0 comments:

    Post a Comment

    Newer Post Older Post Home