Ruby and Blocks go together like chocolate and peanut butter. With JRuby, you can use blocks to solve old Java problems in new and interesting ways. Earlier this week, while scripting a Swing client, we found that some of our code would generate exceptions from the AWT Thread. I know what you’re thinking: “This sounds like a job for invokeLater.” We thought so too, except, what we really wanted to do was pass a block to invokeLater. Here’s what we came up with:
class BlockRunner < java.lang.Thread def initialize(&proc) @p = proc end def run @p.call end end SwingUtils = javax.swing.SwingUtilities def SwingUtils.invoke_block_later(&proc) r = BlockRunner.new &proc invoke_later r end
This code creates BlockRunner, which extends java.lang.Thread. BlockRunner is initialized by passing a block to new. The block is wrapped in a Proc object, which is called when the BlockRunner thread is executed. The SwingUtils#invoke_block_later method instantiates a new BlockRunner, which is passed to #invoke_later.
A call to #invoke_block_later might look like this:
SwingUtils.invoke_block_later do some_widget.text = 'blah' end
Nothing here is particularly earth-shattering. There may even be a better way to this. What’s cool is that, in a very few lines of code, we were able to create an elegant solution to our problem. A solution that looks familiar to Java programmers, while not looking out of place in a Ruby program.