JSON Restful Web Service in Java

What kind of ways are available to get JSON Restful Web Service in Java?

Wait, what is JSON? Also Restful Web Service exactly?

Actually, I got to know them only a couple of weeks ago.

If you have tried XML Web Service with SOAP, you probably know how hard to get performance, and ease of use without complexity(especially about schema binding).

Then, JSON Restful Web Service must be what you will get interested in.

Let's go back to the first question. You can think of two providers. Sun and Apache. Here're options to go first.

  1. Apache Axis2.0
  2. JAX-WS with JSON extention

In my opinion, they're just a topping on top of XML Web Service. That is the very basic mismatch. Feel free to try if you need to make sure

This is the one, with which you can get a true power of JSON Restful Web Service.

Restlet

Take a look at Introduction on the site if you are not 100% sure about Restful Web Service(REST).

I'm going to show you an example to implement a service that returns DataTable compatible with one of Google Visualization API. The source of information is this thread in Google Visualization Discussion.

Code:

<CHUNK1>
google.visualization.Query.setResponse(
{
        requestId:'0',
        status:'ok',
        signature:'6173382439516707022',                /* Changes when data changes */
</CHUNK1>
So the timeseries gadget must download this JSON every so often and
check the new signature against it's own.  If the signature is
different, it knows that the data on the "spreadsheet" has changed.
<CHUNK2>
        table:{
                cols:
                        [
                                {
                                        id:'A',
                                        label:'Date',
                                        type:'d',               /* d=date */
                                        pattern:'M/d/yyyy'      /* unique date pattern */
                                },
                                {
                                        id:'B',
                                        label:'Budget',
                                        type:'n',       /*      n=number */
                                        pattern:'#0.###############'    /* unique number pattern */
                                },
                                {
                                        id:'C',
                                        label:'Revenue',
                                        type:'n',
                                        pattern:'#0.###############'
                                },
                                {
                                        id:'D',
                                        label:'Movie',
                                        type:'t',       /*      t=text */
                                        pattern:''      /* there is no text pattern */
                                }
                        ],
</CHUNK2>
Chunk2 shows the columns needed for a timeseries chart. (Date,
Value1, ..., ValueN, PopupText)
Note the type and pattern fields.  d=date, n=number, t=text
<CHUNK3>
                rows:
                        [
                                [
                                        {
                                                v:new Date(1981,10,6),
                                                f:'11/6/1981'
                                        },
                                        {
                                                v:5000000.0,
                                                f:'5000000'
                                        },
                                        {
                                                v:4.2365581E7,
                                                f:'42365581'
                                        },
                                        {
                                                v:'Time Bandits'
                                        }
                                ],
</CHUNK3>

To get this type of JSON Object is the goal. So how to do this?

In order to understand the following code, you may want to learn the tutorial how Restlet models the resource oriented Restfull world.

Restlet

Code:

import org.restlet.Application;
import org.restlet.Context;
import org.restlet.Restlet;
import org.restlet.Router;
 
public class JSONApplication extends Application {
 
  public JSONApplication() {
    super();
  }
 
  public JSONApplication(Context arg0) {
    super(arg0);
  }
 
  @Override
  public Restlet createRoot() {
        Router router = new Router(getContext());
        
        router.attach("/table", JSONTableResource.class);
        
    return router;
  }
 
}

Table Resource and JSON Representation

Code:

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.restlet.Context;
import org.restlet.data.CharacterSet;
import org.restlet.data.MediaType;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.data.Status;
import org.restlet.ext.json.JsonRepresentation;
import org.restlet.resource.Representation;
import org.restlet.resource.Resource;
import org.restlet.resource.ResourceException;
import org.restlet.resource.Variant;
 
public class JSONTableResource extends Resource {
  
  private static final String JSON_NAME_TABLE = "table";
  
  private static final String JSON_NAME_COLUMNS = "cols";
  private static final String JSON_NAME_COLUMNS_ID = "id";
  private static final String JSON_NAME_COLUMNS_LABEL = "label";
  private static final String JSON_NAME_COLUMNS_TYPE = "type";
  private static final String JSON_NAME_COLUMNS_PATTERN = "pattern";
  
  private static final String JSON_NAME_ROWS = "rows";
  private static final String JSON_NAME_ROWS_V = "v";
  private static final String JSON_NAME_ROWS_F = "f";
 
  public JSONTableResource(Context context, Request request, Response response) {
    super(context, request, response);
    
    getVariants().add(new Variant(MediaType.APPLICATION_JSON));
  }
 
  @Override
  public Representation represent(Variant variant) throws ResourceException {
    JSONObject json = new JSONObject();
    
    try {
      
      json.put("requestId", "0");
      json.put("status", "ok");
      json.put("signature", "6173382439516707022");
      
      json.put(JSON_NAME_TABLE, this.createTable());
      
    } catch (JSONException e) {
      throw new ResourceException(Status.SERVER_ERROR_INTERNAL);
    }
    
    JsonRepresentation jr = new JsonRepresentation(json);
    
    jr.setCharacterSet(CharacterSet.UTF_8);
    
    return jr;
  }
  
  private JSONObject createTable() throws JSONException{
    JSONArray columns = new JSONArray();
    JSONArray rows = new JSONArray();
    JSONObject r_c = new JSONObject();
    r_c.put(JSON_NAME_COLUMNS, columns);
    r_c.put(JSON_NAME_ROWS, rows);
    
    this.createColumns(columns);
    this.createRows(rows);
    
    return r_c;
  }
  
  private void createColumns(JSONArray columns) throws JSONException{
    
    columns.put(this.createColumn("A", "Date", "d", "M/d/yyyy"));
    columns.put(this.createColumn("B", "Budget", "n", "#0.###############"));
    columns.put(this.createColumn("C", "Revenue", "n", "#0.###############"));
    columns.put(this.createColumn("D", "Movie", "t", ""));
    
  }
  
  private void createRows(JSONArray rows) throws JSONException{
    
    JSONArray row = new JSONArray();
    
    row.put(this.createCell("new Date(1981,10,6)", "11/6/1981"));
    row.put(this.createCell("5000000.0", "5000000"));
    row.put(this.createCell("4.2365581E7", "42365581"));
    row.put(this.createCell("Time Bandits", null));
    
    rows.put(row);
    
  }
  
  private JSONObject createCell(String v, String f) throws JSONException{
    JSONObject jo = new JSONObject();
    jo.put(JSON_NAME_ROWS_V, v);
    if(f != null)
      jo.put(JSON_NAME_ROWS_F, f);
    return jo;
  }
  
  private JSONObject createColumn(String id, String label, String type, String pattern) throws JSONException{
    JSONObject jo = new JSONObject();
    jo.put(JSON_NAME_COLUMNS_ID, id);
    jo.put(JSON_NAME_COLUMNS_LABEL, label);
    jo.put(JSON_NAME_COLUMNS_TYPE, type);
    jo.put(JSON_NAME_COLUMNS_PATTERN, pattern);
    return jo;
  }
 
}

web.xml

XML:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
            xmlns="http://java.sun.com/xml/ns/j2ee"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
                 http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
   <display-name>first steps servlet</display-name>
   <!−− Application class name −−>
   <context-param>
      <param-name>org.restlet.application</param-name>
      <param-value>
         firstSteps.JSONApplication
      </param-value>
   </context-param>
 
   <!−− Restlet adapter −−>
   <servlet>
      <servlet-name>RestletServlet</servlet-name>
      <servlet-class>
         com.noelios.restlet.ext.servlet.ServerServlet
      </servlet-class>
   </servlet>
 
   <!−− Catch all requests −−>
   <servlet-mapping>
      <servlet-name>RestletServlet</servlet-name>
      <url-pattern>/json/*</url-pattern>
   </servlet-mapping>
</web-app>

You can get JSON Object in Java here.

Here's the JSON texts you'll get.

Code:

{"status":"ok","requestId":"0",
"table":
  {"cols":[
        {"id":"A","pattern":"M/d/yyyy","label":"Date","type":"d"},
        {"id":"B","pattern":"#0.###############","label":"Budget","type":"n"},
        {"id":"C","pattern":"#0.###############","label":"Revenue","type":"n"},
        {"id":"D","pattern":"","label":"Movie","type":"t"}  
      ],
  "rows":[
        [
          {"f":"11/6/1981","v":"new Date(1981,10,6)"},
          {"f":"5000000","v":"5000000.0"},
          {"f":"42365581","v":"4.2365581E7"},
          {"v":"Time Bandits"}
        ]
      ]
  },
"signature":"6173382439516707022"}

Then, you can call the service, get DataTable, then process to visualize. Here's an example to show a simple table in Ajax.

Code:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <script type="text/javascript">
    
    var xhr;
    try {  xhr = new ActiveXObject('Msxml2.XMLHTTP');   }
    catch (e)
    {
        try {   xhr = new ActiveXObject('Microsoft.XMLHTTP');    }
        catch (e2)
        {
          try {  xhr = new XMLHttpRequest();     }
          catch (e3) {  xhr = false;   }
        }
     }
 
   xhr.open("GET", JSON_RESTFULL_WEB_SERVICE_URL,  true);
   xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
   xhr.send(null);
  
   xhr.onreadystatechange  = function()
    {
         if(xhr.readyState  == 4)
         {
              if(xhr.status  == 200){
                  the_object = eval( "(" + xhr.responseText + ")" );
                  handleQueryResponse(the_object.table);
              }else{
                
              }
         }
    };
 
      // Query response handler function.
      function handleQueryResponse(table) {
 
        var html = [];
        html.push('<table border="1">');
 
        // Header row
        html.push('<tr><th>Seq</th>');
        for (var col = 0; col < table.cols.length; col++) {
          html.push('<th>' + escapeHtml(table.cols[col].label) + '</th>');
        }
        html.push('</tr>');
 
        for (var row = 0; row < table.rows.length; row++) {
          html.push('<tr><td align="right">' + (row + 1) + '</td>');
          for (var col = 0; col < table.cols.length; col++) {
            html.push(table.cols[col].type == 'number' ? '<td align="right">' : '<td>');
            html.push(escapeHtml(table.rows[row][col].f));
            html.push('</td>');
          }
          html.push('</tr>');
        }
        html.push('</table>');
 
        document.getElementById('tablediv').innerHTML = html.join('');
      }
 
      function escapeHtml(text) {
        if (text == null)
          return '';
 
        return text.replace(/&/g, '&amp;')
          .replace(/</g, '&lt;')
          .replace(/>/g, '&gt;')
          .replace(/"/g, '&quot;');
      }
 
    </script>
  </head>
 
  <body>
    <div id="tablediv">Loading...</div>
  </body>
</html>

Simple, Fast, and Flexible. Experience JSON Restful Web Service!

UPDATE(4/14/2011) : Looking for the latest example? Check out: Restlet + GWT StockWatcher sample integration

6 comments

Comment from: Mahboob [Visitor]
***--
Good work !
That U help other to understand something.
I remember U as a teacher.

Thanks.
2009/03/28 @ 18:56
Comment from: MD [Member] Email
You're Welcome!
2009/03/29 @ 02:53
Comment from: Ramon [Visitor]
Hi, i'm using restler 1.2m2, do you know how to use @get("json") ?

The server throws tihs warning.
"Unable to find a converter for this object : {"id":"1234","name":"Ramon"}"

Thanks.
2009/04/19 @ 03:21
Comment from: MD [Member] Email
It seems lots of discussions undergo. According to them, any extention, like "json", sounds valid for the value of those annotations.

If it does not work as expected, you can just work around by specifying in a constructor of Resource as follows.

getVariants().add(new Variant(MediaType.APPLICATION_JSON));

Cheers,
2009/04/20 @ 17:49
Comment from: cowtowncoder [Visitor]
***--
Quick comment: JAX-RS (and esp. Jersey, http://jersey.dev.java.net) is an excellent choice, too, for REST-style services. So no, you don't need to do SOAP (and with JSON, shouldn't) for web services. :)

I also think that instead of using Json.org package, there are many other choices that make it MUCH easier to output Json. Amount of code needed in the example was quite a lot -- with data binding, it should be just 3 lines of code or so to get JSON out of a Bean.
2009/05/19 @ 06:31
Comment from: Jonathan [Visitor]
Thanks for posting this. i really had good time reading this. 00-)
2011/11/04 @ 22:19

Leave a comment


Your email address will not be revealed on this site.

Your URL will be displayed.
PoorExcellent
(Line breaks become <br />)
(Name, email & website)
(Allow users to contact you through a message form (your email will not be revealed.)
Free Blog Themes and Free Blog Templates