Skip to main content

Develop an Ajax-based file upload portlet using DWR

Display a convenient progress bar during the file upload process

Xiaobo Yang (x.yang@dl.ac.uk), Software Developer, STFC e-Science Centre, UK
Xiaobo Yang
Xiaobo Yang is a software developer working in the Grid Technology Group, CCLRC e-Science Centre, in the United Kingdom. He is interested in grid, collaborative virtual research environments, and various Web technologies, including grid portals, and Service-Oriented Architecture (SOA).
Robert Allan (r.j.allan@dl.ac.uk), Group Leader, STFC e-Science Centre, UK
Robert Allan
Rob Allan is leader of the Grid Technology Group in STFC's e-Science Centre. His background is as a physicist and developer of high-performance computing applications using the latest technologies going back to the mid 1980s. He has managed several large HPC and e-Science projects in the UK and has a particular interest in making the grid more widely usable.

Summary:  File upload is a basic function of today's Web portals. In this article, authors Xiaobo Yang and Rob Allan describe how to develop an Ajax-based file upload JSR 168-compliant portlet using DWR (Direct Web Remoting). DWR is an ideal Ajax framework for Java™ developers that dynamically generates JavaScript based on server-side deployed Java classes. You will learn how you can use DWR to retrieve file upload progress from the portal server.

Date:  21 Aug 2007
Level:  Intermediate
Activity:  9756 views

Introduction

Web portals provide users a central gateway for accessing various resources and services. At the same time, they provide users a platform for contributing resources to be shared with other users. Users might share anything from photos to audio and video files to scientific datasets for research use. Therefore, file upload is a basic and necessary function of Web portals.

Today's Web portals are heavily based on Java portlet technology. While progress bars for file upload have been described by various developers using Ajax, we have yet to discover one that is portlet based. This article shows how to develop an Ajax-based file upload portlet that displays a progress bar during the file upload process. This portlet is particularly useful for those who need to share large audio, video, and scientific files.

To follow this article, you should be familiar with Web development using Java Servlets and JavaServer Pages (JSPs). Also, it is essential that you understand portal and portlet technology development. However, if you are not proficient with portlet technology, don't abandon the article now because you'll find a brief introduction to portlet technology as well as useful resources you can use to help you get up to speed.

The developerWorks Ajax resource center
Check out the Ajax Resource Center, your one-stop shop for information on the Ajax programming model, including articles and tutorials, discussion forums, blogs, wikis, events, and news. If it's happening, it's covered here.

Consider experimenting with one of the JSR 168-compliant portal frameworks, such as IBM® WebSphere® Portal Server, Apache Pluto, eXo platform, or Liferay Portal before testing the file upload portlet described in this article. We used Apache Pluto 1.0.1, the JDK 5.0 Update 10, and Apache Ant Version 1.6.5 during the process of developing this article.

Basic concepts of portlets

In general, portlets can be treated as Web components. Portlets are similar to servlets, but they focus on the presentation layer of your application. Typical output of a portlet is HTML fragments that can then be assembled by a Web portal. Portlets themselves are managed by a portlet container. The main features of portlets include:

  • Multiple modes: A portlet can have different views under different modes. For example, besides the view mode, a portlet can support the edit mode so that users can set their own preferences.
  • Multiple window states: A portlet can be minimized, maximized, and so on.
  • Customizable parameters: A portlet can define parameters, which are customizable by users.

To get more detailed information on portlets, refer to the Java Portlet Specification 1.0, JSR 168. (JSR 286, the successor to JSR 168, is due to be released in late 2007, with improvements such as inter-portlet communication and a portlet filter.) See Resources for links to this information.

Steps to get started with the file upload portlet

The cornerstone of your file upload portlet is the Apache Commons FileUpload package (also referred to as FileUpload in this article). In addition to file upload support in a servlet, the Apache Commons FileUpload Version 1.1 package supports file upload in a portlet as well. This article uses Apache Commons FileUpload Version 1.2.

