SwingCommand part 7 – Composite Commands

May 2nd, 2009 Nick Posted in Uncategorized No Comments »

There are occasions when it is useful to group commands together and execute several in combination. SwingCommand provides a CompositeCommandTask which allows you to group commands together in a single task which executes them sequentially.

TaskListeners on the CompositeCommandTask receive progress events as each child command is processed. The example below creates a String progress value to describe the current child command being processed.

Cancelling the composite task will cause the currently processing child command to be cancelled (if it supports cancellation), and will cause the composite task to abort processing for any remaining child command tasks. The reverse is also true – if the currently processing child command’s task is cancelled, this will cause the composite task to be cancelled and abort early.

If any of the child commands fail, the composite task will also fail with a CompositeCommandTaskException, which has the child task’s exception as the cause.

Here is a simple example of a composite task:

  SwingCommand loadThreeUsersMessages = new SwingCommand() {
 
      protected Task createTask() {
 
          CompositeCommandTask compositeTask = new CompositeCommandTask() {
 
              //let's send progress as a String update to any TaskListeners
              protected String getProgress(int currentCommandId, int totalCommands, Task currentChildCommand) {
                  return "Now running number " + currentCommandId + " out of " + totalCommands + " commands";
              }
          };
 
          compositeTask.addCommand(new LoadMessagesCommand("User 1"));
          compositeTask.addCommand(new LoadMessagesCommand("User 2"));
          compositeTask.addCommand(new LoadMessagesCommand("User 3"));
          return compositeTask;
      }
  };
 
  loadThreeUsersMessages.execute();

The composite task implements the getProgress() method to generate the String used in the progress event.

AddThis Social Bookmark Button

SwingCommand part 6 – Cancellation

May 2nd, 2009 Nick Posted in Uncategorized No Comments »

SwingCommand has support for cancellable commands. To support cancellation for a Task it is easiest if the Task extends InterruptibleTask. InterruptibleTask helps to implement the logic necessary to interrupt the background thread if cancel() is called.

When you invoke command.execute() on a SwingCommand instance, a reference to the Task which is created to handle the execution is returned from the execute() method. Getting the reference to the Task which is running can be useful – for Tasks which support the cancel operation, you may want to cancel the task by calling task.cancel()

To implement cancellation correctly, your Task must be able to respond to the interrupt request. There are two main cases to consider:

  • Interrupting a task which is blocked on IO, or on some other blocking call
  • Interrupting a task programatically by checking the isInterrupted() status periodically

Lets look at the first of these, interrupting a task which is blocking:

//interruping a background task with cancel

  SwingCommand c = new SwingCommand() {
      protected Task createTask() {

            return new InterruptibleTask() {

                public void doInBackground() throws InterruptedException {
                    Thread.sleep(10000);
                }

                public void doInEventThreadIfNotCancelled() {
                    textArea.setText("Task was not cancelled");
                }
        };
      }
  };

  //let's pop up a option pane if the task is cancelled
  c.addTaskListener(new TaskListenerAdapter() {
      public void cancelled(Task task) {
              JOptionPane.showMessageDialog(frame, "Task was Cancelled");
      }
  });


  Task t = c.execute();

  //and then a while later, from any thread...
  t.cancel();

In the example above the Task extends InterruptibleTask. During the doInBackground() handler, the background thread is blocked for a time in the call to Thread.sleep(). When task.cancel() is called by any thread, the InterruptibleTask logic will trigger thread.interrupt() on the background thread. This will result in an InterruptedException being generated by the sleep() method. Because cancel() was called, InterruptibleTask will catch the InterruptedException and the Task will finish with cancelled set to true (task.isCancelled() == true).

Note, if cancel() had not been called, the exception would have been allowed to propagate through causing TaskListeners to receive an error message, and the command would finish in the ERROR state.


What if cancel is called before or after the background processing?

If the call to task.cancel() occurs before background processing starts, the doInBackground() handler will not be called, and cancellation will always succeed. If the call to cancel() occurs after doInBackground() has returned, the call to cancel will not succeed – in this case and the task will end with isCancelled() == false.

The doInEventThreadIfNotCancelled() method is only called if the task is not cancelled. (You could alternatively override doEvenIfCancelled() if you wanted to do some post-processing in the event thread regardless of cancellation).


