Foxtrot - Easy API for JFC/Swing - Documentation
Last Updated: $Date: 2005-03-22 05:00:37Z $

Foxtrot API

The Foxtrot API is very small and simple, and consists of 3 main classes:

  • class foxtrot.Worker
  • class foxtrot.Task
  • class foxtrot.Job

From Foxtrot 2.x, the API has been extended to allow customization of the part that handles event pumping and of the part that handles execution of Tasks and Jobs in a worker thread, via the following classes:

  • interface foxtrot.EventPump
  • interface foxtrot.WorkerThread
  • class foxtrot.AbstractWorkerThread

Normally users do not need to deal with these classes to use Foxtrot in their Swing applications, since Foxtrot will configure itself with the most suitable implementations; however, if a specific customization of the event pumping mechanism or of the worker thread mechanism is needed, the APIs provided by these classes allow fine grained control on Foxtrot's behavior.

Foxtrot API Details

The Worker class is used to post Tasks or Jobs that will be executed in the Foxtrot Worker Thread.

The Task class is subclassed by the user to perform heavy tasks that throw checked exceptions.

The Job class, conversely, is subclassed by the user to perform heavy tasks that do not throw checked exceptions, but only RuntimeExceptions (or Errors).

The Worker class has the following 2 public methods that can be used to post Tasks or Jobs:

  • public static Object post(Task task) throws Exception
  • public static Object post(Job job)

The Task class has a single abstract method that must be implemented by the user, with the time-consuming code that may throw checked exceptions:

  • public abstract Object run() throws Exception

The Job class, conversely, has a single abstract method that must be implemented by the user, with the time-consuming code that does not throw checked exceptions:

  • public abstract Object run()

The exceptions or errors thrown inside the Task.run() or Job.run() methods are re-thrown by the corrispondent Worker.post(...) method as is, i.e. without being wrapped into, for example, an InvocationTargetException.

The usage is very simple; here's an example with the Job class:


Worker.post(new Job()
{
   public Object run()
   {
      // Here write the time-consuming code
      // that does not throw checked exceptions
   }
});

and here's an example with the Task class:


try
{
   Worker.post(new Task()
   {
      public Object run() throws Exception
      {
         // Here write the time-consuming code
         // that may throw checked exceptions
      }
   });
}
catch (Exception x)
{
   // Handle the exception thrown by the Task
}

It is possible to narrow the throws clause of the Task class, but unfortunately not the one of the Worker class.
So, when using the Worker.post(Task task) method, you have to surround it in a try...catch(Exception x) block (unless the method that contains Worker.post(Task task) throws Exception itself).


try
{
   Worker.post(new Task()
   {
      public Object run() throws FileNotFoundException
      {
         // Here write the time-consuming code
         // that accesses the file system
      }
   });
}
catch (FileNotFoundException x)
{
   // Handle the exception or rethrow.
}
catch (RuntimeException x)
{
   // RuntimeExceptions are always possible.
   // Catch them here to prevent they are
   // ignored by the catch(Exception ignored)
   // block below.
   throw x;
}
catch (Exception ignored)
{
   // No other checked exceptions are thrown
   // by the Task (the compiler will enforce this),
   // so we can safely ignore it, but we're forced
   // to write this catch block: Worker.post(Task t)
   // requires it.
}

The Worker class, from Foxtrot 2.x, has the following public methods to deal with the EventPump and WorkerThread components:

  • public static EventPump getEventPump()
  • public static void setEventPump(EventPump pump)
  • public static WorkerThread getWorkerThread()
  • public static void setWorkerThread(WorkerThread worker)

Foxtrot configures itself automatically with the most suitable implementation of EventPump and WorkerThread. Some implementations of EventPump or WorkerThread allow an even further customization of the component.

For example, implementations of EventPump that also implement the foxtrot.pumps.EventFilterable interface may allow the user to filter events that are being dispatched by the java.awt.EventQueue. See also the bundled Javadocs for further details.
However, it is recommended not to exploit these features unless knowing exactly what one is doing: Foxtrot's defaults may change from version to version to suit better implementations, and these defaults may depend on the Java Runtime Environment version Foxtrot is running on, so that features working in JDK 1.3.x may not work in JDK 1.4.x or viceversa.
Playing with AWT events too badly is normally looking for troubles, so consider you warned :)

The same holds for WorkerThread implementations, that should extend the abstract class AbstractWorkerThread: Foxtrot uses a synchronous model, so replacing (for example) the default WorkerThread implementation (that uses a single worker thread) with an implementation that uses multiple pooled threads does not lead (in the common case) to a great speed-up of Tasks execution.
To be more precise, with a multiple thread implementation of WorkerThread, Tasks posted from pumped events will return control to the initial caller after a time that is (roughly) the time of the longest Task, while with the default implementation will be after a time that is (roughly) the sum of the times of all Tasks posted from pumped events.
Tasks posted from pumped events are normally a rare case, and may not be worth the effort of a multiple thread implementation of WorkerThread.

Refer to the bundled Javadoc documentation for further information, and to the bundled examples for further details on how to use the Foxtrot classes with Swing. And do not forget the Tip 'n' Tricks section !