Chaning pages dynamically using JQuery Mobile - use different .htmls

In the Changing pages dynamically in JQuery Mobile Worklight application i blogged about how you can use the JQuery Mobile JavaScript framework to create multi-page web application. In that example i built a web application which has only single HTML file that contains HTML fragments for different pages and i used following JavaScript to change page dynamically

function switchToPage2(){
  jq.mobile.changePage ("#page2");
}
One of the reader raised a very good question that it might not be good idea to have all the pages in same html and can we break the html's into different pages and answer is yes. I wanted to try that so first i did create a listcontact.html in the same directory as that of ManageContact.hml that has markup of only listcontact.html like this

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport"
  content="width=device-width, initial-scale=1.0, 
  maximum-scale=1.0, minimum-scale=1.0, user-scalable=0" />
<title>ManageContact</title>
<link rel="shortcut icon" href="images/favicon.png" />
<link rel="apple-touch-icon" href="images/apple-touch-icon.png" />
<link rel="stylesheet" href="css/reset.css" />
<link rel="stylesheet" href="css/ManageContact.css" />
<link rel="stylesheet" href="css/jquery.mobile-1.0.min.css" />
<script src="js/jquery-1.7.1.min.js"></script>
<script>
  var jq = jQuery.noConflict();
</script>
<script src="js/jquery.mobile-1.0.min.js"></script>
</head>
<body onload="WL.Client.init({})" id="content" style="display: none">
  <div data-role="page" id="home">
    <div data-theme="a" data-role="header">
      <h3>Contact List</h3>
    </div>
    <div data-role="content" id="pagePort">
      <ul data-role="listview" data-inset="true" data-filter="true"
        id="displayContact">
      </ul>
       <a data-role="button"
            data-transition="fade" href="#home"
            id="searchContact"> Home </a>
    </div>
    <div data-theme="a" data-role="footer">
      <h3>Copyright stuff</h3>
    </div>
  </div>
  <script src="js/ManageContact.js"></script>
  <script src="js/messages.js"></script>
  <script src="js/auth.js"></script>
</body>
The listcontact.html has the same structure as ManageContact.html (The worklight server does add more resources to the ManageContact.html as part of build process). Then i had to use following JavaScript to switch page

function switchToPage2(){
  jq.mobile.changePage ("listcontact.html");
}
and when i click on switchPage it does make forward control to listcontact.html, that works. But since we refreshed the whole page we loose the JavaScript context.

Calling a HTTP POST using Worklight REST adapter

I am trying to build Contact Management application using WorkLight that uses REST service as back end. You can take a look and download the REST service from Returning JSON response from JAXRS service This is how the insertContact() method of my JAXRS service looks like, the insertContact() method consumes MediaType.APPLICATION_FORM_URLENCODED

@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
public void insertContact(@FormParam("contactId") int contactId,
      @FormParam("firstName") String firstName,
      @FormParam("lastName") String lastName,
      @FormParam("email") String email) {
    Contact contact = new Contact();
    contact.setContactId(contactId);
    contact.setFirstName(firstName);
    contact.setLastName(lastName);
    contact.setEmail(email);
    ContactDAO contactDAO = new ContactDAOImpl();
    contactDAO.insertContact(contact);
}
This is how the insertContact() method in my REST adapter looks like. The method for this request is POST and the contentType is application/x-www-form-urlencoded i have to create the string representing the formBody and submit it in content.

function insertContact(firstName,lastName,email){
  WL.Logger.debug("Entering ContactRESTService1.insertContact()");
  var input = {
      method : 'post',
      returnedContentType : 'json',
      path : '/ManageContact/rest/contact',
      body:{
      contentType:'application/x-www-form-urlencoded',
      content:"firstName="+firstName+"&lastName="+lastName+"&email="+email
      } 
  };
  WL.Logger.debug("Exiting ContactRESTService1.insertContact()");
  return WL.Server.invokeHttp(input);
}

Changing pages dynamically in JQuery Mobile Worklight application

In the Creating multi page application with JQuery Mobile entry i talked about how to build a multi-page application with JQuery Mobile, in that i talked about how to switch page using static href's but most of time you would want to change page name dynamically after executing some JavaScript, so i changed my html like this

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport"
  content="width=device-width, initial-scale=1.0, maximum-scale=1.0,
  minimum-scale=1.0, user-scalable=0" />
<title>HelloWorkLightPhoneGap</title>
<link rel="shortcut icon" href="images/favicon.png" />
<link rel="apple-touch-icon" href="images/apple-touch-icon.png" />
<link rel="stylesheet" href="css/reset.css" />
<link rel="stylesheet" href="css/HelloWorkLightPhoneGap.css" />
<link rel="stylesheet" href="css/jquery.mobile-1.0.min.css" />
<script src="js/jquery-1.7.1.min.js"></script>
<script>
  var jq = jQuery.noConflict();
</script>
<script src="js/jquery.mobile-1.0.min.js"></script>
<script type="text/javascript"
  src="http://maps.google.com/maps/api/js?sensor=false"></script>
</head>
<body onload="WL.Client.init({})" id="content" style="display: none">
  <div data-role="page" id="page1">
    <div data-theme="a" data-role="header">
      <h3>First Page</h3>
    </div>
    <div data-role="content" id="pagePort">
      <a href="javascript:switchToPage2()">Go to second page</a>
    </div>
    <div data-theme="a" data-role="footer">
      <h3>Copyright stuff</h3>
    </div>
  </div>

  <div data-role="page" id="page2" >
    <div data-theme="a" data-role="header">
      <h3>Second Page</h3>
    </div>
    <div data-role="content" id="pagePort">
      <a href="javascript:switchToPage1()">Go to third page</a>
    </div>
    <div data-theme="a" data-role="footer">
      <h3>Copyright stuff</h3>
    </div>
  </div>
   <script src="js/HelloWorkLightPhoneGap.js"></script>
  <script src="js/messages.js"></script>
  <script src="js/auth.js"></script>
</body>
</html>
In this the anchor for change page is changed to point to JavaScript function that looks like this, you can use the jq.mobile.changePage("<pageid>")

function switchToPage2(){
  jq.mobile.changePage ("#page2");
}

function switchToPage1(){
  jq.mobile.changePage ("#page1");
}

Worklight Phone Gap Android application

I just created my first Worklight Phone Gap application for Android. The process is pretty easy you just add support for Android environment and then WorkLight creates/generates Android project for you. Once your project is ready you just right click on it and say Run as Android application to get a view like this
I wanted to see what is going on so i looked at the generated project, but before that this is how my Worklight application is structured
When you add support for Android, WorkLight generates PhoneGap Android project that is similar to Getting Started with PhoneGap on Android project, the Generated Java class looks like this

package com.HelloWorkLightPhoneGap;

import android.os.Bundle;

import com.worklight.androidgap.WLDroidGap;

public class HelloWorkLightPhoneGap extends WLDroidGap {
 @Override
 public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    super.loadUrl(getWebMainFilePath());
 }  
}
So basically this class is forwarding control to the HTML page but the HTML file name is not hard coded here instead it comes from wlclient.properties file which looks like this

wlServerProtocol = http
wlServerHost = 192.168.94.131
wlServerPort = 8080
wlAppId = HelloWorkLightPhoneGap
wlAppVersion = 1.0
wlC2DMEmailSender = ${wlC2DMEmailSender}
wlMainFilePath = HelloWorkLightPhoneGap.html
enableSettings = true
So the HelloWorkLightGap.html file is the main file for my WorkLight application that becomes a main file here. Also if you take a closer look at the content of the project you will notice that the Android has assets/www/default folder which has all the files from your worklight application

Creating multi page application with JQuery Mobile

JQuery Mobile makes creating multi-page application very easy, I think its much better than using Worklight for creating multi-page application Take a look at this simple html page that i built which has 3 pages page1, page2 and page3, every page has link to the next page.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport"
  content="width=device-width, initial-scale=1.0, maximum-scale=1.0,
  minimum-scale=1.0, user-scalable=0" />