Interrupting a background task using custom logic

Sometimes a blocked thread will not respond automatically to thread.interrupt(). This is the case during some JDBC queries, for example. In some cases you have to implement extra logic to interrupt the task, and you can do this by overriding the doInterrupt() method. This example demonstrates how you might handle interrupting a query on a JDBC statement:

  SwingCommand c = new SwingCommand() {
      protected Task createTask() {

            return new InterruptibleTask() {

                private volatile Statement s;
                private StringBuffer text = new StringBuffer();

                public void doInBackground() throws SQLException {
                    s = connection.createStatement();
                    ResultSet r = s.executeQuery("select text from Message");
                    while(r.next()) {
                        text.append(r.getString(1)).append("\n");
                    }
                }

                protected void doInterrupt() throws SQLException {
                    Statement statement = this.s;
                    if ( s != null) {
                        s.cancel();
                    }
                }

                public void doInEventThreadIfNotCancelled() {
                    textArea.setText(text.toString());
                }
        };
      }
  };

  Task t = c.execute();

  //do something else for a while, and then call:
  t.cancel();

In the example above, the basic processing is the same, but this time we have also overridden the doInterrupt() method, to close the JDBC statement if the background query is interrupted. This should cause the statement.executeQuery() method to throw an SQLException. Because cancel() has been called, this exception will be treated as the result of a cancellation, and the task will end with isCancelled() == true.

Interrupting a task by checking isInterrupted()

There’s just one more case to demonstrate. How to handle a non-blocking cancel. This is actually quite simple – you just need to periodically check the isInterrupted() method, and return early if necessary:

SwingCommand c = new SwingCommand() {
      protected Task createTask() {
         
        return new InterruptibleTask() {

            public void doInBackground() throws InterruptedException {
                for ( int loop=0; loop < 1000000; loop ++) {
                    if ( isInterrupted() ) {
                        break;
                    }
                }
            }

            public void doInEventThreadIfNotCancelled() {
                textArea.setText("Task was not cancelled");
            }
        };
      }
  };

Here the doInBackground() handler enters a processing loop. On each iteration, it checks to see if isInterrupted() is true – this will be the case if cancel() has been called on the task. If so, it breaks the loop to end the processing early.

Note that a task is considered cancelled even if the doInBackground() does not return early, provided that when the doInBackground() method returns the background thread still has its interrupted flag set.

Whew – that’s a fair amout to absorb. But the thing to take away is that extending InterruptedTask makes handling cancel easy. There is very little boilerplate code in the examples above, and you shouldn’t need to work too hard to get this right.

AddThis Social Bookmark Button

SwingCommand part 5 – Task States and Error Handling

May 2nd, 2009 Nick Posted in Uncategorized No Comments »

Task States

It is possible to find the current state of a Task instance directly by calling task.getExecutionState();
There are six ExecutionStates: NOT_RUN, PENDING, STARTED, SUCCESS, CANCELLED and ERROR.

A task starts in state NOT_RUN. During the call to command.execute(), the state will change to PENDING. Once task processing begins (which may be some time later if the task is queued for processing or is blocked waiting for a thread from a thread pool) the state moves to STARTED. The final state will be either SUCCESS , ERROR or CANCELLED. In the case that a Task finishes in ERROR, you can obtain the Exception that caused the error by calling task.getExecutionException()

If a SwingCommand task handler method ( doInEventThread() or doInBackground() ) throws an Exception the task is considered to have failed. Any TaskListeners will receive an error() callback, and the task will end in the ExecutionState.ERROR state.

Ending a SwingCommand Early

If an exception is thrown during doInBackground(), the doInEventThread() handler will not be called. Instead, processing is aborted before doInEventThread() is called. This makes sense, because in most cases we will not want to update the ui if, for example, a task loading data failed.

However, sometimes you will need to perform error handling in the Swing Event Thread, or perform some processing whether or not an error occurs or the task is cancelled. For example you may need to stop a progress animation. These cases are best handled by a TaskListener, in the error() method, or the finished() method respectively.

