DWR & Maven2 & upload progress bar

DWR + Maven2 + upload progress bar

DWR is a framework that adheres somewhat to the spirit of GWT, in the sense where you manipule Java objets via JavaScript. This example will illustrate how to use DWR with Stripes to construct a progress bar while uploading a file.

MultipartWrapper Implementation

To be able to use the listener mecanisms offerd by commons-fileupload, we need to modify the standard Multipart Wrapper implemented by Stripes.

Here's the modified build method which adds a listener for the ServletFileUpload. The listener follows the code below.

 
public void build(HttpServletRequest request, File tempDir, long maxPostSize) 
throws IOException, FileUploadLimitExceededException { 
try { 
this.charset = request.getCharacterEncoding(); 
DiskFileItemFactory factory = new DiskFileItemFactory(); 
factory.setRepository(tempDir); 
ServletFileUpload upload = new ServletFileUpload(factory); 
upload.setSizeMax(maxPostSize); 

// Adding the listener 
upload.setProgressListener(new UploadProgressListener()); 
List<FileItem> items = upload.parseRequest(request); 
Map<String, List<String>> params = new HashMap<String, List<String>>(); 

for (FileItem item : items) { 
// If it's a form field, add the string value to the list 
if (item.isFormField()) { 
List<String> values = params.get(item.getFieldName()); 
if (values == null) { 
values = new ArrayList<String>(); 
params.put(item.getFieldName(), values); 
} 
values.add(charset == null ? item.getString() : item.getString(charset)); 
} 
// Else store the file param 
else { 
files.put(item.getFieldName(), item); 
} 
} 

// Now convert them down into the usual map of String->String[] 
for (Map.Entry<String, List<String>> entry : params.entrySet()) { 
List<String> values = entry.getValue(); 
this.parameters.put(entry.getKey(), values.toArray(new String[values.size()])); 
} 
} catch (FileUploadBase.SizeLimitExceededException slee) { 
throw new FileUploadLimitExceededException(maxPostSize, slee.getActualSize()); 
} catch (FileUploadException fue) { 
IOException ioe = new IOException("Could not parse and cache file upload data."); 
ioe.initCause(fue); 
throw ioe; 
} 
} 

 

Listener Implementation

 
package com.fullsix.demo.dwr; 

import java.text.NumberFormat; 

import org.apache.commons.fileupload.ProgressListener; 

