MrBool
You must be logged in to give feedback. Click here to login
[Close]

You must be logged to download.

Click here to login

[Close]

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

[Close]

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

Mobile application integrations: switching to JSON

In this article we will discuss about mobile application integrations with JSON. We will see also how to switch the server side.

[close]

You didn't like the quality of this content?

Would you like to comment what you didn't like?

Introduction

It does however have drawbacks: it is a relatively heavyweight format, with a degree of flexibility that can make manipulating it in environments where we either don’t have or don’t want to use object binding somewhat daunting.

In web client scripting (i.e. AJAX) environments, JSON is often preferred. JSON is a format designed specifically for use by Javascript applications, which has a one-to-one mapping with Javascript’s native object model, meaning that object mapping of the kind we have been using with XML is not necessary when working in Javascript with JSON.

With this in mind, if you are developing a dynamic web client for your services as well as the mobile client, you may prefer to use JSON to integrate both parts, thus reducing the amount of work required on the server.

Jackson is the most popular Java library for handling JSON data. It can be downloaded from http://jackson.codehaus.org/, and I have used version 2.1 in the code for this article (although other versions should be similar).

Switching the server side

In preparation to switch to using Jackson, I removed the SimpleXML jar files from my server project and fixed the errors that occurred by removing the references. I then set up Spring to create and configure the necessary Jackson objects:

Listing 1: Spring configuration to create Jackson objects

 
    <bean id="objectMapper" class="com.fasterxml.jackson.databind.ObjectMapper" /> 
    <bean id="objectWriter" factory-bean="objectMapper" factory-method="writerWithDefaultPrettyPrinter" />
    <bean id="objectReader" factory-bean="objectMapper" factory-method="reader" />

    <util:map id="servlets">

       … other servlets configured here ….
        <entry key="/json/customers"><bean class="com.example.jsonservice.CustomerList" /></entry>
        <entry key="/json/customerAccounts">
		<bean class="com.example.jsonservice.CustomerAccounts" /></entry>
        <entry key="/json/newCustomer"><bean class="com.example.jsonservice.NewCustomer" /></entry>
        
    </util:map>

It is possible to just use the Jackson ObjectMapper object directly, rather than creating ObjectWriter and ObjectReader instances, but I wanted to use Jackson’s “pretty printer” feature to get formatted JSON output, and this requires configuration that cannot be performed directly on the ObjectMapper. I therefore decided to use both ObjectWriter (which is required to use the pretty printer) and ObjectReader (which is not) in order to maintain symmetry in the way my application creates and consumes JSON documents.

Having done this, I switched my first servlet over to using the Jackson interface:

Listing 2: The CustomerList servlet

 
public class CustomerList extends HttpServlet
{
	CustomerDAO customerDAO;
	ObjectWriter objectWriter;
	
	public void setCustomerDAO (CustomerDAO customerDAO)
	{
	    this.customerDAO = customerDAO;
	}
	public void setObjectWriter (ObjectWriter objectWriter)
	{
	    this.objectWriter = objectWriter;
	}
	
	@Override
	protected void doGet (HttpServletRequest req, HttpServletResponse resp) 
		throws ServletException, IOException
	{
		resp.setContentType ("application/json");
		try
		{
			objectWriter.writeValue(resp.getWriter(), 
				Result.customers (customerDAO.getAll ()));
		}
		catch (JsonGenerationException|JsonMappingException|SQLException e)
		{
			throw new ServletException ("Error sending list of customers", e);
		}
	}
}

The changes are, as you can see, minimal. Running it, I got this output:

Listing 3: JSON output from the first run

{}

This highlights an important difference between SimpleXML and Jackson that it is important to understand and can help work with either of them: SimpleXML is a field-based serializer, i.e. when looking at an object it examines a list of its fields and queries them directly (under control of annotations on those fields). Jackson, however, works with getter and setter methods instead. As I had not defined public getters for fields in my Result class, it did not list any values. Adding the necessary getters and retesting produces the expected output:

Listing 4: JSON output fixed

 
{
  "success" : true,
  "error" : null,
  "customers" : [ {
    "id" : 1,
    "name" : "Joe"
  }, {
    "id" : 2,
    "name" : "Carinna"
  } ],
  "accounts" : null
}
 

Switching over the account list servlet was just as easy. Changing the new customer servlet, however, required just a little more work:

Listing 5: Updated NewCustomer servlet

 
public class NewCustomer extends HttpServlet
{
	CustomerDAO customerDAO;
	ObjectReader objectReader;
	ObjectWriter objectWriter;

	public void setCustomerDAO(CustomerDAO customerDAO)
	{
		this.customerDAO = customerDAO;
	}

	public void setObjectReader(ObjectReader objectReader)
	{
		this.objectReader = objectReader;
	}

	public void setObjectWriter(ObjectWriter objectWriter)
	{
		this.objectWriter = objectWriter;
	}

	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException
	{
		resp.setContentType("application/json");
		try
		{
			Customer customer = objectReader.withType(Customer.class)
					.readValue(req.getInputStream());
			customer.validate();
			customerDAO.create(customer);
			objectWriter.writeValue(resp.getWriter(), Result.success());
		} 
		catch (Exception e)
		{
			e.printStackTrace();
			try
			{
				objectWriter.writeValue(
						resp.getWriter(),
						Result.error("Failed to create customer: "
								+ e.toString()));
			} 
			catch (JsonGenerationException | JsonMappingException nestedError)
			{
				throw new ServletException(nestedError);
			}
		}
	}
}