The finished() callback always occurs, no matter if the task succeeds, fails or is cancelled. The TaskListener methods also allow you to perform handling only on success (the success() callback).

  SwingCommand c = new SwingCommand() {
      protected Task createTask() {
          return new BackgroundTask() {

              public void doInBackground() throws Exception {
                  //this method throws an exception instead of returning
                  throw new Exception("woe");
              }

              public void doInEventThread() throws Exception {
                  //So we'll never get here!
              }
          };
      }
  };

     
  c.addTaskListener(new TaskListenerAdapter() {
     
      public void error(Task task, Throwable error) {
          JOptionPane.showMessageDialog(frame, "Failed to Load Messages");
      }
   
      public void finished(Task task) {
          //the task will finish in the ERROR state since doInBackground() threw an Exception
          assert(Task.ExecutionState.ERROR == task.getExecutionState());
       
          //we can get the error back by calling task.getExecutionException()
          Throwable cause = task.getExecutionException();
      }
  });

  c.execute();
AddThis Social Bookmark Button

SwingCommand part 4 – Using Executors

May 2nd, 2009 Nick Posted in Uncategorized No Comments »

SwingCommand has good integration with the java.util.Concurrent, and this allows you to control which background thread will be used to run your BackgroundTask. You can specify the Executor which should be used by your SwingCommand.

This can be very useful. For example, there are occasions when it is important to ensure that only one background task of a certain type runs at a time. You could achieve this in the UI by disabling buttons or menu items while a command executes – but if your SwingCommand instance is shared and used in many areas of your application it might be nice to provide a firmer guarantee.

To achieve this, you could associate a single thread Executor with a SwingCommand. If the SwingCommand is executed again before the initial task has finished running, the second Task will then be queued to start processing once the first has completed. (Sometimes it is also a good idea to cancel the currently processing task at this point.)

//To make doubly sure no two tasks execute concurrently for this command
//we can associate a single thread executor -

  command.setExecutor(Executors.newSingleThreadExecutor());

Using a Thread Pool

Alternatively, let’s pretend there are many different commands in our app, and our users hammer buttons as if they were being paid per click. We don’t want to risk spamming the database server with requests (it’s probably on its last legs anyway!). A good solution might be to impose a limit on the number of threads which can concurrently run background tasks in our application. Once these threads are active, any new Tasks will be queued until there is a spare thread.

We could do this very easily by specifying a fixed size thread pool for all our SwingCommands. For example, the following code snippit creates a thread pool limited to three threads, and associates it with a command.

//using a Thread pool Executor

  Executor e = Executors.newFixedThreadPool(3);
  command.setExecutor(e);

To make sure all our commands use the thread pool, we could subclass SwingCommand to supply the thread pool Executor as the default. We could then use ThreadPoolSwingCommand instead of the basic SwingCommand throughout out application.

//Let's extend SwingCommand so that by default our commands share a fixed size thread pool:
//Our SwingCommand classes should all subclass this instead

  static abstract class ThreadPoolSwingCommand<P> extends SwingCommand<P> {

      private static Executor threadPoolExecutor = Executors.newFixedThreadPool(3);

      protected Executor getDefaultBackgroundTaskExecutor() {
          return threadPoolExecutor;
      }

  }

Setting one-off Executors

Similar to TaskListeners, you can also specify an Executor to be used for a one-off invocation of a SwingCommand. You do this by passing an Executor into the execute() method.

//specify an Executor for a single execution

  SwingCommand<String> c = new LoadMessagesCommand("My User");
  c.execute(Executors.newSingleThreadExecutor());

Processing a SwingCommand synchronously on a background thread

Passing in an Executor to the execute() method in this way can change the way in which a SwingCommand is processed. Usually, a SwingCommand launched from a background thread is processed asynchronously, so as not to block the thread which calls execute(). However, in some cases you may want the current background thread to be used for the execution of the Task – in which case the call to command.execute() will not return until the Task has finished processing. In this case, you can pass in a simple Executor which runs the command on the current thread:

  //use an Executor which makes a SwingCommand execute synchronously from a background thread
 
  SwingCommand<String> c = new LoadMessagesCommand("My User");
  c.execute(new Executor() {
    public void execute(Runnable command) {
      //just process synchronously in the current thread
      command.run();
    }
  });

In the above example the normal threading guarantees for the Task are still obeyed – doInEventThread() will still be run in the Swing Event Thread. The background thread will be blocked while the EventThread does its work.