Basically, you need to perform two steps to develop a file upload progress bar:

  1. Server side retrieval of file upload progress
  2. Client side retrieval and display of the upload progress from the portal server

Server side retrieval of file upload progress

The FileUpload package supports using a listener to retrieve file upload progress. In the doUpload() method of the file upload portlet (named uk.ac.dl.esc.gtg.myportlets.fileupload.FileUploadPortlet in the source files included in the Download area of this article), we set such a progress listener for PortletFileUpload by calling the setProgressListener() method as shown in Listing 1:


Listing 1. Set a progress listener for the file upload package
                
DiskFileItemFactory factory = new DiskFileItemFactory();
PortletFileUpload pfu = new PortletFileUpload(factory);
pfu.setSizeMax(uploadMaxSize); // Maximum upload size
pfu.setProgressListener(new FileUploadProgressListener());
            

FileUploadProgressListener (see Listing 2) is a listener that implements the org.apache.commons.fileupload.ProgressListener interface. The update() method is called automatically by the FileUpload package to refresh the latest information about how many bytes are transferred. In this article's implementation, progress is updated when every 10KB of data are transferred. This prevents progress updates from occurring too frequently. The getFileUploadStatus() method is used to calculate the current file upload progress, which will be called by the client using DWR (to be discussed in the next section).


Listing 2. File upload listener for retrieving file upload progress
                
package uk.ac.dl.esc.gtg.myportlets.fileupload;

import java.text.NumberFormat;

import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class FileUploadProgressListener implements ProgressListener {
	private static Log log = LogFactory.getLog(FileUploadProgressListener.class);

	private static long bytesTransferred = 0;

	private static long fileSize = -100;

	private long tenKBRead = -1;

	public FileUploadProgressListener() {
	}

	public String getFileUploadStatus() {
		// per looks like 0% - 100%, remove % before submission
		String per = NumberFormat.getPercentInstance().format(
				(double) bytesTransferred / (double) fileSize);
		return per.substring(0, per.length() - 1);
	}

	public void update(long bytesRead, long contentLength, int items) {
		// update bytesTransferred and fileSize (if required) every 10 KB is
		// read
		long tenKB = bytesRead / 10240;
		if (tenKBRead == tenKB)
			return;
		tenKBRead = tenKB;

		bytesTransferred = bytesRead;
		if (fileSize != contentLength)
			fileSize = contentLength;
	}

}
      

Client-side retrieval of file upload progress

Communication between the server and the client on file upload progress is realized using Ajax. We chose Direct Web Remoting (DWR) to provide Ajax support in our portlet. DWR is an ideal framework for Java developers to use to bring Ajax into the Web development processes because it allows JavaScript in a browser to interact with server-side Java objects. To use DWR in our portlet, the following steps are required (for more information about how to configure DWR, see Resources):

Herein lies the beauty of Direct Web Remoting: The client is communicating with the server-side Java object.
  • Configure DwrServlet through WEB-INF/web.xml (see Listing 3).
  • Define one or more server-side objects in WEB-INF/dwr.xml for the client to communicate. In Listing 4, FileUploadProgressListener is defined for DWR so that the client can call this auto-generated JavaScript. Also, only the getFileUploadStatus method is allowed to be called by the client. The other public method, update, is not allowed to be accessed (see Listing 2).
  • Include DWR-related JavaScript code in fileupload-view.jsp (see Listing 5).
  • Include the DWR library in our portlet application.

Listing 3. Configuration of DwrServlet in WEB-INF/web.xml
                
<!-- DWR servlet -->
  <servlet>
    <servlet-name>dwr-invoker</servlet-name>
    <display-name>DWR Servlet</display-name>
    <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
    <init-param>
      <param-name>debug</param-name>
      <param-value>false</param-value>
    </init-param>
  </servlet>

