#{extends 'jqueryui/layout.html'/} #{set title:'Progress bar'/}

Progress bar

Use a progress bar to show progress for a server-size process for which the completion percentage can be calculated. Play’s web sockets support is ideal for updating the progress bar, and Play’s asynchronous jobs are suitable for long-running jobs.

Demo

Note that the WebSocket API version used by Play 1.2.3 is only supported by Safari and Chrome (less than version 14). Play 1.2.4 is expected to support Safari, Chrome, Firefox and Internet Explorer 10.

#{form @startJob()}

#{/form} #{if processId}

Job ${processId} progress:

#{/if}

Client

The widget is based on an empty HTML div element.

<div id="progressbar" data-url="@@{jqueryui.ProgressSocket.progress(processId)}"></div>

The data-url attribute value specifies the URL for a web socket connection. Note that the template uses the @@ syntax to generate an absolute URL that includes the web socket protocol - @@{jqueryui.ProgressSocket.progress(processId)}.

The progressbar.js JavaScript applies the jQuery UI dialog plug-in to the div element and opens a web socket connection. Finally, the JavaScript uses web socket messages to update the progress bar value.

#{includeVerbatim '/public/javascripts/progressbar.js'/}

Server

The server-side has three parts. First, we define an implementation of a long-running job, which has a generated UUID identifier and an event stream that the job will publish progress to. The implementation in this example simply waits for short intervals, publishing progress to the event stream after each one.

#{includeVerbatim 'app/models/jqueryui/Process.java'/}

The second server-side class is a conventional action that starts an asynchronous long-running job, and stores a reference to the job in a ‘registry’ singleton. This action then renders the same page with a processId argument that indicates that a job has been started.

#{includeVerbatim 'app/controllers/jqueryui/Progressbar.java'/}

The last part is a is a web socket controller that retrieves the running job from the registry, using its ID, and waits for events on the job’s event stream. When the job publishes a completion percentage to its event stream, the controller sends the data in a web socket message to the browser client.

#{includeVerbatim 'app/controllers/jqueryui/ProgressSocket.java'/}

Note that this design means that the job is started by a conventional HTTP POST request to the Progressbar.startJob() action, which means that the job is executed even if the client does not have web socket support and is therefore unable to update the progress bar.

One possible enhancement would be to add JavaScript to detect the case where web sockets are not supported, and send a single Ajax request to get the current progress value to update the progress bar.