/** 
* @author Damien Viel <viel@fullsix.com> 
* @version $Id$ 
* 
*/ 
public class UploadProgressListener implements ProgressListener { 

private static long bytesTransferred = 0; 
private static long fileSize = -100; 
private long tenKBRead = -1; 

public String getFileUploadStatus() { 
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) { 
long tenKB = bytesRead / 10240; 
if (tenKBRead == tenKB) 
return; 
tenKBRead = tenKB; 

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

DWR Configuration

In the WEB-INF folder of your web app, create the following file named 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="UploadProgressListener"> 
<param name="class" value="com.fullsix.demo.dwr.UploadProgressListener" /> 
<include method="getFileUploadStatus"/> 
</create> 
</allow> 
</dwr> 

web.xml file

Use the new MultipartWrapper and declare the DWRServlet.

 
<?xml version="1.0" encoding="ISO-8859-1" ?> 
<web-app id="Communautaire_Front" 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>SWF Upload</display-name> 

<filter> 
<display-name>Stripes Filter</display-name> 
<filter-name>StripesFilter</filter-name> 
<filter-class>net.sourceforge.stripes.controller.StripesFilter</filter-class> 
<init-param> 
<param-name>ActionResolver.UrlFilters</param-name> 
<param-value>classes</param-value> 
</init-param> 
<init-param> 
<param-name>ActionResolver.PackageFilters</param-name> 
<param-value>com.fullsix.demo.action.*</param-value> 
</init-param> 
<init-param> 
<param-name>MultipartWrapper.Class</param-name> 
<param-value>com.fullsix.demo.dwr.CommonsDWRMultipartWrapper</param-value> 
</init-param> 
<init-param> 
<param-name>FileUpload.MaximumPostSize</param-name> 
<param-value>500m</param-value> 
</init-param> 
</filter> 

<filter-mapping> 
<filter-name>StripesFilter</filter-name> 
<url-pattern>*.jsp</url-pattern> 
<dispatcher>REQUEST</dispatcher> 
<dispatcher>FORWARD</dispatcher> 
</filter-mapping> 

<filter-mapping> 
<filter-name>StripesFilter</filter-name> 
<servlet-name>StripesDispatcher</servlet-name> 
<dispatcher>REQUEST</dispatcher> 
</filter-mapping> 

<servlet> 
<servlet-name>StripesDispatcher</servlet-name> 
<servlet-class>net.sourceforge.stripes.controller.DispatcherServlet</servlet-class> 
<load-on-startup>1</load-on-startup> 
</servlet> 

<servlet> 
<servlet-name>dwr-invoker</servlet-name> 
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class> 
<init-param> 
<param-name>debug</param-name> 
<param-value>false</param-value> 
</init-param> 
<init-param> 
<param-name>logLevel</param-name> 
<param-value>WARN</param-value> 
</init-param> 
</servlet> 

<servlet-mapping> 
<servlet-name>dwr-invoker</servlet-name> 
<url-pattern>/dwr/*</url-pattern> 
</servlet-mapping> 

<servlet-mapping> 
<servlet-name>StripesDispatcher</servlet-name> 
<url-pattern>*.action</url-pattern> 
</servlet-mapping> 

<!-- The Usual Welcome File List --> 
<welcome-file-list> 
<welcome-file>index.jsp</welcome-file> 
</welcome-file-list> 

</web-app> 

JSP File

 
<%@ taglib uri="http://stripes.sourceforge.net/stripes.tld" prefix="stripes"%> 

<html xmlns="http://www.w3.org/1999/xhtml" > 
<head> 
<title>DWR Demo</title> 
<link href="css/default.css" rel="stylesheet" type="text/css" /> 
<script src="${pageContext.request.contextPath}/dwr/engine.js"></script> 
<script src="${pageContext.request.contextPath}/dwr/util.js"></script> 
<script src="${pageContext.request.contextPath}/dwr/interface/UploadProgressListener.js"></script> 

<script type="text/javascript"> 
function startProgress() { 
document.getElementById('progressBar').style.display = 'block'; 
document.getElementById('progressBarText').innerHTML = 'Progression : 0%'; 
window.setTimeout('fileupload_ajax_query_upload_status()', 1500); 
return true; 
} 

function fileupload_ajax_query_upload_status() { 
UploadProgressListener.getFileUploadStatus(fileupload_ajax_show_upload_status);
return true; 
} 

function fileupload_ajax_show_upload_status(status) { 
document.getElementById("progressBar").style.display = "block"; 
document.getElementById("progressBarText").innerHTML = "Progression : " + status + "%"; 
document.getElementById("progressBarBoxContent").style.width = parseInt(status * 3.5) + "px"; 
window.setTimeout('fileupload_ajax_query_upload_status()', 200); 
return true; 
} 
</script> 
</head> 
<body> 
<div id="content"> 
<h2>Simple Demo</h2> 
<stripes:form beanclass="com.fullsix.demo.action.UploadActionBean" onsubmit="startProgress();"> 
<h1>Web upload</h1> 
<p> 
<stripes:file id="fileBean" name="fileBean" /> 
<br /> 
<stripes:submit value="begin upload" id="uploadbutton" name="upload" /> 
<br /> 
<div id="progressBar" style="display: none;"> 
<div id="progressBarText"></div> 
<div id="progressBarBox"> 
<div id="progressBarBoxContent"></div> 
</div> 
</div> 
</p> 
</stripes:form> 
</div> 
</body> 
</html> 

The pom.xml

 
<?xml version="1.0" encoding="UTF-8"?> 
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<modelVersion>4.0.0</modelVersion> 
<groupId>com.fullsix</groupId> 
<artifactId>demodwr</artifactId> 
<packaging>war</packaging> 
<name /> 
<version>0.0.1-SNAPSHOT</version> 
<description /> 
<build> 
<finalName>demoDWR</finalName> 
<plugins> 
<plugin> 
<artifactId>maven-compiler-plugin</artifactId> 
<configuration> 
<source>1.5</source> 
<target>1.5</target> 
<encoding>UTF-8</encoding> 
</configuration> 
</plugin> 
<plugin> 
<groupId>org.mortbay.jetty</groupId> 
<artifactId>maven-jetty-plugin</artifactId> 
<configuration> 
<contextPath>/</contextPath> 
<connectors> 
<connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
<port>8080</port> 
</connector> 
</connectors> 
</configuration> 
</plugin> 
</plugins> 
</build> 
<dependencies> 
<dependency> 
<groupId>commons-fileupload</groupId> 
<artifactId>commons-fileupload</artifactId> 
<version>1.2.1</version> 
</dependency> 
<dependency> 
<groupId>commons-io</groupId> 
<artifactId>commons-io</artifactId> 
<version>1.4</version> 
</dependency> 
<dependency> 
<groupId>commons-logging</groupId> 
<artifactId>commons-logging</artifactId> 
<version>1.1.1</version> 
</dependency> 
<dependency> 
<groupId>net.sourceforge.stripes</groupId> 
<artifactId>stripes</artifactId> 
<version>1.4.3</version> 
</dependency> 
<dependency> 
<groupId>javax.servlet</groupId> 
<artifactId>servlet-api</artifactId> 
<version>2.5</version> 
</dependency> 
<dependency> 
<groupId>org.directwebremoting</groupId> 
<artifactId>dwr</artifactId> 
<version>2.0.2</version> 
</dependency> 
<dependency> 
<groupId>commons-lang</groupId> 
<artifactId>commons-lang</artifactId> 
<version>2.4</version> 
</dependency> 
</dependencies> 
</project>