It should be clear from the above that the ability to set the Executor for a SwingCommand or a Task gives you a lot of control over the threads used to process your SwingCommands.

AddThis Social Bookmark Button

SwingCommand part 3 – Showing Progress

May 2nd, 2009 Nick Posted in Uncategorized No Comments »

The progress animation triggered by the TaskListener in the previous example would at least inform the user that a SwingCommand is executing. However, sometimes it may be useful for a long running command to show publish interim results, or simply post more descriptive progress updates.

To help with this, as well as allowing you to set the generic type for parameters to your SwingCommand, the SwingCommand class also allows you to specify a generic type for a progress update. The following example demonstrates perhaps a simple case, in which an Integer progress event is fired:

//Here I have updated the ClearMessagesCommand to publish progress messages as a Integer

  class ClearMessagesCommand extends SwingCommand<String,Integer> {

      public ClearMessagesCommand() {
      }

      public Task<String,Integer> createTask() {

          return new BackgroundTask<String,Integer>() {

              public void doInBackground() throws Exception {
                  fireProgress(1);

                  String userName = getParameters();
                  Statement s = connection.createStatement();
                  s.execute("delete from Message where User = " + userName);

                  fireProgress(2);
              }

              public void doInEventThread() {
                  fireProgress(3);    
              }
          };
      }
  }

  SwingCommand<String,Integer> c = new ClearMessagesCommand();
  c.execute("Nick");

  c.addTaskListener(new TaskListenerAdapter<Integer>() {
      public void progress(Task task, Integer progressDescription) {
          progressLabel.setText("stage " + String.valueOf(progressDescription));
      }
  });

You could do more sophisticated things by firing progress, and progress events make it easy to update the UI safely – remember that these messages are received on the Swing Event thread even if fired from doInBackground().

For example, you could use this mechanism to gradually populate messages into an ‘inbox’ while reading mail messages from a remote server. Or you could send an Integer progress update representing a percentage value, to update a progress bar with the current percentage of work completed by a background thread.

AddThis Social Bookmark Button

SwingCommand part 2 – TaskListeners

May 2nd, 2009 Nick Posted in Uncategorized No Comments »

A common requirement in User Interfaces is to show an animation while a background task runs. How might this be accomplished using SwingCommand?

The following example shows how you can add a TaskListener to a command. The TaskListener will receive events as the command executes, and start and stop an animation.

TaskListeners always receive their events on the Swing Event thread, even if the Task is a BackgroundTask.

//TaskListeners always receive their events on the Swing event thread

  LoadMessagesCommand command = new LoadMessagesCommand("My User");

  TaskListener animationListener = new TaskListenerAdapter() {
      public void pending(Task task) {
          startProgressAnimation();
      }

      public void finished(Task task) {
          stopProgressAnimation();
      }
  };

  command.addTaskListener(animationListener);
  command.execute();
  }

Every time the command is executed, the SwingCommand creates a new Task instance, and the TaskListener will receive events while the Task runs.

It’s also possible to add a TaskListener to receive events for a single SwingCommand invocation, by passing it as a parameter to the execute() method:

//Let's add a listener to perform some error handling..
//this listener will not receive events on any subsequent executions:

  LoadMessagesCommand command = new LoadMessagesCommand("My User");

  command.execute(new TaskListenerAdapter() {
      public void error(Task task, Throwable error) {
          System.err.println("Oops, perhaps our database is offline");
      }
  });

The ability to add TaskListeners to SwingCommands is a key feature of SwingCommand, and it can be very convenient. For example, you could create several different commands and add a shared listener which tracks the background tasks and updates progress components on your UI. This listener will receive events on the Swing Event thread whenever one of the commands is executed, no matter which thread or which class actually executes it.

Separation of concerns

TaskListeners are a very useful mechanism. They allow you to separate the logic for handling progress animations, and error handling logic, from the main Task processing logic. You could, for example, provide a TaskListener which performs consistent error handling for all of the commands in your application. This is a good separation of concerns. Mixing that logic in with the main command processing logic tends to clutter the code up and make classes less easy to reuse – and there are certainly cases where you might want different error handling depending on the situation in which the SwingCommand is executed (e.g. if it’s executed in response to a button click in a Dialog, you may want to show an error message in the Dialog, rather than the main UI frame). To achive this, you can add some listeners to the SwingCommand, which will get notified whenever it is executed, and others context specific listeners can be passed as parameters to SwingCommand.execute().

