Ilias Tsagklis

About Ilias Tsagklis

Ilias Tsagklis is a senior software engineer working in the telecom domain. He is an applications developer in a wide variety of applications/services. Ilias is co-founder and Executive Editor at Java Code Geeks.

Add JSON capabilities into your GWT application

Introduction to JSON
While working on web applications, the issue of client-server data exchange always arises. There are various approaches on this matter, with a lot of them using XML for the exchange. A not so well known format for performing this task is JSON. JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write, and easy for machines to parse and generate. JSON is considered less verbose and bloated than XML and more readable, even though those might vary on the transmitted data. There are multiple resources online to kick start you with JSON.

JSON libraries
JSON is a text format that is completely language independent and there are libraries available for a huge number of programming languages. For JSON in Java, the source code of the implementation is available. Note that the site does not provide binaries in an archive file, but we have compiled the classes and bundled them in a JAR file, which you can directly download here.

GWT and JSON integration
In this tutorial, I am going to show you how to manipulate JSON in GWT so that you can communicate with a JSON enabled web application. Note that in GWT applications, the most common way to achieve client-server communication is via RPC calls. So using JSON applies mostly in the case when an external server is reached via plain old HTTP calls.

Creating the application
Let’s get started by creating a new Eclipse project (“File ? New ? Web Application Project”) and name it “JsonGwtProject”. Select support only for Google’s Web Toolkit and not for the App Engine. The role of the server will be played by the embedded Jetty container that is provided by the GWT SDK.

After the project skeleton is created, edit the modules declaration file (named “JsonGwtProject.gwt.xml” in our case). Add the following line after the line that reads “Other modules inherits” in order to make your GWT application JSON enabled.

<inherits name="com.google.gwt.json.JSON" />

The domain model object
Now, let’s create the model object that will be used to hold the data. Our model is a “Product” class with various fields:

  • Name
  • Company
  • Serial Number
  • Prices

Multiple prices will be used in order to show you how to use nested JSON expressions.

The corresponding Java class (plain old Java object) is the following:

package com.javacodegeeks.json.gwt.server.model;

import java.util.LinkedList;
import java.util.List;

public class Product {
 
 private String name;
 private String company;
 private String serialNumber;
 private List<Double> prices = new LinkedList<Double>();
 
 public Product(String name, String company, String serialNumber, List<Double> prices) {
  super();
  this.name = name;
  this.company = company;
  this.serialNumber = serialNumber;
  this.prices = prices;
 }
 
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public String getCompany() {
  return company;
 }
 public void setCompany(String company) {
  this.company = company;
 }
 public String getSerialNumber() {
  return serialNumber;
 }
 public void setSerialNumber(String serialNumber) {
  this.serialNumber = serialNumber;
 }
 public List<Double> getPrices() {
  return prices;
 }
 public void setPrices(List<Double> prices) {
  this.prices = prices;
 }

}

Application’s server side
Now let’s create the server side code of the application. We will create a servlet that will be used to simulate an external server from which the data will be retrieved. The servlet creates a JSON response to the client using a static list of products (in a real-life application, the products would be fetched from a DAO or even better from an other service). Make sure you include the json.jar you downloaded into your project’s classpath and that it is also copied in the “war\WEB-INF\lib” folder. The servlet code is the following:

package com.javacodegeeks.json.gwt.server;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.json.JSONObject;

import com.javacodegeeks.json.gwt.server.model.Product;

public class ProductsServlet extends HttpServlet {
 
 private static final long serialVersionUID = 8032611514671727168L;
 
 private static List<Product> products = new LinkedList<Product>();
 
 static {
  Product product1 = new Product("Prod1", "Company1", "12345", Arrays.asList(123.2, 123.6));
  Product product2 = new Product("Prod2", "Company2", "67890", Arrays.asList(234.2, 234.6));
  products.add(product1);
  products.add(product2);
 }

 @Override
 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  
  try {
   
   JSONObject responseObj = new JSONObject();
   
   List<JSONObject> productObjects = new LinkedList<JSONObject>();
   
   for (Product product : products) {
    
    JSONObject productObj = new JSONObject();
    
    productObj.put("name", product.getName());
    productObj.put("company", product.getCompany());
    productObj.put("serialNumber", product.getSerialNumber());
    
    List<JSONObject> pricesObjects = new LinkedList<JSONObject>();
    for (Double price : product.getPrices()) {
     JSONObject priceObj = new JSONObject();
     priceObj.put("price", price);
     pricesObjects.add(priceObj);
    }
    
    productObj.put("prices", pricesObjects);
    
    productObjects.add(productObj);
   }
   
   responseObj.put("products", productObjects);
   
   PrintWriter writer = resp.getWriter();
   writer.write(responseObj.toString());
   writer.flush();
   
  } 
  catch (Exception e) {   
   e.printStackTrace();
   throw new ServletException(e);
  }
  
 }
 
}

Java JSON response generation
Let me explain how the JSON response is produced. Make sure you are importing the JSON classes from the org.json package and not the com.google.gwt.json. The first step is to create a JSONObject which will be the one that will hold the response. Since we most probably have a number of products, we also create a List of JSONObjects. We loop through the existing products and create a separate object for each one of them. In that object, we add key-value pairs, just like we would do with a Map. For the prices, we also create a List of JSONObjects and then we add the whole list in the product’s JSONObject. Finally we add the List of product objects into the response’s JSONObject. The toString() method of the JSONObject is used to create the string representation. For that example, the result is:

{“products”:
[
{“company”:”Company1″,”name”:”Prod1″,”prices”:[{"price":123.2},{"price":123.6}],”serialNumber”:”12345″}
{“company”:”Company2″,”name”:”Prod2″,”prices”:[{"price":234.2},{"price":234.6}],”serialNumber”:”67890″}
]
}