Here I use both an ObjectReader and an ObjectWriter object. In order to use the ObjectReader I need to configure it with the class of item it reads; if I were concerned about efficiency I could store this configured object (generated by calling objectReader.withType(Customer.class)), but I am more concerned with the readability of my code and I feel it is easier to reader when the type to be read is specified close to where the reading occurs. Sending the result back to the client is similar to the customer list servlet.

Switching the client

Changing the client to use Jackson was just as easy as changing the server. I created a new “Config” class to provide configured Jackson objects in a centralized way so that I can easily change options on them throughout the application later. Here’s the class:

Listing 6: The new Config class

 
public class Config
{
	private static ObjectMapper mapper = new ObjectMapper();
	
	public static ObjectReader getReader(Class<?> class1)
	{
		return mapper.reader(class1);
	}

	public static ObjectWriter getWriter()
	{
		return mapper.writerWithDefaultPrettyPrinter();
	}
}
 

I also ensured that all references to SimpleXML were removed and that my data transfer objects Reader, Customer and Account all had a complete set of public getters and setters.

The CustomerListActivity required minimal changes. Apart from removing references to SimpleXML, the doInBackground method changed to this:

Listing 7: CustomerListActivity.DownloadTask.doInBackground()

 
@Override
protected Result doInBackground (Void... params)
{
	HttpClient client = new DefaultHttpClient ();
	try
	{
		HttpResponse response = client.execute (new HttpGet (
			"http://192.168.1.101:8080/simplespring/json/customers"));
		if (response.getStatusLine ().getStatusCode () != 200)
			return Result.error (response.getStatusLine ().getReasonPhrase ());
				
		HttpEntity entity = response.getEntity();
		String contentType = entity.getContentType().getValue();
		if (!contentType.startsWith("application/json"))
			return Result.error ("Did not receive JSON response (content type was: " +
				 contentType + ")");
				
		return Config.getReader(Result.class).readValue (entity.getContent());
	}
	catch (Exception e)
	{
		return Result.error (e.toString());
	}
}

The changes to the AccountListActivity were similar. NewCustomerActivity required slightly more attention. Its doInBackground method became:

Listing 8: NewCustomerActivity.CreateCustomerTask.doInBackground()

 
@Override
protected Result doInBackground (Customer... params)
{
	HttpClient client = new DefaultHttpClient ();
	try
	{
		HttpPost request = new HttpPost (
			"http://192.168.1.101:8080/simplespring/json/newCustomer");
		
		StringEntity requestEntity = new StringEntity(
				Config.getWriter().writeValueAsString (params[0]));
		requestEntity.setContentType("application/json");
			
		request.setEntity(requestEntity);
		
		HttpResponse response = client.execute (request);
		if (response.getStatusLine ().getStatusCode () != 200)
			return Result.error (response.getStatusLine ().getReasonPhrase ());
				
		HttpEntity entity = response.getEntity();
		String contentType = entity.getContentType().getValue();
				
		if (!contentType.startsWith("application/json"))
			return Result.error ("Did not receive JSON response (content type was: " + 
				contentType + ")");
				
		return Config.getReader(Result.class).readValue(entity.getContent());
	}
	catch (Exception e)
	{
		return Result.error (e.toString());
	}
}

Note that this is slightly simpler than the original code; Jackson’s ObjectWriter objects support a writeValueAsString() method that returns the encoded JSON document in a String. This avoids the need to create a StringWriter to capture the document sent to a Writer as we had to with SimpleXML.

Switching to Jackson from SimpleXML is a simple and fast change. The resulting application is slightly larger (its usage of storage space on my test phone increased by around 800KB in the process), but feels somewhat snappier in usage (probably caused by the fact that JSON is a more space-efficient format than the XML it replaced). In the end, there is little to choose between the two formats, but I would definitely prefer JSON when also developing an AJAX web client for the same service.

This is all for this article. See you next time.

Also read:



My main area of specialization is Java and J2EE. I have worked on many international projects like Recorders,Websites,Crawlers etc.Also i am an Oracle Certified java professional as well as DB2 certified

What did you think of this post?
Services
Know how to keep MrBool Online
SUPPORT US
SUPPORT US
With your help, we can keep providing free content and helping you to be a better professional
support us
[Close]
To have full access to this post (or download the associated files) you must have MrBool Credits.

  See the prices for this post in Mr.Bool Credits System below:

Individually � in this case the price for this post is US$ 0,00 (Buy it now)
in this case you will buy only this video by paying the full price with no discount.

Package of 10 credits - in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download few videos. In this plan you will receive a discount of 50% in each video. Subscribe for this package!

Package of 50 credits � in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download several videos. In this plan you will receive a discount of 83% in each video. Subscribe for this package!


> More info about MrBool Credits
[Close]
You must be logged to download.

Click here to login