Getting started with the Directory Listing sample application

This page is the starting point for learning about the Directory Listing application. The following topics are covered:

Overview

The Directory Listing sample application was created to complement the use of the dojox.data.FileStore store from the Dojo Toolkit for JavaScript. The Directory Listing sample demonstrates how to develop a JAX-RS Representational State Transfer (REST) application that can receive and respond to requests originating from the dojox.data.FileStore data store.

The dojox.data.FileStore data store is a lightweight JavaScript implementation for accessing details about a remote file system. This data store and the server side JAX-RS resource do not inflate the entire hierarchy of the requested file system path. This allows it to quickly return information for the requested path while providing hooks for lazy loading the subdirectories. This is an example of how a Dojo data store can do lazy loading, and how to create the JAX-RS resource that conforms to the expectations of the dojox.data.FileStore.

The primary purpose of this Directory Listing sample is to demonstrate the simplicity and capability of the JAX-RS resource class. However, to fully demonstrate this simplicity, the dojox.data.FileStore data store is included in a larger Dojo application. Read about writing the Directory Listing application for an example.

Prerequisites

Product prerequisite Version
Java Technology Edition 5.0 and later
Java Platform, Enterprise Edition 5 (Java EE) application server and later

WebSphere Application Server Version 6.1.0.x and later

WebSphere Application Server Community Edition Version 2.X.

Web browser Any modern web browser, such as: Internet Explorer 7 and later Mozilla Firefox 3.x and later Google Chrome Safari Opera
Develoment IDE (Optional) Eclipse version 3.X

Limitations

The Directory Listing sample application is not intended for deployment to production servers. It is for development and educational purposes only.

All source code for the JAX-RS application, resource, and Web pages is provided as is for you to use, copy, and modify without royalty payment when you develop applications that run with WebSphere software. You can use the sample code either for your own internal use or for redistribution as part of an application, or in your products.

Writing the Directory Listing sample application

The design of the Directory Listing sample application demonstrates how to approach development of Ajax-based applications with the Dojo Toolkit in a Java EE environment. To meet these goals, the two parts of a Java EE application, the client side and the server side, are organized into simple operations that perform a useful function. It follows the basic pattern that Java EE applications use when incorporating Ajax technologies.

Assumptions

The following sections assume that you are already familiar with the JavaScript framework for Dojo, and do not explain in detail the sample Dojo client application or the Dojo dojox.data.FileStore data store that is being used.

The client

The client is the web page that is served to the browser. In the web page, the dojox.data.FileStore data store is instantiated and declared as the store to a dijit.tree.ForestStoreModel, which is declared as the model to a dijit.Tree widget. The dijit.Tree widget provides the visual representation of the file system hierarchy. It provides plus and minus symbols next to the directories in the tree that users click to expand or contract. When the user clicks the plus symbol, the requested path is passed to the JAX-RS resource by the dojox.data.FileStore data store and performs the lazy loading feature. For more specific information about the client side design read about the client side design of the Directory Listing sample application.

The server

The server provides the infrastructure for processing services and serving Web pages. In this application, the server side is a JAX-RS resource class that receives and processes GET queries from the dojox.data.FileStore data store, and responds according to the requirements of this data store and the enclosing Dojo application. For more specific information about the server side design, read about the server side design of the Directory Listing sample application.

Directory Listing sample application for the client

The Directory Listing sample application uses the dojox.data.FileStore data store to query the JAX-RS resource for information about a path on the server's file system. The dojox.data.FileStore object is configured with an options string, a URL to the service, and the pathAsQueryParam flag to indicate that the path being requested should be sent as a ?path=/the/path query parameter. Without this flag, the request would be sent as an appendage to the URL.

The application built around the dojox.data.FileStore, model, and tree, includes dojo.form.CheckBox widgets to enable or disable support of individual features of the dojox.data.FileStore data store. They are included as part of the application to demonstrate the capability of the data store. Enabling or disabling a feature by clicking an individual checkbox requires that the data store resend the initial request to the server, and refresh the model and tree, which you will see as you test these features.

The search features of dojox.data.FileStore are also handled in the application. A file attribute available in a drop-down list can be selected along with text (including wild card asterisks) to do matching. The search can be further narrowed by selecting "Ignore capitalization" or "Deep search". Finally, to limit or control the amount of items returned in the search, the start index can be provided along with the count of the maximum number of entries that should be returned.

In addition to the expected features of a standard Dojo data store, model, and tree, the application calls a special feature of the JAX-RS resource to pre-populate a directory tree so the client renders a useful set of data. The application uses dojo.xhrPut to send a PUT request to the JAX-RS resource, indicating to the JAX-RS resource that it should populate a directory hierarchy for use by the sample.

The primary purpose of this Directory Listing sample application is to demonstrate the simplicity of getting a JAX-RS resource developed that can receive and process queries from the dojox.data.FileStore. Therefore, the exercise of understanding and coding the client is left to the reader. However, it should be noted that this client is written to use Dojo features programmatically to demonstrate all of the features of the dojox.data.FileStore and to eliminate the need to manually build up a file system hierarchy. The visual dijit.Tree, and its inclusion of the model and store could have also been written declaratively in just a few short lines of HTML code, shown here:

<div dojoType="dojox.data.FileStore"
     jsId="myStore" url="rest/directorylisting" pathAsQueryParam="true"></div>
<div dojoType="dijit.tree.ForestStoreModel"
     jsId="myModel" store="myStore" rootId="myfiles" rootLabel="Files" childrenAttrs="children"></div>
<div dojoType="dijit.Tree"
     id="mytree" model="myModel"></div>

For more information on how to use the client side, refer to the application source code. Each section in the HTML document is commented, explaining the purpose of the code block.

Directory Listing sample application for the server

At a minimum, the Directory Listing sample application for the server must be capable of receiving a GET request with a path appended to the path listening for the request or a ?path=/myPath query parameter attached to the GET request. In an effort to make the setup of the sample as convenient as possible, the JAX-RS resource includes a method listening for PUT queries that will pre-populate a file system directory hierarchy so the Dojo client may call it prior to demonstrating the dojox.data.FileStore features. This eliminates the need to manually create a file system hierarchy.

The JAX-RS runtime environment has built-in capability of splitting any query parameters into their name/value pairs, and passing them as parameters to the Java method receiving the GET request.

Creating the JAX-RS resource class that will receive the HTTP requests

package com.ibm.websphere.mobile.appsvcs.sample.directorylisting.resources;

import javax.ws.rs.Path; // Full import list not shown.

@Path("/directorylisting")
public class DirectoryListingService
{
   // ...
}

Note that this JAX-RS resource class is declared to have a URL segment of "/directorylisting". This resource class will handle requests targeted at http://<server>:<port>/<context-root>/<uri-mapping>/directorylisting.

The context root is defined by the application.xml file if your web archive file (.war) is packaged in an enterprise archive (.ear) file. If the .war is installed by itself, the context root is defined at install time by the user. The uri mapping is defined in the WEB-INF/web.xml in the .war file.

Creating the JAX-RS resource methods

The dojox.data.FileStore data store sends GET requests. In the client it has been configured to send the desired path as a query parameter and a subset of the various optional arguments described in dojox.data.FileStore, including the dojo.data.api.Read query protocol. For example, the dojox.data.FileStore data store might send a GET request as http://<server>:<port>/<context-root>/<uri-mapping>/directorylisting?path=/the/path. Given we need to handle the path as part of the URL and alternatively as query parameter, we have a JAX-RS resource method for each. They each call into a common method to handle the logic of the service.

// Query parameters and values
private static final String QUERY_OPTIONS = "options";
private static final String QUERY_PATH = "path";
private static final String QUERY_QUERY = "query";
private static final String QUERY_QUERYOPTIONS = "queryOptions";
private static final String QUERY_START = "start";
private static final String QUERY_COUNT = "count";

// Default value for start and count query parameters.
private static final String NO_VALUE_STRING = "-1";
private static final int NO_VALUE_INT = -1;