<!-- DWR servlet mapping -->
  <servlet-mapping>
    <servlet-name>dwr-invoker</servlet-name>
    <url-pattern>/dwr/*</url-patter>
  </servlet-mappin>
  


Listing 4. WEB-INF/dwr.xml
                
<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN"
                     "http://getahead.org/dwr//dwr20.dtd">

<dwr>
  <allow>
    <create creator="new" javascript="FileUploadProgressListener">
      <param name="class"
             value="uk.ac.dl.esc.gtg.myportlets.fileupload.FileUploadProgressListener"/>
      <include method="getFileUploadStatus"/>
    </create>
  </allow>
</dwr>
  

The JSP file, fileupload-view.jsp, is shown in Listing 5 to illustrate how DWR helps to retrieve file upload progress from the server side. Once a file is selected and the Upload button (see Figure 1) is clicked, the fileupload_ajax_query_upload_status() method is called after one second. This method then calls the getFileUploadStatus() method of FileUploadProgressListener (see Listing 2) in asynchronous mode. Herein lies the beauty of DWR: The client is communicating with the server-side Java object. Once a response is received, the fileupload_ajax_show_upload_status() method is called to refresh the progress. If the file upload is not accomplished, an updated progress is retrieved after two seconds.


Listing 5. File upload portlet JSP file -- fileupload-view.jsp
                
<%@ page session="false" %>
<%@ page contentType="text/html" %>
<%@ page import="javax.portlet.PortletURL" %>
<%@ taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<portlet:defineObjects/>

<script type="text/javascript"
        src='<%= renderResponse.encodeURL(renderRequest.getContextPath()
				+ "/dwr/interface/FileUploadProgressListener.js") %>'> 
</script>

<script type="text/javascript"
        src='<%= renderResponse.encodeURL(renderRequest.getContextPath()
				+ "/dwr/engine.js") %>'> 
</script>

<script type="text/javascript"
        src='<%= renderResponse.encodeURL(renderRequest.getContextPath()
				+ "/dwr/util.js") %>'> 
</script>

<script type="text/javascript">
  function fileupload_ajax_query_upload_status() {
    FileUploadProgressListener.getFileUploadStatus

                 (fileupload_ajax_show_upload_status);
    return true;
  }

  function fileupload_ajax_show_upload_status(status) {
    if (status == "100")
      document.getElementById("fileupload_progress").innerHTML
                                       ="File successfully uploaded";
    else {
      document.getElementById("progressBar").style.display = "block";
      document.getElementById("fileupload_progress").innerHTML=
                                       "Uploading file: " + status
                                       + "% completed, please wait...";
      document.getElementById("progressBarBoxContent").style.width =
                                       parseInt(status * 3.5) + "px";
      setTimeout(fileupload_ajax_query_upload_status, 2000);
    }

    return true;
  }
</script>

<style type="text/css">
  #progressBar {padding-top: 5px;}
  #progressBarBox {width: 350px; height: 20px; border: 1px insert; background: #eee;}
  #progressBarBoxContent {width: 0; height: 20px; border-right: 1px solid #444;
                                       background: #9ACB34;}
</style>

<h4>File Upload</h4>

<!-- the upload form -->
<% PortletURL pUrl = renderResponse.createActionURL();
 %>
<form action="<%= pUrl.toString() %>"
         enctype="multipart/form-data" method="post"
	 onsubmit="setTimeout('fileupload_ajax_query_upload_status()', 1000)">
	 
  <input type="file" name="fileupload_upload" value="Upload File">
  <input type="submit" value="Upload">
</form>

<%-- file upload progress bar --%>
<div id="fileupload_progress"></div>
<div id="progressBar" style="display: none;">
  <div id="progressBarBoxContent"></div>
</div>
      

Deploy and test the file upload portlet with Apache Pluto

The next step in the process is to deploy and test the file upload portlet with Apache Pluto 1.0.1. (Note: The binary version was used in this article.)

Code compilation and deployment

An Ant script is provided within the downloadable portlet source code included with this article so that you can compile the portlet and build up the .war file for deployment. First, you must copy the following library files to the lib directory under the root of the source code:

  • commons-fileupload-1.2/commons-fileupload-1.2.jar
  • commons-io-1.3/commons-io-1.3.jar
  • commons-logging-1.0.4/commons-logging-1.0.4.jar
  • dwr-2.0.1/dwr.jar
  • portletapi-1.0/portlet.jar
  • servletapi-2.4/servletapi-2.4.jar

Now you're ready to run ant build and ant war to compile the code and build up the .war file for deployment accordingly. If everything goes as planned, you will find myportlets-fileupload.war under the dist directory. Follow these steps to deploy the portlet using Apache Pluto 1.0.1:

  1. Start Apache Tomcat and access http://localhost:8080/pluto/portal.
  2. Click the Admin link on the left side of the Pluto screen to deploy the portlet.
  3. Locate myportlets-fileupload.war and then click Submit.
  4. Define a portlet title, description, and layout, and then click Submit.
  5. Click Submit again on the page that is displayed.

You are now asked to either restart Tomcat or click the link Hot deploy myportlets-fileupload portlet application. We suggest you click the link Hot deploy myportlets-fileupload portlet application. The portlet is then loaded as shown in Figure 1:


Figure 1. File upload portlet running in Apache Pluto
FileUpload portlet

Test the file upload portlet

Once the portlet is deployed, you are ready to upload a file. To get the progress bar displayed, you should access the portlet from a computer other than your portal server. To upload a file, do the following:

  1. Click the Browse... button to select a file for uploading.
  2. Click the Upload button to upload the selected file. During file upload, the progress bar is displayed and updated (see Figure 2).

If you want to test the portlet from the same computer where Pluto is installed, you won't be able to see the progress bar because the maximum upload size is set to 20MB. You can change the upload size by altering fileupload_upload_maxsize within the WEB-INF/portlet.xml file.


Figure 2. A file being uploaded within the file upload portlet
File upload portlet uploading a file

In our portlet, the uploaded file is saved as a disk file under java.io.tmpdir -- for example, temp under $PLUTO_HOME or $CATALINA_HOME. Keep in mind that in actual Web applications, further processing might be required. For example, the uploaded file may be stored in a database for future usage; if it is an image file, it may be displayed in a Web browser.

Other applications for this technique

The technique in this article has been successfully applied to a file transfer portlet that makes use of the GridFTP protocol for managing large datasets between two third-party data grid nodes.

Summary

This article demonstrated how to use Ajax to develop a file upload portlet to display a progress bar. You learned about server side retrieval of file upload progress using a progress listener, client-side retrieval of file upload progress using DWR from the portal server, and rendering the progress bar to end users. This portlet is especially useful for sharing large datasets like audio and video files and scientific data. It has also demonstrated the ease of use of DWR to bring Ajax support to JSR 168 portlets.



Download

DescriptionNameSizeDownload method
Source code of the file upload portletwa-aj-dwr.zip13KB HTTP

Information about download methods


Resources

Learn

Get products and technologies

Discuss

About the authors

Xiaobo Yang

Xiaobo Yang is a software developer working in the Grid Technology Group, CCLRC e-Science Centre, in the United Kingdom. He is interested in grid, collaborative virtual research environments, and various Web technologies, including grid portals, and Service-Oriented Architecture (SOA).

Robert Allan

Rob Allan is leader of the Grid Technology Group in STFC's e-Science Centre. His background is as a physicist and developer of high-performance computing applications using the latest technologies going back to the mid 1980s. He has managed several large HPC and e-Science projects in the UK and has a particular interest in making the grid more widely usable.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Web development, XML
ArticleID=249369
ArticleTitle=Develop an Ajax-based file upload portlet using DWR
publish-date=08212007
author1-email=x.yang@dl.ac.uk
author1-email-cc=
author2-email=r.j.allan@dl.ac.uk
author2-email-cc=

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers