Deploying Servlets on Smart Cards: Portable Web Servers with Java Card 3.0

   
By Bruce Hopkins, January 2010  
No, that's not a typo. No, I'm not talking about technology that will be available 10 years from now. Java Card 3.0 technology is available today that allows application developers to create and deploy servlet applications on smart card devices. This article shows developers how to get started with developing servlets with the Java Card Connected Development Kit 3.0.2.
Contents
 
Background
Comparing JavaCard 2 to JavaCard 3
Getting Started the Java Card Connected Development Kit and the Persistence Example
Conclusion
 

Background

In previous versions of the Java Card specification, Java developers were significantly limited in the breadth and depth of the applications that could be created for Java Card 2 devices, such as:

  • A very strict subset of Java APIs, with only JDK 1.0 features
  • No support for java.lang.String objects
  • No threads
  • No garbage collection
  • No support for networking
  • No native support for .class files
  • No dynamic class loading
  • 1-D Arrays
  • 8-bit CPUs
  • 8kB of RAM

Despite these limitations, Java Card technology became the most widely deployed Java platform in the world with over 3.5 billion deployments. Java Card 3.0 technology has several significant enhancements over the Java Card 2 platform, as explained in the following sections.

Comparing JavaCard 2 to JavaCard 3

As you can see from the sequence diagrams in Figures 1 and 2 located below, creating a complete application that involved using Java Card 2 technology could be tedious.

 
Figure 1. A Sequence Diagram Depicting the Interactions Between a Desktop Application and a Java Card 2 Application
 
 
 
Figure 2. A Sequence Diagram Depicting the Interactions Between a Mobile Application and a Java Card 2 Application
 
 

As you can see from the preceding figures, both the desktop and mobile applications need to eventually use the APDU (application protocol data unit) protocol to communicate with applications (also known as applets) located on the Java Card 2 smart card. In some cases, however, the API restrictions -- combined with having to use byte arrays for all interaction with the smart card -- were major deterrents to attracting enterprise Java developers to the Java Card platform.

However, the Java Card 3 platform provides significant improvements to its predecessor, and those changes should appeal not only to enterprise and desktop developers, but to mobile developers as well. The Java Card 3 platform includes support for the following features:

  • An API based upon a CLDC subset, with Java 6 features
  • Annotations
  • byte, short, int, long, char and java.lang.String
  • Threads
  • Servlets
  • Garbage collection of objects
  • TCP/IP networking
  • HTTP and HTTPS
  • .class files
  • .war deployment files
  • Dynamic class loading
  • 2-D Arrays
  • 32-bit CPUs
  • 24kB of RAM

Figure 3, shown below is a sequence diagram showing the steps and actions involved in creating a complete application using the Java Card 3 platform.

 
Figure 3. A Sequence Diagram Depicting the Interactions Between a Mobile or Desktop Application and a Java Card 3 Application
 
 

With Java Card 3 technology, smart card application development has instantly become a lot easier, and has now taken a significant leap-ahead in capability so that the following scenarios are possible:

  • Developers no longer need to create individual client applications to access the data and resources on the smart card. The only client interface needed is an ordinary web browser.
  • Smart Card applications are now fully functioning TCP-based servers. These server applications are Java servlets, and they have a full HTTP stack to allow them to process GET requests, POST requests, headers, cookies, sessions, and so on.
  • You can secure the data between the client (the browser) and the server (the smart card) by using the industry-standard SSL (secure sockets layer).

Getting Started the Java Card Connected Development Kit and the Persistence Example

Did you know that Java Card applications have access to two heap spaces? One of them is volatile, which means that it acts like RAM, so all information stored in that heap location is lost after the system is reset (that is, when the card is removed and inserted). The other heap area is non-volatile, so data stored in that location is truly persistent, even after a system reset.

To get clear understanding of how to store data on the card in the volatile heap allocation, let's take a look at the Persistence example from the Java Card Connected Development Kit 3.0.2. Table 1, shown below, provides a detailed breakdown of the files contained within the %folder_root%\JCDK3.0.2_ConnectedEdition\samples\web\Persistence folder.

Table 1. Description of Files and Folders Within the Persistence Example
Folder/File Name
Description
/build.xml
This is the primary ant build xml file. The project name, base directory, and import file are specified in this file.
/build/
This is the parent folder that contains the build arifacts that will be automatically created by ant. These artifacts include the intermediary /WEB-INF/classes folder, which will be packaged into the final .war file
/config/
This is the parent folder that contains the configuration files.
/config/build-impl.xml
This is an autogenerated ant build file that is imported from the primary build.xml file. It is not recommended for developers to modify this file.
/config/genfiles.properties
This is an autogenerated file used by NetBeans. It is not recommended for developers to modify this file.
/config/project.properties
This is the main property file that sets several configurable properties such as the main servlet, the main URL, as well as the web context path.
/config/project.xml
This the NetBeans project XML file.
/dist
This is the parent folder containing the redistributable items / artifacts after the build process is complete.
/dist/Presistence.signature
This is a binary file that contains a digital signature.
/dist/Presistence.war
This is the deployable .war file that will be loaded on the Java Card.
/html/
This is the parent folder containing the index.html as well as the accompanying images.
/html/index.html
This is a simple placeholder html page that redirects to the "index" path of the JavaCard WAR application.
/html/images/
This is the folder that contains the images referenced by the JavaCard servlet.
/META-INF/
This is the parent folder containing manifest files.
/META-INF/javacard.xml
This is the JavaCard application descriptor file.
/META-INF/MANIFEST.MF
This is a simpe manifest file that's common for JAR and WAR files.
/src
This is the parent folder for all Java source code.
src/.../PresistanceServlet.java
This is a servlet that shows the contents of the database, adds new items to the database, and deletes existing items.
src/.../IndexServlet.java
This is a servlet that has been mapped to the "index" path of the Java Card WAR application. This servlet presents an HTML form, which invokes the HelloWorldServlet card application.
src/.../Database.java
JavaCard 3 applications have two heap spaces (volatile and non-volatile). This is a simple class that store data in volatile heap.
/WEB-INF
This is the parent folder that contains the assests used by the servlets.
/WEB-INF/footer.i
This is a part of an HTML file.
/WEB-INF/header.i
This is a part of an HTML file.
/WEB-INF/index.i
This is a part of an HTML file.
/WEB-INF/web.xml
This is a typical web.xml that defines and maps the servlets with URLs.
 

Listing 1 is the code for Database.java, a class that allows multiple users in different browser sessions to store and retrieve data objects from the volatile heap space of a Java Card application.

Listing 1. Database.java
package com.sun.jchowto.persistence;

import java.util.Vector;

/**
 * 
 */
public class Database {
    private static Vector<String> items = new Vector<String>();

    /**
     * @param item
     */
    public static void addItem(String item) {
        if (!items.contains(item)) {
            items.addElement(item);
        }
    }

    /**
     * @return
     */
    public static Vector<String> getItems() {
        return items;
    }

    /**
     * @param item
     * @return
     */
    public static boolean delete(String item) {
        return items.removeElement(item);
    }
}
       

As you can see, the code for the database is pretty simple as it is primarily a wrapper class that allows users to store, retrieve, and delete objects from a String-typed Vector. It demonstrates the capabilities of the Java Card 3 platform well, since it shows that you can use generics, first introduced in the Java SE 5.0.

Listing 2 is the code for the Java Card 3 servlet that accesses the database.

Listing 2. PersistenceServlet.java
package com.sun.jchowto.persistence;

import java.io.IOException;
import java.io.PrintWriter;

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

/**
 * A Simple Persistence Servlet.
 */
public class PresistanceServlet extends HttpServlet {    /* (non-Javadoc)
     * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
     */


    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {

        String op = request.getParameter("op");
        String item = request.getParameter("item");

        if (op != null) {
            if (op.equals("Add")) {
                if (item != null) {
                    Database.addItem(item);
                }
            } else if (op.equals("Delete")) {
                if (item != null) {
                    Database.delete(item);
                }
            }
        }

        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        RequestDispatcher dispatcher = null;

        dispatcher = request.getRequestDispatcher("/WEB-INF/header.i");
        dispatcher.include(request, response);

        out.println("        <tr>");
        out.println("            <td bgcolor=\"#FFFFFF\" align=\"center\" valign=\"middle\">");
        out.println("                <table bgcolor=\"#000000\" border=\"0\" width=\"100%\" cellspacing=\"1\" cellpadding=\"15\">");
        out.println("                    <tr>");
        out.println("                        <td align=\"center\" bgcolor=\"#FFFFFF\">");

        out.println("</b><big><big>Simple Database</big></big></b>");
        out.println("<form method=\"get\" action=\"database\">");
        out.println("   <table border = 0>");
        out.println("       <tr>");
        out.println("           <td>Item : </td><td colspan=2><input type=\"text\" name=\"item\"></input></td>");
        out.println("       </tr>");
        out.println("       <tr>");
        out.println("           <td> </td>");
        out.println("           <td><input type=\"submit\" name=\"op\" value=\"Add\"></td>");
        out.println("           <td><input type=\"submit\" name=\"op\" value=\"Delete\"></td>");
        out.println("       </tr>");
        out.println("       <tr>");
        out.println("           <td colspan=3><hr></td>");
        out.println("       </tr>");
        out.println("       <tr>");
        out.println("           <td colspan=3><b>Items in Database</b></td>");
        out.println("       </tr>");
        out.println("<tr>");
        out.println("   <td colspan=3><textarea readonly rows=\"5\" cols=\"20\">");
        if(Database.getItems().size() <= 0) {
            out.print(" \n \nDatabase is Empty;\n \n ");
        } else {
        for (String str : Database.getItems()) {
            out.println(str);
        }
        }
        out.println("</textarea></td>");
        out.println("</tr>");
        out.println("   </table>");
        out.println("</form>");

        out.println("                        </td>");
        out.println("                    </tr>");
        out.println("                </table>");
        out.println("            </td>");
        out.println("        </tr>");

        dispatcher = request.getRequestDispatcher("/WEB-INF/footer.i");
        dispatcher.include(request, response);

    }
}
       

As you can see from the preceding code listing, PersistenceServlet.java works like any other subclass of HTTPServlet. All you need to do is override the HTTP methods that you want, and replace them with your own code. In this case, we're only supporting HTTP GET requests. If the HTTP parameter "op" is set to "Add", then we'll add a new item to the database. If, however, "op" is set to "Delete", then the specified item will be removed from the database.

In either case, the servlet completes its work by showing the final list of contents in the database. The Java Card 3 platform doesn't support JSP files, so you should notice in Listing 2 that much of the application is dedicated to creating the HTML response. Figure 4 is the PersistenceServlet in action.

 
Figure 4. Adding My Favorite Stock Symbols to the PersistenceServlet.java
 
 

Conclusion

The Java Card 3 platform is lightyears ahead of its predecessor. It includes several new features that allow developers to create extremely sophisticated applications using Java servlet technology. Are you ready for a new generation of servlet applications that execute on a smart card?

Rate This Article

 
 

Discussion

We welcome your participation in our community. Please keep your comments civil and on point. You can optionally provide your email address to be notified of replies—your information is not used for any other purpose. By submitting a comment, you agree to these Terms of Use.