@GET
@Produces(MediaType.APPLICATION_JSON)
public JSONObject getFileListWithPathInParam(
        @Context ServletConfig servletConfig,
        @Context HttpHeaders httpHeaders,
        // Note, the path is obtained with @QueryParam.
        @QueryParam(QUERY_PATH) String path,
        @QueryParam(QUERY_OPTIONS) String options,
        @QueryParam(QUERY_QUERY) String query,
        @QueryParam(QUERY_QUERYOPTIONS) String queryOptions,
        @DefaultValue(NO_VALUE_STRING) @QueryParam(QUERY_START) String startParam,
        @DefaultValue(NO_VALUE_STRING) @QueryParam(QUERY_COUNT) String countParam)
{
    return getFileListCommon(servletConfig, path, options, query, queryOptions, startParam, countParam);
}

@GET
// JAX-RS will call this method if the URL has more than the root path.
@Path("{path:.*}")
@Produces(MediaType.APPLICATION_JSON)
public JSONObject getFileListWithPathInUri(
        @Context ServletConfig servletConfig,
        @Context HttpHeaders httpHeaders,
        // Note, the path is obtained with @PathParam.
        @PathParam(QUERY_PATH) String path,
        @QueryParam(QUERY_OPTIONS) String options,
        @QueryParam(QUERY_QUERY) String query,
        @QueryParam(QUERY_QUERYOPTIONS) String queryOptions,
        @DefaultValue(NO_VALUE_STRING) @QueryParam(QUERY_START) String startParam,
        @DefaultValue(NO_VALUE_STRING) @QueryParam(QUERY_COUNT) String countParam)
{
    return getFileListCommon(servletConfig, path, options, query, queryOptions, startParam, countParam);
}

The first @GET annotation declares that the method will receive HTTP GET requests at the URL ending with directorylisting per the class level @Path annotation. Note the use of the @QueryParam annotation to access the path being requested in the service.

The second @GET annotation further qualifies the @Path with a regular expression, "{path:.*}" which maps to any characters being present after the class level @Path annotation. Therefore, when the second method is called, the path is expected to be in the URL. Note the use of the @PathParam to access the value of the path being requested in the service.

Each of the two methods include the @Produces annotation. This helps the JAX-RS runtime match the inbound message with the Java method. The JAX-RS runtime will try to match the inbound message Accept header with the @Produces value. It also informs the JAX-RS runtime in what format the response should be.

Creating the JAX-RS core application class

At this point, one more class is required to complete the application. JAX-RS initializes an application and its resources and providers through the class that extends javax.ws.rs.core.Application. Therefore, create the following class.

package com.ibm.websphere.mobile.appsvcs.sample.directorylisting;

import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;

public class DirectoryListingApplication extends Application
{
   @Override
   public Set<Class<?>> getClasses()
   {
      Set<Class<?>> classes = new HashSet<Class<?>>();
      classes.add(DirectoryListingService.class);
      return classes;
   }
}

Enabling the JAX-RS application in web.xml

Below are the critical parts to enable this JAX-RS application.

...
<servlet-name>JAXRSServlet</servlet-name>
<servlet-class>com.ibm.websphere.jaxrs.server.IBMRestServlet</servlet-class>
<init-param>
   <param-name>javax.ws.rs.Application</param-name>
   <param-value>com.ibm.websphere.mobile.appsvcs.sample.directorylisting.DirectoryListingApplication</param-value>