<title>HelloWorkLightPhoneGap</title>
<link rel="shortcut icon" href="images/favicon.png" />
<link rel="apple-touch-icon" href="images/apple-touch-icon.png" />
<link rel="stylesheet" href="css/reset.css" />
<link rel="stylesheet" href="css/HelloWorkLightPhoneGap.css" />
<link rel="stylesheet" href="css/jquery.mobile-1.0.min.css" />
<script src="js/jquery-1.7.1.min.js"></script>
<script>
  var jq = jQuery.noConflict();
</script>
<script src="js/jquery.mobile-1.0.min.js"></script>
<script type="text/javascript"
  src="http://maps.google.com/maps/api/js?sensor=false"></script>
</head>
<body onload="WL.Client.init({})" id="content" style="display: none">
  <div data-role="page" id="page1">
    <div data-theme="a" data-role="header">
      <h3>First Page</h3>
    </div>
    <div data-role="content" id="pagePort">
      <a href="#page2">Go to second page</a>
    </div>
    <div data-theme="a" data-role="footer">
      <h3>Copyright stuff</h3>
    </div>
  </div>

  <div data-role="page" id="page2" >
    <div data-theme="a" data-role="header">
      <h3>Second Page</h3>
    </div>
    <div data-role="content" id="pagePort">
      <a href="#page3">Go to third page</a>
    </div>
    <div data-theme="a" data-role="footer">
      <h3>Copyright stuff</h3>
    </div>
  </div>
  
  <div data-role="page" id="page3">
    <div data-theme="a" data-role="header">
      <h3>Third page</h3>
    </div>
    <div data-role="content" id="pagePort">
      <a href="#page1">Go to first page</a>
    </div>
    <div data-theme="a" data-role="footer">
      <h3>Copyright stuff</h3>
    </div>
  </div>

  <script src="js/HelloWorkLightPhoneGap.js"></script>
  <script src="js/messages.js"></script>
  <script src="js/auth.js"></script>
</body>
</html>
When you want to move to the next page you use the link with value of href equal to the id of the next page

Setting up Android PhoneGap development environment

Before couple of days i was trying to setup Android Phone Gap environment on my machine, by following instructions at Getting started guide for Android environment on PhoneGap site, I was using PhoneGap 1.5 version and i had a problem of not being able to start the application. The solution was to use Android 2.2 SDK using the latest Android SDK some how does not work.

Invoking REST service that returns JSON from worklight

In the Invoking REST service from WorkLight i built a simple WorkLight application that makes REST call but the REST service in that case returns XML, To me if your building a REST service for access from Browser it would be much better idea to return JSON instead of XML that avoids one conversion. So with that goal in mind i wanted to change my application and i followed these steps for that
  • First thing that i had to do was change the REST service so that it returns JSON and also i made JSON as the default return type for service, you can get more information and download the sample application by using entry
  • Next i changed the ContactRESTService-impl.js, the worklight REST adapter that i am using for making the actual call,
    
    function getContactList() {
      var input = {
          method : 'get',
          returnedContentType : 'json',
          path : '/ManageContact/rest/contact'
      };
      return WL.Server.invokeHttp(input);
    }
    
    function searchContact(lastName){
      var input = {
            method : 'get',
            returnedContentType : 'json',
            path : '/ManageContact/rest/contact/search?lastName='+lastName
        };
        return WL.Server.invokeHttp(input);
    }
    
    Only change in this file is to let the WorkLight adapter know that i am expecting json as response type instead of xml
  • After that i had to change the way i am parsing the response and using it to display results to the user, the reason being now the structure of the response is different so the callback that reads the response and displays the result has to know about how to handle the changed structure.
    
    function loadContactSuccess(result) {
      console.log("Inside loadContactSuccess " + result);
      var html = '';
      try {
        if (result.status == 200) {
          var contactList = result.invocationResult.contact; 
          var i = 0;
          for (i = 0; i < contactList.length; i++) {
            var currentContact = contactList[i];
            html = html + '<li><a href="javascript:showContactDetail('
                + currentContact.contactId + ')">'
                + currentContact.firstName + ' '
                + currentContact.lastName + '</a></li>';
          }
        }
        jq("#displayContact").html(html);
        jq("#displayContact").listview('refresh');
        busyIndicator.hide();
      } catch (e) {
        busyIndicator.hide();
        displayError(e.toString());
      }
    }
    
    The highlighted code displays how i am getting the actual contact list from the response. This is how the response of the REST service looks like when i hit it directly
    This is how the response that WorkLight adapter is returning to the JavaScript client looks like