The TaskListener interface

There are actually six listener methods in the TaskListener interface. Some of these are always invoked, others are only invoked if a Task enters a specific state (ERROR or SUCCESS) for example. To avoid having to implement all the methods, you can extend TaskListenerAdapter.

The full definition of the TaskListener interface is below:

/**
 * Implement this interface to listen to the progress of a task
 * Callbacks on this interface are guaranteed to be received on the AWT event thread,
 * even if fired by an BackgroundTask
 *
 * These callbacks provide an easy and safe way to update the UI to show the progress of a task.
 *
 * <P> - the type of Progress object that this TaskListener will receive
 */

public interface TaskListener<P> {

    /**
     * The callback to pending is triggered when command.execute() is called
     * If the Executor running the task queues the task or blocks waiting for
     * a thread, it may be some time before started() is invoked.
     */

    void pending(Task task);

    /**
     * Called when the task starts processing. For BackgroundTask this callback
     * takes place just before doInBackground is called. For SimpleTask just before doInEventThread
     */

    void started(Task task);

    /**
     * This callback may take place at any time during task execution, to indicate progress
     */

    void progress(Task task, P progress);

    /**
     * Called when the task reaches the SUCCESS end state
     * This callback takes place once a command has successfully completed (was not cancelled,
     * and did not throw an Exception resulting in a callback to error())
     */

    void success(Task task);

    /**
     * Called when the task reaches the ERROR end state
     * This callback takes place if an exception is raised during task execution, which prevents
     * successful completion
     */

    void error(Task task, Throwable error);

    /**
     * Called when the task reaches the CANCELLED end state
     * This callback takes place if the task is cancelled.
     * @param task
     */

    void cancelled(Task task);

    /**
     * This callback always takes place once the task has finished, whether or not the
     * task finishes in ERROR, SUCCESS or CANCELLED states
     */

    void finished(Task task);
}
AddThis Social Bookmark Button

SwingCommand part 1 – Creating Commands

May 2nd, 2009 Nick Posted in Uncategorized No Comments »

This is the first of several blog posts in which I’ll demonstrate how to use the SwingCommand library to handle background tasks in Swing apps.

SwingCommand version 2 has recently been released, and it contains a lot of improvements.

It’s high time to add more documentation!

First let’s recap a bit.

SwingCommand targets the same problem area as SwingWorker – namely, how to handle background tasks and update the UI safely in Swing. Recall that you should generally only access Swing components and their models on the Swing Event Thread, due to Swing’s threading model. See the Swing tutorial if you are unfamiliar with this.

The main difference between SwingCommand and SwingWorker is that each SwingCommand instance can be executed multiple times. Each time you execute a SwingCommand, a Task instance is generated, which performs the processing and wraps the state and any parameters used for that execution. This means that SwingCommand instances can be created once and shared throughout your application. (There’s nothing to stop you creating a SwingCommand for one-off use, if this makes more sense in some situations).

This is how to create a simple SwingCommand

  //This SwingCommand creates a Task which runs only on the Swing Event thread:
  final JTextArea textArea = new JTextArea();
 
  class ClearTextAreaCommand extends SwingCommand {
      public Task createTask() {
          return new Task() {
              public void doInEventThread() {
                  textArea.setText("");
              }
          };
      }
  }
 
  //Run the command
  SwingCommand c = new ClearTextAreaCommand();
  c.execute();

The task created by the SwingCommand above does not do any processing in a background thread – the doInEventThread() handler method will always be called in the SwingEvent thread, even if another Thread calls the execute() method. To create a task which does run in a background thread, we would need to extend BackgroundTask rather than extending Task directly.

Why would you want to create a SwingCommand which doesn’t run a background task?

Well, one of the main drivers for this, and for the Command pattern in general one might say, is reuse. A SwingCommand encapsulates a chunk of ui logic which can be shared throughout your app. Whenever you find yourself tempted to duplicate ui code, that’s a good time to consider creating a SwingCommand.

It’s also nice that both ‘Background Tasks’ and ‘Event Thread Only tasks’ extend the same Task abstraction, so that in many places in your client code, you need not descriminate between the two types.

