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”.
http://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 = "http://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("http://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 http://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
- JSON Binding
Reference: MOXy as Your JAX-RS JSON Provider – Client Side from our JCG partner Blaise Doughan at the Java XML & JSON Binding blog.