Enabling request Log in Embedded Jetty

You can enable NCSA logging in Jetty so that it starts logging every request that enters Jetty with request details like this. It can be very useful for debugging sometimes. 127.0.0.1 - - [11/Apr/2012:15:44:19 +0000] "GET /ManageContact/rest/contact HTTP/1.1" 200 471 "-" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.152 Safari/535.19" 127.0.0.1 - - [11/Apr/2012:15:44:21 +0000] "GET /ManageContact/rest/contact HTTP/1.1" 200 471 "-" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.152 Safari/535.19" 127.0.0.1 - - [11/Apr/2012:15:44:26 +0000] "GET /ManageContact/rest/contact HTTP/1.1" 200 276 "-" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.152 Safari/535.19" You can use following plugin configuration to enable the NCSA logging

<plugin>
  <groupId>org.mortbay.jetty</groupId>
  <artifactId>jetty-maven-plugin</artifactId>
  <version>7.4.5.v20110725</version>
  <configuration>
    <scanIntervalSeconds>10</scanIntervalSeconds>
    <webAppConfig>
      <contextPath>/ManageContact</contextPath>
    </webAppConfig> <!-- <loginServices> <loginService implementation="org.eclipse.jetty.security.HashLoginService"> 
      <name>Test Realm</name> <config>${basedir}/src/etc/realm.properties</config> 
      </loginService> </loginServices> -->
    <connectors>
      <connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
        <port>9000</port>
        <maxIdleTime>60000</maxIdleTime>
      </connector>
    </connectors>
 
    <requestLog implementation="org.eclipse.jetty.server.NCSARequestLog">
      <filename>target/yyyy_mm_dd.request.log</filename>
      <retainDays>90</retainDays>
      <append>true</append>
      <extended>true</extended>
      <logTimeZone>GMT</logTimeZone>
    </requestLog>
 
  </configuration>
</plugin>
After this start the Jetty server and when you hit the service you will notice that a .log file gets created in the target directory with one entry for every request.

Change the default port in Jetty

The Using Embedded Jetty server entry talks about how to embed a Jetty server using Maven in web application. By default the embedded Jetty server starts at port 8080, some times you might want to change it so that it listens on different HTTP port. I wanted to get Jetty to listen on different port and this is how i configured it

<plugin>
  <groupId>org.mortbay.jetty</groupId>
  <artifactId>jetty-maven-plugin</artifactId>
  <version>7.4.5.v20110725</version>
  <configuration>
    <scanIntervalSeconds>10</scanIntervalSeconds>
    <webAppConfig>
      <contextPath>/ManageContact</contextPath>
    </webAppConfig> 

    <connectors>
      <connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
        <port>9000</port>
        <maxIdleTime>60000</maxIdleTime>
      </connector>

    </connectors>
  </configuration>
</plugin>
In this code the connectors element is used for configuring the new port number, in my case i changed it to use port 9000. In the version 6.1 code you would have to configure Jetty like this, name of the SelectorChannelConnector package was different before it was moved to eclipse

<connectors>
<connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
<port>20080</port>
</connector>
</connectors>

Session Storage API in HTML 5

In the Local Storage API in HTML 5 , i blogged about localStorage JavaScript object that you can use for storing data on the client side. The data stored using localStorage API would be available across browser restart and all the windows/tabs opened from that domain. The HTML5 specification also provides sessionStorage object that has same interface as the localStorage object with the difference that the data stored using the sessionStorage API stays only during lifetime of browser session, so you will loose it when you close the browser window or even if you open a new browser window. I wanted to try this out so i changed the localStorage code to use sessionStorage instead of localStorage object, my code looks like this

