<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>IONCANNON &#187; java</title>
	<atom:link href="http://www.ioncannon.net/tag/java/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.ioncannon.net</link>
	<description>Thoughts on Software Development and Engineering</description>
	<lastBuildDate>Tue, 03 Jan 2012 13:59:08 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
	<atom:link rel='hub' href='http://www.ioncannon.net/?pushpress=hub'/>
		<item>
		<title>Using the Google Closure Compiler in Java</title>
		<link>http://www.ioncannon.net/programming/1447/using-the-google-closure-compiler-in-java/</link>
		<comments>http://www.ioncannon.net/programming/1447/using-the-google-closure-compiler-in-java/#comments</comments>
		<pubDate>Tue, 08 Mar 2011 14:29:55 +0000</pubDate>
		<dc:creator>carson</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[closure]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://www.ioncannon.net/?p=1447</guid>
		<description><![CDATA[I recently had a chance to try out Google&#039;s closure compiler. The closure compiler is similar to the YUI compressor except that along with minimizing it may rewrite the JavaScript. If you want to understand more about what it does start at the overview documentation and then go from there. What I needed was a [...]]]></description>
			<content:encoded><![CDATA[<p>I recently had a chance to try out <a href="http://code.google.com/closure/compiler/">Google&#039;s closure compiler</a>. The closure compiler is similar to the <a href="http://developer.yahoo.com/yui/compressor/">YUI compressor</a> except that along with minimizing it may rewrite the JavaScript. If you want to understand more about what it does start at the <a href="http://code.google.com/closure/compiler/docs/overview.html">overview documentation</a> and then go from there.</p>
<p>What I needed was a way to use the closure compiler in an Ant task. The Ant task that comes with the library is good but there wasn&#039;t a way for me to integrate it into an existing system that wasn&#039;t going to change. After looking around for some example code and not finding any I went into the library&#039;s Ant task and figured out how to wire it all up myself.</p>
<p><span id="more-1447"></span></p>
<p>It isn&#039;t that hard to use the compiler library in your own Java code but without a simple example it takes some work to figure out what is needed and what isn&#039;t. The following code is just about as bare bones as you can get. It takes a number of JavaScript files and compile them using the medium setting, more about the choice of settings after the code:</p>
<pre class="brush: java; title: ; notranslate">
import com.google.javascript.jscomp.*;

import java.io.FileWriter;
import java.util.List;
import java.util.ArrayList;
import java.util.logging.Level;

public class Test
{
  public static void main(String[] args) throws Exception
  {
    // These are external JavaScript files you reference but don't want changed
    String externalJavascriptResources[] = {
        &quot;jquery.js&quot;,
        &quot;jqueryui.js&quot;
    };
    // These are the files you want optimized
    String primaryJavascriptToCompile[] = {
        &quot;somejavascript.js&quot;,
        &quot;otherjavascript.js&quot;
    };
    // This is where the optimized code will end up
    String outputFilename = &quot;combined.min.js&quot;;

    com.google.javascript.jscomp.Compiler.setLoggingLevel(Level.INFO);
    com.google.javascript.jscomp.Compiler compiler = new com.google.javascript.jscomp.Compiler();

    CompilerOptions options = new CompilerOptions();
    CompilationLevel.SIMPLE_OPTIMIZATIONS.setOptionsForCompilationLevel(options);

    WarningLevel.VERBOSE.setOptionsForWarningLevel(options);

    List&lt;JSSourceFile&gt; externalJavascriptFiles = new ArrayList&lt;JSSourceFile&gt;();
    for (String filename : externalJavascriptResources)
    {
      externalJavascriptFiles.add(JSSourceFile.fromFile(filename));
    }

    List&lt;JSSourceFile&gt; primaryJavascriptFiles = new ArrayList&lt;JSSourceFile&gt;();
    for (String filename : primaryJavascriptToCompile)
    {
      primaryJavascriptFiles.add(JSSourceFile.fromFile(filename));
    }

    compiler.compile(externalJavascriptFiles, primaryJavascriptFiles, options);

    for (JSError message : compiler.getWarnings())
    {
      System.err.println(&quot;Warning message: &quot; + message.toString());
    }

    for (JSError message : compiler.getErrors())
    {
      System.err.println(&quot;Error message: &quot; + message.toString());
    }

    FileWriter outputFile = new FileWriter(outputFilename);
    outputFile.write(compiler.toSource());
    outputFile.close();
  }
}
</pre>
<p>The above code is doing a number of things:</p>
<ul>
<li>It takes both external resources you don&#039;t want optimized as well as resources you do want optimized that refer to those external resources. You may not need to list external resources depending on what level of optimization you use.</li>
<li>It combines all the input files that are not external into one output file.</li>
<li>It compiles the javascript code given to it using the SIMPLE_OPTIMIZATIONS setting.</li>
<li>It lists any warnings or errors it found while compiling the code.</li>
</ul>
<p>One of the nice side effects of using the closure compiler is that because it compiles the code it can alert you to errors or potential issues using warnings.</p>
<p>What is listed above is using the middle of the road optimizations. There is a level above SIMPLE_OPTIMIZATIONS that you can set by changing that line in the above code to:</p>
<pre class="brush: java; title: ; notranslate">
  CompilationLevel.ADVANCED_OPTIMIZATIONS.setOptionsForCompilationLevel(options);
</pre>
<p>Be aware that the advanced optimizations will do things, renaming your variables and functions to name two, that can break your code. The compiler gives you a way of alerting it to things you don&#039;t want changed using externs and exports. Before using the advanced option you should read the <a href="http://code.google.com/closure/compiler/docs/api-tutorial3.html">advanced options tutorial</a>.</p>
<p>If you do not like seeing all the steps the compiler takes you can set the logging level to QUIET by changing the WarningLevel line to the following:</p>
<pre class="brush: java; title: ; notranslate">
  WarningLevel.QUIET.setOptionsForWarningLevel(options);
</pre>
<p>One last note about the compiler is that the <a href="http://code.google.com/closure/compiler/docs/inspector.html">closure inspector</a> is a Firebug plugin that will let you see what the original line of code looked like before it was compiled. This can help a lot when something goes wrong.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ioncannon.net/programming/1447/using-the-google-closure-compiler-in-java/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Java AirPlay Client</title>
		<link>http://www.ioncannon.net/utilities/1436/java-airplay-client/</link>
		<comments>http://www.ioncannon.net/utilities/1436/java-airplay-client/#comments</comments>
		<pubDate>Tue, 25 Jan 2011 14:36:04 +0000</pubDate>
		<dc:creator>carson</dc:creator>
				<category><![CDATA[utilities]]></category>
		<category><![CDATA[airplay]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://www.ioncannon.net/?p=1436</guid>
		<description><![CDATA[Ever since getting one of the new AppleTV devices I have been wanting to fiddle with AirPlay. I finally got around to looking at a dump of the traffic between an iPad and the AppleTV over Christmas and was surprised at how simple it was. Soon after I noticed a blog post about AirFlick for [...]]]></description>
			<content:encoded><![CDATA[<p>Ever since getting one of the new AppleTV devices I have been wanting to fiddle with AirPlay. I finally got around to looking at a dump of the traffic between an iPad and the AppleTV over Christmas and was surprised at how simple it was. Soon after I noticed a blog post about <a href="http://ericasadun.com/ftp/AirPlay/">AirFlick</a> for the Mac. AirFlick was close to what I was wanting at the time but I really wanted something that would let me control AirPlay from Linux or Windows.</p>
<p>I decided to make something that could run anywhere so I created my own AirPlay client called <a href="http://www.ioncannon.net/projects/ap4j-player-java-airplay-player/">AP4J</a>. I used Java and a pure Java Bonjour implementation called <a href="http://jmdns.sourceforge.net/">JmDNS</a> so AP4J can run anywhere Java runs.</p>
<p>The current version only has the ability to control an AirPlay device. That means you have to supply a location that has a compatible video (h264 encoded) but once playing you will have control over the video just as you would using the iPad or iPhone. The next step will be to add the ability to directly serve videos instead of only being able to control the playback of videos. My goal will be the ability to run AP4J on my Windows Home Media server where I can have it stream videos to my AppleTV.</p>
<p>I have tested AP4J on Linux, Windows and Mac but only extensively on Linux. I have also tested a number of sites that have compatible videos available, a few of those are listed here:</p>
<ul>
<li><a href="http://blip.tv/">http://blip.tv/</a></li>
<li><a href="http://blip.tv/">http://www.archives.org/</a></li>
<li><a href="http://blip.tv/">http://confreaks.net/</a></li>
</ul>
<p>Now for a couple screen shots. This is what you see after starting the server and going to the web interface:</p>
<p><a href="http://www.ioncannon.net/wp-content/uploads/2011/01/ap4jmain.png"><img src="http://www.ioncannon.net/wp-content/uploads/2011/01/ap4jmain.png" alt="" title="Java AirPlay Application Main Menu" width="353" height="204" class="alignnone size-full wp-image-1431" /></a></p>
<p>This is what it looks like when a video is playing:</p>
<p><a href="http://www.ioncannon.net/wp-content/uploads/2011/01/ap4jpopup.png"><img src="http://www.ioncannon.net/wp-content/uploads/2011/01/ap4jpopup.png" alt="" title="Java AirPlay Application Play Popup" width="698" height="407" class="alignnone size-full wp-image-1432" /></a> <br/></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ioncannon.net/utilities/1436/java-airplay-client/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Spring 3 File Upload Example</title>
		<link>http://www.ioncannon.net/programming/975/spring-3-file-upload-example/</link>
		<comments>http://www.ioncannon.net/programming/975/spring-3-file-upload-example/#comments</comments>
		<pubDate>Mon, 22 Mar 2010 11:30:40 +0000</pubDate>
		<dc:creator>carson</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://www.ioncannon.net/?p=975</guid>
		<description><![CDATA[I had the opportunity to figure out how to do file uploads using Spring 3 the other day and I couldn&#039;t find anything that pulled it all together. What follows is a complete example of how to do MVC based file uploads with Spring 3. I&#039;m going to assume you know something about Spring and [...]]]></description>
			<content:encoded><![CDATA[<p>I had the opportunity to figure out how to do file uploads using Spring 3 the other day and I couldn&#039;t find anything that pulled it all together. What follows is a complete example of how to do MVC based file uploads with Spring 3.</p>
<p><span id="more-975"></span></p>
<p>I&#039;m going to assume you know something about <a href="http://www.springsource.org/">Spring</a> and their MVC configuration in general. If you want a simple MVC example to start with check out their <a href="https://src.springframework.org/svn/spring-samples/mvc-basic/trunk/src/main/">SVN MVC-Basic sample</a>. There is a decent amount of boiler plate work so I&#039;ve created a <a href="http://www.ioncannon.net/examples/Spring3Upload.zip">project zip file</a> with all the code, a build file and configuration in it (you just need to add the libraries).</p>
<p>First lets start by gathering up all the libraries we are going to need (see the end of the post for the directory layout I used or just unzip the project). Grab a copy of the Spring 3 libraries, at this time the latest version is spring-framework-3.0.1.RELEASE-A.zip and that is what I used for the following example. For the file upload part there are two non-Spring dependencies as well: <a href="http://commons.apache.org/fileupload/">Apache Commons FileUpload</a> and <a href="http://commons.apache.org/io/">Apache Commons IO</a>. If you want to use the example project from the zip just copy all the jar files to the lib directory.</p>
<p>Next it is worth a quick look at the information provided in the Spring documentation about <a href="http://static.springsource.org/spring/docs/3.0.0.RELEASE/reference/html/mvc.html#mvc-multipart">MVC multipart</a>. It touches on what needs to be done but leaves out a full example. In documentation you will see that they talk about using a &#034;multipart resolver&#034; and that can be found at the end of <i>web/WEB-INF/spring/app-config.xml</i>:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
       xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
       xmlns:context=&quot;http://www.springframework.org/schema/context&quot;
       xsi:schemaLocation=&quot;
		http://www.springframework.org/schema/beans	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd&quot;&gt;

    &lt;!-- Scans the classpath of this application for @Components to deploy as beans --&gt;
    &lt;context:component-scan base-package=&quot;net.ioncannon&quot;/&gt;

    &lt;!-- Configures Spring MVC --&gt;
    &lt;import resource=&quot;mvc-config.xml&quot;/&gt;

    &lt;!-- Configure the multipart resolver --&gt;
    &lt;bean id=&quot;multipartResolver&quot; class=&quot;org.springframework.web.multipart.commons.CommonsMultipartResolver&quot;&gt;
        &lt;!-- one of the properties available; the maximum file size in bytes --&gt;
        &lt;property name=&quot;maxUploadSize&quot; value=&quot;100000&quot;/&gt;
    &lt;/bean&gt;

&lt;/beans&gt;
</pre>
<p>The above app-config.xml configuration file is referenced from the mvc-config.xml configuration file. The mvc-config.xml configuration file doesn&#039;t need anything special for multipart uploads so I&#039;ll skip listing it here, have a look in the zip file if you are interested in its contents.</p>
<p>Now that the configuration is set the next step is to create the entry form for the upload. I&#039;ve done this in the view JSP found in <i>web/WEB-INF/views/upload/uploadForm.jsp</i>:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;%@page contentType=&quot;text/html;charset=UTF-8&quot; %&gt;
&lt;%@page pageEncoding=&quot;UTF-8&quot; %&gt;
&lt;%@ page session=&quot;false&quot; %&gt;
&lt;%@ taglib prefix=&quot;form&quot; uri=&quot;http://www.springframework.org/tags/form&quot; %&gt;

&lt;html&gt;
    &lt;head&gt;
        &lt;META http-equiv=&quot;Content-Type&quot; content=&quot;text/html;charset=UTF-8&quot;&gt;
        &lt;title&gt;Upload Example&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;form:form modelAttribute=&quot;uploadItem&quot; method=&quot;post&quot; enctype=&quot;multipart/form-data&quot;&gt;
            &lt;fieldset&gt;
                &lt;legend&gt;Upload Fields&lt;/legend&gt;

                &lt;p&gt;
                    &lt;form:label for=&quot;name&quot; path=&quot;name&quot;&gt;Name&lt;/form:label&gt;&lt;br/&gt;
                    &lt;form:input path=&quot;name&quot;/&gt;
                &lt;/p&gt;

                &lt;p&gt;
                    &lt;form:label for=&quot;fileData&quot; path=&quot;fileData&quot;&gt;File&lt;/form:label&gt;&lt;br/&gt;
                    &lt;form:input path=&quot;fileData&quot; type=&quot;file&quot;/&gt;
                &lt;/p&gt;

                &lt;p&gt;
                    &lt;input type=&quot;submit&quot; /&gt;
                &lt;/p&gt;

            &lt;/fieldset&gt;
        &lt;/form:form&gt;
    &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>A few notes about this view JSP:</p>
<ul>
<li>The form needs to have the encoding type set correctly. Look for: enctype=&#034;multipart/form-data&#034;</li>
<li>The file input field needs to be set: type=&#034;file&#034;</li>
<li>In the above I&#039;ve included a Name field in the model as well as the File field just to show that you can mix fields in the same form</li>
<li>The definition of the model can be found next and I assume that it is introduced into the form as &#034;uploadItem&#034;</li>
</ul>
<p>The model is pretty simple and can be found in <i>src/net/ioncannon/model/UploadItem.java</i>:</p>
<pre class="brush: java; title: ; notranslate">
package net.ioncannon.model;

import org.springframework.web.multipart.commons.CommonsMultipartFile;

public class UploadItem
{
  private String name;
  private CommonsMultipartFile fileData;

  public String getName()
  {
    return name;
  }

  public void setName(String name)
  {
    this.name = name;
  }

  public CommonsMultipartFile getFileData()
  {
    return fileData;
  }

  public void setFileData(CommonsMultipartFile fileData)
  {
    this.fileData = fileData;
  }
}
</pre>
<p>The Name attribute is just an extra input field and not the name of the file. Notice that the File attribute is of type CommonsMultipartFile. The CommonsMultipartFile type has a number of features that give you information about the uploaded file as well as access to its contents.</p>
<p>The controller brings everything together. The source can be found in the file <i>src/net/ioncannon/controller/UploadController.java</i>:</p>
<pre class="brush: java; title: ; notranslate">
package net.ioncannon.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;

import net.ioncannon.model.UploadItem;

@Controller
@RequestMapping(value = &quot;/upload&quot;)
public class UploadController
{
  @RequestMapping(method = RequestMethod.GET)
  public String getUploadForm(Model model)
  {
    model.addAttribute(new UploadItem());
    return &quot;upload/uploadForm&quot;;
  }

  @RequestMapping(method = RequestMethod.POST)
  public String create(UploadItem uploadItem, BindingResult result)
  {
    if (result.hasErrors())
    {
      for(ObjectError error : result.getAllErrors())
      {
        System.err.println(&quot;Error: &quot; + error.getCode() +  &quot; - &quot; + error.getDefaultMessage());
      }
      return &quot;upload/uploadForm&quot;;
    }

    // Some type of file processing...
    System.err.println(&quot;-------------------------------------------&quot;);
    System.err.println(&quot;Test upload: &quot; + uploadItem.getName());
    System.err.println(&quot;Test upload: &quot; + uploadItem.getFileData().getOriginalFilename());
    System.err.println(&quot;-------------------------------------------&quot;);

    return &quot;redirect:/app/&quot;;
  }
}
</pre>
<p>Once the file is uploaded I&#039;m just dumping out part of the information. Doing something exciting with the file is up to you.</p>
<p>That is all there is to it. Here is a list of what the project structure looks like with everything pulled together including all the libraries, build file, source and configuration files:</p>
<div class="codesnip-container" >build/build.xml<br />
lib/commons-fileupload-1.2.1.jar<br />
lib/commons-io-1.4.jar<br />
lib/org.springframework.aop-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.asm-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.aspects-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.beans-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.context-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.context.support-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.core-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.expression-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.instrument-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.instrument.tomcat-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.jdbc-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.jms-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.orm-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.oxm-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.spring-library-3.0.1.RELEASE-A.libd<br />
lib/org.springframework.test-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.transaction-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.web-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.web.portlet-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.web.servlet-3.0.1.RELEASE-A.jar<br />
lib/org.springframework.web.struts-3.0.1.RELEASE-A.jar<br />
src/net/ioncannon/controller/UploadController.java<br />
src/net/ioncannon/model/UploadItem.java<br />
web/WEB-INF/web.xml<br />
web/WEB-INF/spring/app-config.xml<br />
web/WEB-INF/spring/mvc-config.xml<br />
web/WEB-INF/views/welcome.jsp<br />
web/WEB-INF/views/upload/uploadForm.jsp</div>
]]></content:encoded>
			<wfw:commentRss>http://www.ioncannon.net/programming/975/spring-3-file-upload-example/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>AJAX file upload progress for Java using commons fileupload and prototype</title>
		<link>http://www.ioncannon.net/programming/38/ajax-file-upload-progress-for-java-using-commons-fileupload-and-prototype/</link>
		<comments>http://www.ioncannon.net/programming/38/ajax-file-upload-progress-for-java-using-commons-fileupload-and-prototype/#comments</comments>
		<pubDate>Mon, 03 Apr 2006 02:15:15 +0000</pubDate>
		<dc:creator>carson</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://www.ioncannon.net/uncategorized/38/ajax-file-upload-progress-for-java-using-commons-fileupload-and-prototype/</guid>
		<description><![CDATA[This has been done before with PHP (AJAX upload progress meter for PHP) etc but I needed something a little different because I wanted to upload a file and then have it loaded into a database. I looked around and found that someone had already made something that used the commons file upload package to [...]]]></description>
			<content:encoded><![CDATA[<p>This has been done before with PHP (<a href="http://bluga.net/projects/uploadProgressMeter/">AJAX upload progress meter for PHP</a>) etc but I needed something a little different because I wanted to upload a file and then have it loaded into a database. I looked around and found that someone had already made something that used the commons file upload package to do the upload part (<a href="http://www.telio.be/blog/2006/01/06/ajax-upload-progress-monitor-for-commons-fileupload-example/">AJAX Upload progress monitor for Commons-FileUpload Example</a>). It wasn&#039;t exactly what I was looking for but it a good start.</p>
<p><span id="more-38"></span></p>
<p>To understand the way this works I think it is easiest to break it down into parts:</p>
<ol>
<li>A file upload extention that counts bytes as they are uploaded</li>
<li>An interface that monitors the progress of something running on the server</li>
<li>AJAX to pull the monitoring into the current screen</li>
</ol>
<p><a></a></p>
<h3>Counting bytes when files are uploaded</h3>
<p>This was taken from the <a href="http://www.telio.be/blog/2006/01/06/ajax-upload-progress-monitor-for-commons-fileupload-example/">example listed above</a>. It extends and wraps parts of the commons File Upload classes so that you can count the bytes as they are uploaded to the server. You can download the <a href="http://www.ioncannon.net/examples/fileupload-ext.zip">source with build file</a> or the <a href="http://www.ioncannon.net/examples/fileupload-ext1.zip">binary</a>. You will also need the <a href="http://jakarta.apache.org/site/downloads/downloads_commons-fileupload.cgi">commons file upload</a>, <a href="http://jakarta.apache.org/site/downloads/downloads_commons-io.cgi">commons io</a> and <a href="http://jakarta.apache.org/site/downloads/downloads_commons-logging.cgi">commons logging</a>. If you download the source put the commons jars in the lib directory before building.</p>
<p>The code is fairly simple to follow. MonitoredDiskFileItemFactory replaces DiskFileItemFactory and the construction of a MonitoredDiskFileItemFactory takes a OutputStreamListener that will be passed on down the chain. The new factory creates MonitoredDiskFileItems instead of DiskFileItems for each file uploaded. When the file needs to be written to disk a MonitoredOutputStream is given back instead of a normal OutputStream. The MonitoredOutputStream calls the OutputStreamListener methods as the bytes are written and with that you now have a way to monitor the byte count as the file is created on the server.</p>
<p>Now to test this all out we can just have an OutputStreamListener that writes its progress out to a logfile or something.</p>
<div class="codesnip-container" >
<div class="java codesnip" style="font-family:monospace;"><span class="kw1">public</span> <span class="kw1">class</span> FileUploadListener <span class="kw1">implements</span> OutputStreamListener<br />
<span class="br0">&#123;</span><br />
&nbsp; <span class="kw1">private</span> <span class="kw4">long</span> totalFileSize<span class="sy0">;</span><br />
&nbsp; <span class="kw1">private</span> <span class="kw4">long</span> currentFileRead<span class="sy0">;</span></p>
<p>&nbsp; <span class="kw1">public</span> FileUploadListener<span class="br0">&#40;</span><span class="kw4">long</span> totalFileSize<span class="br0">&#41;</span><br />
&nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">this</span>.<span class="me1">totalFileSize</span> <span class="sy0">=</span> totalFileSize<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">this</span>.<span class="me1">currentFileRead</span> <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; <span class="kw1">public</span> <span class="kw4">void</span> start<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; log.<span class="me1">debug</span><span class="br0">&#40;</span><span class="st0">&quot;Upload started. Total file size: &quot;</span> <span class="sy0">+</span> totalFileSize<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; <span class="kw1">public</span> <span class="kw4">void</span> bytesRead<span class="br0">&#40;</span><span class="kw4">int</span> byteCount<span class="br0">&#41;</span><br />
&nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; log.<span class="me1">debug</span><span class="br0">&#40;</span><span class="st0">&quot;Read bytes. Currently &quot;</span> <span class="sy0">+</span> byteCount <span class="sy0">+</span> <span class="st0">&quot; out of &quot;</span> <span class="sy0">+</span> totalFileSize <span class="sy0">+</span> <span class="st0">&quot; bytes.&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; currentFileRead<span class="sy0">+=</span>byteCount<span class="sy0">;</span><br />
&nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; <span class="kw1">public</span> <span class="kw4">void</span> error<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> error<span class="br0">&#41;</span><br />
&nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; log.<span class="me1">debug</span><span class="br0">&#40;</span><span class="st0">&quot;Hit an error: &quot;</span> <span class="sy0">+</span> error<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; <span class="kw1">public</span> <span class="kw4">void</span> done<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; log.<span class="me1">debug</span><span class="br0">&#40;</span><span class="st0">&quot;Upload done.&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; <span class="kw1">public</span> <span class="kw4">long</span> getTotalRead<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> currentFileRead<span class="sy0">;</span><br />
&nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; <span class="kw1">public</span> <span class="kw4">long</span> getTotalSize<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> totalFileSize<span class="sy0">;</span><br />
&nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div>
</div>
<p>Now we try it out. You can put this in a servlet or jsp so I&#039;m only going to list the parts that matter.</p>
<div class="codesnip-container" >
<div class="java codesnip" style="font-family:monospace;">FileUploadListener listener <span class="sy0">=</span> <span class="kw1">new</span> FileUploadListener<span class="br0">&#40;</span>request.<span class="me1">getContentLength</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; session.<span class="me1">setAttribute</span><span class="br0">&#40;</span><span class="st0">&quot;LISTENER&quot;</span>, listener<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; FileItemFactory factory <span class="sy0">=</span> <span class="kw1">new</span> MonitoredDiskFileItemFactory<span class="br0">&#40;</span>listener<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; ServletFileUpload upload <span class="sy0">=</span> <span class="kw1">new</span> ServletFileUpload<span class="br0">&#40;</span>factory<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Alist+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">List</span></a> items <span class="sy0">=</span> upload.<span class="me1">parseRequest</span><span class="br0">&#40;</span>request<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aiterator+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">Iterator</span></a> i <span class="sy0">=</span> items.<span class="me1">iterator</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span> i.<span class="me1">hasNext</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><span class="br0">&#41;</span><br />
&nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; FileItem fileItem <span class="sy0">=</span> <span class="br0">&#40;</span>FileItem<span class="br0">&#41;</span> i.<span class="me1">next</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>fileItem.<span class="me1">isFormField</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// code here to process the file</span><br />
&nbsp; &nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;<span class="br0">&#125;</span></div>
</div>
<p>I&#039;m going to assume you can find the correct way to do the actual form upload part.</p>
<p>Note: One issue that you will face at some point is where the upload post goes to becuase when you get to the AJAXy part of things you want the post to stay on the same page. You can use a hidden iframe and the form&#039;s &#034;target&#034; parameter to do this (I have an example later). This is one thing the Java examples I found didn&#039;t have but the PHP examples did and I&#039;m not sure exactly how the Java examples work without it.</p>
<h3>Monitoring progress on the server</h3>
<p>The next step is to monitor the progress of the upload on the server. What you are monitoring on the server doesn&#039;t even need to be the upload. For the work I was doing the upload goes fairly quickly but what happens to the file after the upload takes a little longer. I wanted to monitor both and that is one reason I think it helps to break this up into parts because you aren&#039;t limited to just monitoring file uploads.</p>
<p>The main thing to keep in mind here is that the application server is multithreaded and you can make more than one request to the server at the same time. You probably know that you can open a tab in firefox or another window in ie and use the same session from the current webapp you are using. Knowing that you can create a page that monitors the status of things as they are running on the server. </p>
<p>From the example above you could toss the listener into the users session. Then insead of logging you just add a couple variables to keep track of the number of bytes that have been uploaded. Then create a simple jsp that pulls the Listener out of the session and dumps its data to a page. Open two windows, one to the upload page and another one to the status page. Start the upload and then start refreshing the status. You should see that the values change as the file is uploaded.</p>
<div class="codesnip-container" >
<div class="java codesnip" style="font-family:monospace;"><span class="sy0">&lt;%</span>@page<span class="sy0">%&gt;</span><br />
<span class="sy0">&lt;%</span><br />
&nbsp; FileUploadListener listener <span class="sy0">=</span> <span class="br0">&#40;</span>FileUploadListener<span class="br0">&#41;</span>session.<span class="me1">getAttribute</span><span class="br0">&#40;</span><span class="st0">&quot;LISTENER&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="sy0">%&gt;</span><br />
Total size<span class="sy0">:</span> <span class="sy0">&lt;%=</span>listener.<span class="me1">getTotalSize</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">%&gt;&lt;</span>br<span class="sy0">/&gt;</span><br />
Read count<span class="sy0">:</span> <span class="sy0">&lt;%=</span>listener.<span class="me1">getTotalRead</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">%&gt;&lt;</span>br<span class="sy0">/&gt;</span></div>
</div>
<p>Of course you will probably want more than just the total size and bytes read as well as more formating like a little progress bar or something but I&#039;ll leave that up to you. </p>
<h3>AJAX integration with prototype</h3>
<p>You have the major parts to the upload progress done and now all you need is the AJAX part. To do this I chose to use <a href="http://prototype.conio.net/">prototype</a> because it cuts right to what you want to do. One call is all you need to use: Ajax.PeriodicalUpdater.</p>
<p>The Ajax.PeriodicalUpdater call will update a container (in my case a div) on a set interval. Here is an example of how to have it update a div with an id of &#034;status&#034; every second.</p>
<div class="codesnip-container" >
<div class="javascript codesnip" style="font-family:monospace;"><span class="kw2">new</span> Ajax.<span class="me1">PeriodicalUpdater</span><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#039;status&#039;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#039;status.jsp&#039;</span><span class="sy0">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span>asynchronous<span class="sy0">:</span><span class="kw2">true</span><span class="sy0">,</span> frequency<span class="sy0">:</span><span class="nu0">1</span><span class="sy0">,</span> method<span class="sy0">:</span><span class="st0">&#039;get&#039;</span><span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span></div>
</div>
<p>The first argument is the id of the div, the second is the jsp that contains the data to stick into the div every second and the 3rd arguement is a set of options. There are more options availabe if you need them.</p>
<p>You would want to kick the update off whenever the form is posted. When the post is complete the iframe used as a place to post to will load with the results of the servlet or jsp that you posted to. If you return some javascript as a result for the iframe you will be able to create a final &#034;finished&#034; message on the page to let the user know the upload has completed and stop the processing of the AJAX updater.</p>
<p>So there you have it. The basics of setting up an upload progress bar using java and AJAX. I have left out a good bit but you should have enough to at least get you started.</p>
<p>By request I have created a simple example that pulls everything together. The source contains everything you need to create a war file including all source and an ant build file.</p>
<p><a href="http://www.ioncannon.net/examples/testupload.zip">Example Source</a>
</p>
<p>Tags: <a href="http://technorati.com/tag/java" rel="tag">java</a>, <a href="http://technorati.com/tag/ajax" rel="tag"> ajax</a>, <a href="http://technorati.com/tag/file+upload" rel="tag"> file upload</a>, <a href="http://technorati.com/tag/prototype" rel="tag"> prototype</a>, <a href="http://technorati.com/tag/javascript" rel="tag"> javascript</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ioncannon.net/programming/38/ajax-file-upload-progress-for-java-using-commons-fileupload-and-prototype/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>

