Collin Fagan is a Sr. Software Engineer at NAVTEQ working on next generation map building software. He holds a BS in Computer Science from the Rochester Institute of Technology. Collin has worked in the Map, Medical, Produce Warehousing and Telecommunications industries on a wide assortment of projects ranging from customized Linux thin clients to highly concurrent telecommunications control systems. Collin has posted 13 posts at DZone. View Full User Profile

More First Class Methods Code

03.10.2008
| 5662 views |
  • submit to reddit

I'm still experimenting with the prototype implementation of the FCM closures proposal. Here are a few utility methods that immediately came to mind.

withLock -- This one I've seen an example of online a few times. It automatically release the lock when the block of code finishes executing.

public static void withLock(Lock lock, Runnable task) {
lock.lock();
try {
task.run();
} catch (Exception e) {
throw e;
} finally {
lock.unlock();
}
}
Example Usage:
final ReentrantLock lock = new ReentrantLock();
withLock(lock, #{
// call some important locked code
});
Now I'm not too fond of unchecked Exceptions, but rethrowing is still better then swallowing every exception that escapes the Runnable. Here is my second attempt.
private static interface ExceptionHandler {
public void uncaughtException(Runnable source, Throwable e);
}

public static void withLock(Lock lock, Runnable task, ExceptionHandler eHandel) {
lock.lock();
try {
task.run();
} catch (Exception e) {
eHandel.uncaughtException(task, e);
} finally {
lock.unlock();
}
}
Example Usage:
withLock(lock, #{
// do some code that needs to be locked.
// throw an exception to test the event handler.
throw new RuntimeException("year is even error");
}, #(Runnable source, Throwable e){
// inline implemented event handler.
e.printStackTrace();
}
);
Once side effect of this is now one might be able to write reusable exception handling code. There have been plenty of times where a method I'm executing throws an exception, but there is no real way for me to recover. All I can do is log the failure and continue on. I end up writing the same try catch block over and over. It would be nice to write something like this once and reuse it.
public class LogAndContinueExceptionHandler implements ExceptionHandler{
public void uncaughtException(Runnable source, final Throwable e) {
SwingUtilities.invokeLater(#{
Logger.getLogger("ErrorLogger").log(Level.SEVERE, e.getMessage(), e);
});
}
}
Example Usage:
withLock(lock, #{
// do some code that needs to be locked.
// throw an exception to test the event handler.
throw new RuntimeException("year is even error");
}, new LogAndContinueExceptionHandler());
I used this idea when exploring another area that might benefit from closures. The EDT thread scheduling methods.

invokeAndWait
public static void invokeAndWait(Runnable r, ExceptionHandler eHandel){
try {
SwingUtilities.invokeAndWait(r);
catch (InterruptedException e) {
eHandel.uncaughtException(e);
} catch (InvocationTargetException e) {
eHandel.uncaughtException(r, e.getCause());
}
}

public class AlertAndContinueExceptionHandler implements ExceptionHandler{
public void uncaughtException(Runnable source, final Throwable e) {
Runnable showMessageBox = #{
JOptionPane.showMessageDialog(null, e.getMessage());
};
if(SwingUtilities.isEventDispatchThread()){
showMessageBox.run();
}else{
SwingUtilities.invokeLater(showMessageBox);
}
}
}
Example Usage:
invokeAndWait(#{
JOptionPane.showMessageDialog(null, "Hello World");
}, new AlertAndContinueExceptionHandler());
simpleSwingWorker -- The simpleSwingWorker method is an attempt to apply closures to the simple case of, "do something off the EDT then do something ON the EDT".
public static void simpleWorker(final Runnable offEDT, final Runnable onEDT){
Thread bGround = new Thread(#{
offEDT.run();
SwingUtilities.invokeLater(onEDT);
});
bGround.start();
}
Example Usage:
simpleWorker(#{
System.out.println("sleep");
Thread.currentThread().sleep(1000);
System.out.println("start");
}, #{
JOptionPane.showMessageDialog(null, "Hello World");
});
I also wrote a blocking version based on invokeAndWait.
public static void simpleBlockingWorker(final Runnable offEDT, final Runnable onEDT){
Thread bGround = new Thread(#{
offEDT.run();
SwingUtilities.invokeAndWait(onEDT);
});
bGround.start();
}

Hay wait a second, invokeAndWait throws exceptions right? And yet the code as it stands compiles without issue. I think I may have found a bug in the FCM prototype.

Some may look at these examples and point out that this type of functionality may really fall into the realm of "control structures". There is some debate in the Java community as to weather the common man should be allowed to write their own control structures. Some prefer to leave this responsibility with the language designers. It is my opinion that once you make this type of code easy, then you already have allowed the common man to make their own control structures. In that case you might as well legitimize the pattern and provide as much support as is possible.

I look forward to the day when there is a Java Control Abstraction (JCA) prototype to play around with.
Published at DZone with permission of its author, Collin Fagan.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Stefan Schulz replied on Tue, 2008/03/11 - 5:51pm

It's cool to see some FCM code. Of course, the prototype is not perfect, and you should have recognized right in your first example, what you noticed in your final one ;)

One thing, though: the JCA would not allow you to do EDT stuff, as it uses unrestricted blocks (allowing for break, return and continue). In our view it would obscure the control flow, as it presents as being executed immediately while passing anonymous methods visually hands over a block of code.

Nice examples, though, which made me jealous when still using Java5 at work. ;) 

Collin Fagan replied on Tue, 2008/03/11 - 6:36pm

I think it's really functional for an early prototype. I'm getting used to the # syntax. I tried to use it at work today before realizing what I was doing. I'm also stuck with Java5 so I feel your pain.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.