<!doctype html>
<html>
  <head>
    <script>
 window.onload =function(){
      if(window["sessionStorage"]){
      // Inserting or updating a key/value
   var currentTime = new Date();
      sessionStorage.setItem("key1","First test value" + currentTime.getTime() );  
   if(sessionStorage.getItem("key2") == null)
  sessionStorage.setItem("key2","Second test value"+ currentTime.getTime());  

   document.getElementById("key2Value").innerHTML = sessionStorage.getItem("key2");
      // Getting value of key from session storage
      console.log(sessionStorage.getItem("key1"));
      
      //Removing a key from the session storage
      sessionStorage.removeItem("key1");
      console.log(sessionStorage.getItem("key1"));
      
      //Iterate through all the keys and print them in key=value format
      for( var key in sessionStorage)
        console.log(key + " = "+sessionStorage[key]);
      
      //Iterate through all the keys and print them in key=value format
      for (var i = 0 ; i < sessionStorage.length;i++){
        var keyName = sessionStorage.key(i);
        console.log(keyName +" = "+ sessionStorage[key]);
      }  
      
      //Removing everything
    // sessionStorage.clear();
      }else{
        alert("Browser does not support sessionStorage");
      }
   }
    </script>
  </head>
  <body>
 <div id="key2Value"></div>
  </body>
  </html>
I made a change to check value of key2 if it exists do not set the value and display it on page. Then i opened two different tabs in same browser and keep refreshing page i could see that two different tabs got different values for the same key.

Returning JSON response from JAXRS service

If your using JAXB for Java to XML conversion in the JAXRS service then changing it to support JSON becomes very easy, i wanted to try this option so built this application that can return response in application/xml and application/JSON type, you can download the sample application from here The sample service that i built in this case is ManageContact service, which supports call to return all the contacts, or contact for given contactId and also allows you to search a contact based on last name, in all these cases it returns a Contact object, i did mark the Contact.java class with @XmlRootElement annotation so that JAXBt knows that it is root element.

package com.javaworld.memcache;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Contact {
  private int contactId;
  private String firstName;
  private String lastName;
  private String email;
  
  public int getContactId() {
    return contactId;
  }
  public void setContactId(int contactId) {
    this.contactId = contactId;
  }
  public String getFirstName() {
    return firstName;
  }
  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }
  public String getLastName() {
    return lastName;
  }
  public void setLastName(String lastName) {
    this.lastName = lastName;
  }
  public String getEmail() {
    return email;
  }
  public void setEmail(String email) {
    this.email = email;
  }
  @Override
  public String toString() {
    return "Contact [contactId=" + contactId + ", firstName=" + firstName
        + ", lastName=" + lastName + ", email=" + email + "]";
  }
}
Then i did create this ContactService class that uses JAXRS annotation to define what are the input types as well as what would be the content type of the output, my service looks like this

package com.javaworld.memcache;

import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;

@Path("/contact")
public class ContactService {
  Logger logger = Logger.getLogger(ContactService.class);
  public ContactService(){
    logger.debug("Inside ContactService constructor");
    BasicConfigurator.configure();
  }

  @GET
  @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
  public List getContactList() {
    logger.debug("Entering ContactService.getContactList()");
    ContactDAO contactDAO = new ContactDAOImpl();
    List contactList = contactDAO.getContacts();
    logger.debug("Exiting ContactService.getContactList()");
    return contactList;
  }

  @POST
  @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
  @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
  public void insertContact(@FormParam("contactId") int contactId,
      @FormParam("firstName") String firstName,
      @FormParam("lastName") String lastName,
      @FormParam("email") String email) {
    Contact contact = new Contact();
    contact.setContactId(contactId);
    contact.setFirstName(firstName);
    contact.setLastName(lastName);
    contact.setEmail(email);
    ContactDAO contactDAO = new ContactDAOImpl();
    contactDAO.insertContact(contact);
  }