Servlet configuration in web.xml
Now let’s configure the application so that the servlet responds to a specific URL. Edit the web.xml file (located in “war/WEB-INF”) and paste the following contents (the original contents with the declaration of the greetingService are all removed):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
  
  <!-- Servlets -->
  <servlet>
    <servlet-name>ProductsServlet</servlet-name>
     <servlet-class>
     com.javacodegeeks.json.gwt.server.ProductsServlet
    </servlet-class>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>ProductsServlet</servlet-name>
    <url-pattern>/jsongwtproject/products.json</url-pattern>
  </servlet-mapping>
  
  <!-- Default page to serve -->
  <welcome-file-list>
    <welcome-file>JsonGwtProject.html</welcome-file>
  </welcome-file-list>

</web-app>

Client side with GWT
Finally, let’s create the GWT application’s entry point named “JsonGwtProject” (the original contents are completely removed). The client will invoke an HTTP GET call to the server, will receive the response in JSON format and then will parse the response. The code is:

package com.javacodegeeks.json.gwt.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.RootPanel;

public class JsonGwtProject implements EntryPoint {
    
    public void onModuleLoad() {
        
        final Button fetchDataButton = new Button("Fetch data");
        fetchDataButton.addStyleName("sendButton");
        
        RootPanel.get("fetchDataButtonContainer").add(fetchDataButton);
        
        fetchDataButton.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                fetchDataFromServer();
            }
        });
        
    }

    private void fetchDataFromServer() {
        
        try {
            
            RequestBuilder rb = new RequestBuilder(
                 RequestBuilder.GET, "/jsongwtproject/products.json");
            
            rb.setCallback(new RequestCallback() {
                @Override
                public void onResponseReceived(Request request, Response response) {
                    parseJsonData(response.getText());
                }
                @Override
                public void onError(Request request, Throwable exception) {
                    Window.alert("Error occurred" + exception.getMessage());
                }
            });
            rb.send();
            
        } 
        catch (RequestException e) {
            Window.alert("Error occurred" + e.getMessage());
        }
    }

    private void parseJsonData(String json) {

        JSONValue value = JSONParser.parse(json);

        JSONObject productsObj = value.isObject();
        
        JSONArray productsArray = productsObj.get("products").isArray();
        
        if (productsArray != null) {
            
            for (int i=0; i<=productsArray.size()-1; i++) {
                
                JSONObject productObj = productsArray.get(i).isObject();
                
                String name = productObj.get("name").isString().stringValue();
                String company = productObj.get("company").isString().stringValue();
                String serialNumber = productObj.get("serialNumber").isString().stringValue();
                
                StringBuffer priceSb = new StringBuffer();
                
                JSONArray pricesArray = productObj.get("prices").isArray();
                if (pricesArray != null) {
                    for (int j=0; j<=pricesArray.size()-1; j++) {
                        JSONObject priceObj = pricesArray.get(j).isObject();
                        double price = priceObj.get("price").isNumber().doubleValue();
                        if (j!=pricesArray.size()-1) {
                            priceSb.append("-");
                        }
                    }
                }
                String message = "Product -- " +
                    "\nName: " + name + 
                    "\nCompany: " + company +
                    "\nSerial: " + serialNumber + 
                    "\nPrices: " +  priceSb.toString();
                Window.alert(message);
                
            }
            
        }
    }

}

For the HTTP call, the RequestBuilder class is used. The HTTP method (GET) is defined along with the endpoint URL (where the servlet is configured to respond). Then, an asynchronous callback method is provided using the RequestCallback class. Finally, the request is sent. When the response arrives from the server (if no errors have occurred), our parseJsonData method is invoked. Parsing JSON data with GWT Let’s see now how to parse the received data using GWT built in methods. Make sure you are importing the JSON classes from the com.google.gwt.json package and not the org.json. First, we use the JSONParser to create a JSONValue object from the string response. From that we retrieve a JSONObject instance using the method isObject(). Since we know that the response is actually a list of products, we create a JSONArray class by invoking the isArray() method of JSONValue. A loop is then used and we extract the model’s fields by using the stringValue() method of the occurring JSONString object. Note that in order to extract the multiple price values, we use the same procedure looping through a JSONArray object. Preparing the HTML file The “JsonGwtProject.html”has also to be changed in order to provide a placeholder for the interface’s button. Edit it and add the following lines after the “noscript” declaration:

...
    <h1>Web Application Starter Project</h1>

    <table align="center">
      <tr>
        <td id="fetchDataButtonContainer"></td>
      </tr>
      <tr>
        <td colspan="2" style="color:red;" id="errorLabelContainer"></td>
      </tr>
    </table>
...

Running the example If we run the project, the interface appears, actually there is only a button. Clicking on the button. the JSON data are retrieved, the parsing is performed and the results are printed on the screen: That would be all. As always, you can download the Eclipse project from here.

Enjoy!

Related Articles :

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

JPA Mini Book

Learn how to leverage the power of JPA in order to create robust and flexible Java applications. With this Mini Book, you will get introduced to JPA and smoothly transition to more advanced concepts.

JVM Troubleshooting Guide

The Java virtual machine is really the foundation of any Java EE platform. Learn how to master it with this advanced guide!

Given email address is already subscribed, thank you!
Oops. Something went wrong. Please try again later.
Please provide a valid email address.
Thank you, your sign-up request was successful! Please check your e-mail inbox.
Please complete the CAPTCHA.
Please fill in the required fields.

2 Responses to "Add JSON capabilities into your GWT application"

  1. Good Share +1 … Quick question though….

    Why are you calling super() in class Product when Product doesn’t extend anything? All the field values are defined in the constructor …

    Just sayin’

    ;-)

Leave a Reply


six − = 1



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy | Contact
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close