If your command does need to perform processing on a background thread, it should create a task which extends BackgroundTask. The following example shows how you might write a command which queries the database to retreive some email messages for a user:

Creating a command which performs some work on a background thread:

//Class to load user messages:
  class LoadMessagesCommand extends SwingCommand {

      private Connection connection;
      private String userName;

      public LoadMessagesCommand(Connection connection, String userName) {
          this.connection = connection;
          this.userName = userName;
      }

      public Task createTask() {
          return new BackgroundTask() {

              StringBuilder text = new StringBuilder();

              public void doInBackground() throws SQLException {
                  Statement s = connection.createStatement();
                  ResultSet r = s.executeQuery("select text from Message where user = " + userName);
                  while(r.next()) {
                      text.append(r.getString(1)).append("\n");
                  }
              }

              public void doInEventThread() {
                  textArea.setText(text.toString());
              }

          };
      }
  }

  SwingCommand c = new LoadMessagesCommand(connection, "My User");
  c.execute();

The SwingCommand above runs a database query in a background thread, and then updates a text area in the Swing Event thread. The command could be created and executed either from the Swing Event thread or from a background thread, and SwingCommand will ensure that the call to doInBackground() occurs in a background thread, and doInEventThread() occurs in the Event thread. In fact, the command could be created in one thread, and executed from another and this guarantee still applies.

One thing to note – in both the above examples, the Task type created by the SwingCommand is an inner class. This is purely for convenience, since it is often easiest to write SwingCommands this way. If you prefer not to use an inner class for this, it’s quite possible for a Task to be implemented as a top level class.

Passing parameters to Commands

Commands often take their parameters from Swing components – for example a value from a JSpinner or a JTextField. In this case, the simplest way to manage things is often to construct the SwingCommand with a reference to the inputs – then when createTask() is called you can read the values from the components and use them in the Task. You can either construct the Task with the parameter values, or if Task is an inner class pass them in as final reference, as below:

//Use a JTextField as a Task parameter

class ClearMessagesCommand extends SwingCommand {

      private JTextField usernameField;

      public ClearMessagesCommand(JTextField usernameField) {
          this.usernameField = usernameField;
      }

      public Task createTask() {
         
          final String user = usernameField.getText();
         
          return new BackgroundTask() {

              public void doInBackground() throws SQLException {
                  Statement s = connection.createStatement();
                  s.execute("delete from Message where User = " + user);
              }

              public void doInEventThread() {
              }
          };
      }
  }

  JTextField userNameField = new JTextField();
  SwingCommand c = new ClearMessagesCommand(userNameField);
  c.execute();

Whenever the above ClearMessagesCommand is executed, it will read the current value from the supplied text field and use it to clear the messages for the named user.

The above pattern is nice because any of your other classes which want to execute the command don’t need to know about the text field. They can just call command.execute(). There may however be instances where you want to pass a parameter into the command when you call command.execute(). This is also possible. When you create a SwingCommand, you can define a generic type for a parameter. You can pass in instance of that parameter into execute(), and then access it from within the Task which is created.

The command below requires a String parameter. This is the first of the two generic types specified for the SwingCommand. The second String specified in SwingCommand actually defines what type of progress object the command can publish – but we’ll talk more about that in another example.

class ClearMessagesCommand extends SwingCommand<String,String> {

      public ClearMessagesCommand() {
      }

      public Task<String,String> createTask() {

          return new BackgroundTask<String,String>() {

              public void doInBackground() throws Exception {
                 
                  //get the parameter object passed to execute()
                  String userName = getParameters();

                  Statement s = connection.createStatement();
                  s.execute("delete from Message where User = " + userName);
              }

              public void doInEventThread() {
              }
          };
      }
  }

  SwingCommand<String,String> c = new ClearMessagesCommand();
  c.execute("Nick");

So the command above now expects to be passed a String username via the command.execute() method. Ideally it would be good to check that this has been set in doInBackground(), and if not either supply a default value or throw an Exception to indicate the command execution failed.

You probably have a lot more questions about the example above. For example, ‘How would you show progress to the user?’, ‘how does it handle any Exceptions generated during doInBackground?’, or ‘what controls which background thread runs the Task?’. I’ll address these issues in subsequent posts.

AddThis Social Bookmark Button