  @GET
  @Path("/{contactId}")
  @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
  public Contact getContact(@PathParam("contactId") int contactId) {
    ContactDAO contactDAO = new ContactDAOImpl();
    return contactDAO.getContact(contactId);

  }

  @DELETE
  @Path("/{contactId}")
  public void deleteContact(@PathParam("contactId") int contactId) {
    ContactDAO contactDAO = new ContactDAOImpl();
    contactDAO.deleteContact(contactId);
  }

  @PUT
  @Path("/{contactId}")
  @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
  @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
  public void updateContact(@PathParam("contactId") int contactId,
      @FormParam("firstName") String firstName,
      @FormParam("lastName") String lastName,
      @FormParam("email") String email) {
    Contact contact = new Contact();
    contact.setContactId(contactId);
    contact.setFirstName(firstName);
    contact.setLastName(lastName);
    contact.setEmail(email);
    ContactDAO contactDAO = new ContactDAOImpl();
    contactDAO.updateContact(contact);
  }
  
  @GET
  @Path("/search")
  @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
  public List searchContact(@QueryParam("lastName") String lastName) {
    ContactDAO contactDAO = new ContactDAOImpl();
    return contactDAO.searchContact(lastName);

  }

}
My rest methods declare that they produce both MediaType.APPLICATION_JSON and MediaType.APPLICATION_XML content type. Now the next question would be which content type should it return when it gets request. So the rule is since MediaType.APPLICATION_JSON is first content type it becomes the default content type, so if you dont set content type it returns JSON, if you set content type to XML in request it returns XML like this Response when i did not set Accept header, so it returns JSON which is default content type
But if i want XML as response type i can set Accept header with value equal to application/xml and it returns XML
In Jersey configuration all you have to do to support JSON is make sure that you add jesey-json related jars in the classpath, which has JSON message writer which takes over when request has accept equal to JSON and returns JSON response

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.javaworld.memcache</groupId>
  <artifactId>ManageContact</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>ManageContact Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
      <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.4.2</version>

    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.4.2</version>

    </dependency>

    
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-entitymanager</artifactId>
      <version>3.4.0.GA</version>
    </dependency>
    <dependency>
      <groupId>org.apache.derby</groupId>
      <artifactId>derbyclient</artifactId>
      <version>10.7.1.1</version>
    </dependency>

    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>commons-beanutils</groupId>
      <artifactId>commons-beanutils</artifactId>
      <version>1.8.0</version>
    </dependency>
    <dependency>
      <groupId>commons-beanutils</groupId>
      <artifactId>commons-beanutils</artifactId>
      <version>1.8.0</version>
    </dependency>
    <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-servlet</artifactId>
            <version>1.12</version>
        </dependency> 
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-json</artifactId>
            <version>1.12</version>
        </dependency> 
  </dependencies>
 
</project>

Local Storage API in HTML 5

The HTML 5 specification allows web applications to store up to 5 MB of data per domain on the client side and the API that you can for it is is called localStorage, this is a sample web page that performs different localStorage API related operations.

<!doctype html>
<html>
  <head>
    <script>
      if(window["localStorage"]){
      // Inserting or updating a key/value
      localStorage.setItem("key1","First test value");  
      localStorage.setItem("key2","Second test value");  
      
      // Getting value of key from local storage
      console.log(localStorage.getItem("key1"));
      
      //Removing a key from the local storage
      localStorage.removeItem("key1");
      console.log(localStorage.getItem("key1"));
      
      //Iterate through all the keys and print them in key=value format
      for( var key in localStorage)
        console.log(key + " = "+localStorage[key]);
      
      //Iterate through all the keys and print them in key=value format
      for (var i = 0 ; i < localStorage.length;i++){
        var keyName = localStorage.key(i);
        console.log(keyName +" = "+ localStorage[key]);
      }  
      
      //Removing everything from localStorage
     localStorage.clear();
      }else{
        alert("Browser does not support localStorage");
      }
    </script>
  </head>
  <body>
   Hello from Local Storage API
  </body>

</html>
This is screen shot of how the keys stored in local Storage look like in Chrome.