When a user executes a long running background task an application usually wants to report progress about the task to the user. Application developers often do this by passing a ProgressListener to the background task’s  method and the method uses the ProgressListener to report it’s progress. But you can also design it in another way and I would like to introduce another pattern here. At least I would like to show an example of how to implement a progress object pattern with Javas Swing. The complete example code is available at gitthub: https://github.com/link-intersystems/blog/tree/master/progress-object-pattern.

But before I introduce the progress object patten let us take a look at the progress listener concept.

Progress listener

A progress listener is conceptually a callback that a background task can use to report it’s progress. Thus you usually first define a ProgressListener interface.

Since the ProgressListener is just an interface clients can adapt specialized implementations. E.g. a StdoutProgressListener

Background tasks will then take a ProgressListener  as parameter so that they can report progress. E.g.

In this case a client must create an instance of a ProgressListener and pass it to the task.

Progress object pattern

Some time ago I thought about other options of how to implement progress reporting in an application and came accross another pattern that I call the progress object pattern. Let me summerize my thoughts that lead to that pattern.

In Java 1.5 the java.util.concurrent.Future<T> interface was introduced to represent a reference to an object that will be available in the future. This means that there is some kind of process that must be finished and the result is that future object. Well, if the process knows all of the actions it must do to create the object it can report progress.

To summerize this:

A process is a series of steps or actions that must be done in order to achieve a goal.
Progress is the knowlede about a process’s state

A Future object is a reference to an object that will be available in the future.  A progress is the state of a process that will produce that future object. Thus we can design a progress as an extension of a Future by introducing a new type called Progress<T> extends Future<T>. E.g.

Progress Object Pattern

A method that can report progress must now just change it’s return type to Progress<T>. So if a method returns a Progress<T> it can report progress and if it returns a Future<T> it can’t. E.g.

Code evolution of Progress Listener vs. Progress Object

Lets take a look at the impacts that code evolution from a non-progress method to a progress method has using either a ProgressListener or a ProgressObject.

Code evolution with a ProgressListener

To make the change downwardly compatible you must introduce a new method that supports progress and delegate calls from the former method to that method.

The implementation of the progress method is easier if you use a null object pattern in the delegate method instead of passing a null reference.

Code evolution with a Progress Object

Differences between a progress listener and progress object

The main difference is the instantiation of the progress reporting object. When you use a ProgressListener callback, client code must instantiate it and pass it to a method that can report progress and the progress method must change it’s signature to take a ProgressListener parameter. Changing the parameters of a method can make it incompatible with former legal client code or you introduce a delegate method as shown above.

Progress Listener: former client code

Progress Listener: evolved client code

Progress Object: former client code

Progress Object: evolved client code

Since I extend Progress<T> from Future<T> a client that is not interessted in progress can simply use the Future<T> interface while another client uses the Progress<T>.

Progress Object state change notification

Just replacing a Future<T> with Progress<T> is not enough to get informed about progress state changes. But fortunately we can solve this problem easy using the Java Beans API. The Progress<T> must support property change events. E.g.

Progress Property Change Support

 

Real life Progress Object example with Java Swing

In Java Swing a SwingWorker is usually used to execute background tasks. Fortunately a SwingWorker implements a Future. A SwingWorker also has a progress property so half of the work is already done. Thank’s to the designers of SwingWorker and the Java API.

So let’s design the interfaces in smart way so that we can easity adapt a SwingWorker.

Now that we have the interfaces we can implement a ProgressWorker<T> that extends a SwingWorker and makes it a Progress<T>.

Since a SwingWorker already supports PropertyChangeListeners  and fires “progress” property change events  we are done. Of couse you must not implement a ProgressWorker. It can also be done just using a SwingWorker but the additional Progress interface adds  more flexibility in application design and classes that only depend on the Progress interface are more easier to unit test.

At least we need an Action that is responsible for

  • getting user data from UI models
  • execute something that returns a Progress
  • bind the Progress to everyone who is interessted in progress
  • get the result of the progress and update UI models

In order to get notified about the SwingWorker‘s state I implemented an adapter class that other can subclass – a SwingWorkerPropertyChangeAdapter.

The ProgressAction implementation I choose is this:

And for everyone that is interrested in progress I added a ProgressAware interface.

You can get the complete example code on github: https://github.com/link-intersystems/blog/tree/master/progress-object-pattern

progress-object-swing-example