</init-param>
...
<servlet-mapping>
   <servlet-name>JAXRSServlet</servlet-name>
   <url-pattern>/rest/*</url-pattern>
</servlet-mapping>
...

Note the servlet-class and the init-param with param-name "javax.ws.rs.Application". This is the standard way to declare the servlet implementation and pass the reference of the class that extends javax.ws.rs.core.Application to the JAX-RS runtime.

With the inclusion of the WEB-INF/web.xml, the compiled application, and the proper library files in the WEB-INF/lib/ directory of the .war file, the application can be installed to an application server. See the contents of the included sample if you want to see the list of required libraries. The included sample application is in the form of a .war file packaged within a .ear file. Within the .ear file is the standard application.xml file, which specifies the URL context root of "/appsvcs-directorylisting". Thus, the URL to the index.html file is http://<server>:<port>/appsvcs-directorylisting/. Note that the URL specified in the index.html file in the sample application is rest/directorylisting, which is relative to the location of the index.html file, and is the result of the concatenation of the URL pattern in the web.xml file and the @Path annotation in the JAX-RS resource class.

Get method implementation

The getFileListCommon method is called from each of the two JAX-RS resource methods described earlier. The list below describes each parameter. The format and content of the parameters aligns with the documentation for dojox.data.FileStore. The first two parameters are always provided by the underlying servlet container. The remaining parameters are optional. Therefore, you can specify null or accept the default values.

protected JSONObject getFileListCommon(
        ServletConfig servletConfig,
        HttpHeaders httpHeaders,
        String path,         // Path of the request, from the URL or an HTTP parameter
        String options,      // JSON array, could contain expand, showHiddenFiles, dirsOnly
        String query,        // JSON array of name/value pairs for a filtered search
        String queryOptions, // JSON array of settings for a deep search and/or ignoreCase
        String startParam,   // Index of results to start with in the returned list
        String countParam)   // Number of items to return in the result list
{
    // ...
}

Methods exist in the source code to validate each of the parameters and in some cases put them into a form that is easy to query later. See the dojox.data.FileStore documentation for descriptions of these parameters.

At this point, you have successfully received the request from the dojox.data.FileStore data store. It expects a reply in JSON format, which can be constructed using information from the requested path in a JSONObject. The code sample below shows how to build the JSON formatted response.

 // Attribute names
 private static final String ATTRIB_ITEMS = "items";
 private static final String ATTRIB_NAME = "name";
 private static final String ATTRIB_PATH = "path";
 private static final String ATTRIB_PARENTDIR = "parentDir";
 private static final String ATTRIB_SIZE = "size";
 private static final String ATTRIB_DIRECTORY = "directory";
 private static final String ATTRIB_CHILDREN = "children";
 private static final String ATTRIB_MODIFIED = "modified";

...
// Assume you have already found the file you want,
// instantiated as a Java file in variable "file"
JSONArray fileList = new JSONArray();
if (path.equals("/") && file.isDirectory()) {
    // Query param "path" was not passed, was blank, or "/"
    File[] children = file.listFiles();
    if (children != null && children.length > 0) {
        for (int i = 0; i < children.length; i++) {
            // Call common code to append the list if the file is acceptable.
            // This also searches recursively if necessary.
            appendFileList(children[i], fileList);
        }
    }
    JSONObject items = new JSONObject();
    items.put(ATTRIB_ITEMS, fileList);
    logger.exit();
    return items;
} else {
    // This is a single identity lookup for a specific path.
    // A JSONObject representing the file will be returned.
    JSONObject jsonFile = appendFileList(file, null);
    if (jsonFile == null) {
        // Handle error
        ...
    } else {
        logger.exit();
        return jsonFile;
    }
}
...

...
private JSONObject appendFileList(File file, JSONArray fileList) {
   ...
   JSONObject item = new JSONObject();

   if (file != null) {
      item.put(ATTRIB_NAME, file.getName());
      item.put(ATTRIB_MODIFIED, new Long(file.lastModified()));
      item.put(ATTRIB_SIZE, new Long(file.length()));
      item.put(ATTRIB_PATH, getFileAttribute(ATTRIB_PATH, file));
      item.put(ATTRIB_PARENTDIR, getFileAttribute(ATTRIB_PARENTDIR, file));
      item.put(ATTRIB_DIRECTORY, new Boolean(file.isDirectory()));
      // See the sample code for details on traversing directory trees of files
      ...
      // Add another item to the list.
      fileList.add(item);

   }
   ...
}

At this point, we have a JAX-RS service resource capable of receiving and responding to the expectations of the dojox.data.FileStore data store. The implementation details of traversing the file system, managing the options from the options query parameter, and allowing configuration of the root directory are left for the reader to see in the source code.

Viewing the source code of the Directory Listing sample application

The source code of the Directory Listing sample application is provided within the .war web module file within the appsvcs-directorylisting.ear file. There are two approaches to viewing the source code: through an Eclipse-based Integrated Development Environment (IDE) or by decompressing the appsvcs-directorylisting.ear file, then decompressing the .war file contained inside.

Locating the enterprise EAR file

The first step in viewing the source code is locating the DirectoryListing.ear file. If you have installed the IBM WebSphere Application Server Feature Pack for Web 2.0 and Mobile, then you can find the EAR file in your installation tree.

For example, if you installed the feature pack in the following location:

Platform Location
Linux and UNIX: /opt/WebSphere/AppServer
z/OS mount point: <install_root>
Windows: c:\WebSphere\AppServer

Then you can find the EAR file at:

Platform Location
Linux and UNIX: /opt/WebSphere/AppServer/web2mobilefep_1.1/samples/directorylisting/appsvcs-directorylisting.ear
z/OS: <install_root>/web2mobilefep_1.1/samples/directorylisting/appsvcs-directorylisting.ear
Windows: c:\WebSphere\AppServer\web2mobilefep_1.1\samples\directorylisting\appsvcs-directorylisting.ear

Viewing the source code in an Eclipse-based IDE

Using an Eclipse-based IDE is the simplest approach to examining the source code of the WAR file. Use any Eclipse 3.2.X, 3.3.X IDE with the Web Tools Project 2.5 or higher, or Rational Application Developer, Version 7.0 or higher, can import the web archive (WAR) file when you complete the following steps:

  1. Expand the appsvcs-directorylisting.ear file.
  2. From the Eclipse IDE menu, select File > Import.
  3. In the presented panel, expand the Web option, then select WAR file, and click Next.
  4. In the WAR File entry field, click Browse, and select the file you located earlier.
  5. Accept defaults for the project name, if they are acceptable, and click Finish.

When the import process completes, a new project, DirectoryListing, exists in the Eclipse workspace. The application source code can be accessed from the DirectoryListing project. To access the client or server code, see the following table for source code locations in the DirectoryListing Eclipse project tree.

Source Code Location
Client side (web browser) WebContent/index.html: Contains the Dojo Widget definitions and client script functions. This file loads the unoptimized Dojo profile.
Server side Java resources: src/com.ibm.websphere.mobile.appsvcs.sample.directorylisting/ DirectoryListingApplication.java: Double-click this file to load the source code.
Java resources: src/com.ibm.websphere.mobile.appsvcs.sample.directorylisting. resources/DirectoryListingService.java: Double-click this file to load the source code.

Viewing the source code by extracting the WAR file

Web application archives are file archives compressed using the ZIP algorithm. Therefore, the archive file can be expanded by any number of tools for compressing files, including the Java archive (JAR) program. The following steps assume that the user chooses their favorite tool to create compressed files.

  1. Expand the DirectoryListing.ear file you located earlier into a directory on your system using your favorite ZIP compression file tool. The following steps assume that EXPAND_DIR/DirectoryListing is the correct location.
  2. List the files in the EXPAND_DIR/DirectoryListing directory that DirectoryListing.ear file was expanded into.

After you have expanded the EAR file contents, expand the .war file contents. Then you can access the source code. To access the client or server code, see the following table for source code locations in the EXPAND_DIR/DirectoryListing directory.

Source Code Location
Client side (web browser) index.html: Contains the Dojo widget definitions and client script functions.
Server side WEB-INF/classes/com/ibm/websphere/mobile/appsvcs/sample/directorylisting/ DirectoryListingApplication.java
WEB-INF/classes/com/ibm/websphere/mobile/appsvcs/sample/directorylisting/ resources/DirectoryListingService.java

Installing the Directory Listing sample application

Refer to the following version-specific installation instructions:

WebSphere Application Server installation instructions

This section describes the procedure for installing the Directory Listing sample application on Version 6.1.0.X and later of the IBM WebSphere Application Server. It is assumed that you are familiar with application installation and administration for the application server.

Before you begin

Locate the Directory Listing sample application enterprise archive (EAR) file that is provided with your product installation. You can find the EAR file in your installation tree where you installed the IBM WebSphere Application Server Feature Pack for Web 2.0 and Mobile. For example, if you installed the feature pack in the following location:

Platform Location
Linux and UNIX: /opt/WebSphere/AppServer
z/OS mount point: <install_root>
Windows: c:\WebSphere\AppServer

Then you can find the EAR file at:

Platform Location
Linux and UNIX: /opt/WebSphere/AppServer/web2mobilefep_1.1/samples/application_services/directorylisting/appsvcs-directorylisting.ear
z/OS: <install_root>/web2mobilefep_1.1/samples/application_services/directorylisting/appsvcs-directorylisting.ear
Windows: c:\WebSphere\AppServer\web2mobilefep_1.1\samples\application_services\directorylisting\appsvcs-directorylisting.ear

Installing the Directory Listing sample application using the administrative console

  1. Log into the administrative console for the application server.
  2. Navigate to Applications > New Application. (Note: In WebSphere Application Server Version 6.1, select Install New Application)
  3. Select New Enterprise Application. (Note: In WebSphere Application Server Version 6.1, skip this step)
  4. Browse your file system, and select the appsvcs-graphics.ear file that you located earlier. Click Next.
  5. Click Next to prepare for the application installation. (Note: In WebSphere Application Server Version 6.1, skip this step)
  6. Click Next to accept the default installation options.
  7. Click Next to accept the default options for map modules to servers.
  8. Click Next to accept the default options for Metadata for modules. (Note: In WebSphere Application Server Versions 6.1 and 7, skip this step)
  9. Click Next to accept the default options for map virtual hosts for web modules.
  10. Review the summary of the installation options.
  11. Click Finish.
  12. Click Save to the master configuration.
  13. Navigate to Applications > Application Types > WebSphere Enterprise Applications. (Note: In WebSphere Application Server Version 6.1, Navigate to Applications > Enterprise Applications)
  14. Select the IBM WebSphere Application Server - Directory Listing sample application, and click Start.

Access the installed application demo client

Point your web browser to your application server installation: http://<application server hostname>:<port>/appsvcs-directorylisting/

The application server host name and port number are specific to your application server installation. An application server default installation web container port is 9080. If you are running your web browser on the same workstation as your application server installation and have taken all the default values, then use the following URL: http://localhost:9080/appsvcs-directorylisting/.

WebSphere Application Server Community Edition Version 2.X installation instructions

This section describes the procedure for installing the Directory Listing sample application into Version 2.X of the IBM WebSphere Application Server Community Edition. It is assumed that you are familiar with application installation and administration for the application server.

Before you begin

Locate the Directory Listing sample application enterprise archive (EAR) file that is provided with your product installation. You can find the EAR file in your installation tree where you installed the IBM WebSphere Application Server Feature Pack for Web 2.0 and Mobile. For example, if you installed the feature pack in the following location:

Platform Location
Linux and UNIX: /opt/WebSphere/AppServerCommunityEdition
Windows: c:\WebSphere\AppServerCommunityEdition

Then, you can find the EAR and library files at:

Platform Location
Linux and UNIX: /opt/WebSphere/AppServerCommunityEdition/web2mobilefep_1.1/AppServices/samples/directorylisting/appsvcs-directorylisting.ear
Windows: c:\WebSphere\AppServerCommunityEdition\web2mobilefep_1.1\AppServices\samples\directorylisting\appsvcs-directorylisting.ear

Installation through the administrative console

Log into the administrative console for the application server.

  1. Click Applications > Deployer in the left menu. (Note: In WebSphere Application Server Community Edition Version 2.0, click Applications > Deploy New)
  2. In the Archive field, browse your file system, and select the appsvcs-directorylisting.ear file that you located earlier. Leave the Plan field empty and the default options selected. Then, click Install.

The application starts automatically, and installation is complete.

Access the installed application demo client

Point your Web browser to your application server installation: http://<application server hostname>:<port>/appsvcs-directorylisting/.

The application server host name and port is specific to your application server installation. The WebSphere Application Server Community Edition server default installation Web container port is 8080. If you are running your browser on the same workstation as your application server installation and have accepted all the default values, then use the following URL:

http://localhost:8080/appsvcs-directorylisting/