(This is Groovy 1.8.9. The problem is fixed in Groovy 2.1.0-rc-1)
I am trying to handle exceptions that occur in a SwingBuilder.doOutside{}
. I have used Thread.setDefaultUncaughtExceptionHandler()
, but it doesn't seem to intercept the uncaught exceptions in the doOutside{}
.
Here's a sample program that illustrates the problem. If I run this from the command line and click on the EDT Exception button, I see the printStackTrace()
results on stderr. If I click Outside Exception, nothing shows. What am I doing wrong?
import groovy.swing.SwingBuilder
class ExceptionTest {
static main(args) {
Thread.setDefaultUncaughtExceptionHandler(
{ thread, exception ->
System.err.println "thread ${thread.getName()}"
exception.printStackTrace()
} as Thread.UncaughtExceptionHandler)
def swing = new SwingBuilder()
def testEDTButton = swing.button('EDT exception')
testEDTButton.actionPerformed = { throw new Exception("EDT exception") }
def testOutsideButton = swing.button('Outside Exception')
testOutsideButton.actionPerformed = { swing.doOutside { throw new Exception("Exception outside") } }
def frame = swing.frame(title: 'Test exception reporting') {
vbox {
widget(testEDTButton)
widget(testOutsideButton)
}
}
frame.pack()
frame.show()
}
}
I looked at the SwingBuilder source for Groovy 1.8.9, and it turns out that doOutside
uses ExecutorService.submit()
if it is invoked from the EDT thread:
private static final ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors())
...
DEFAULT_EXECUTOR_SERVICE.submit(c)
The submit()
returns a Future
, which gets thrown away, as you can see above. A Future
traps its exceptions and only throws an exception itself if you call Future.get()
. But that never happens in doOutside()
.
So I need put a try-catch inside the closure I pass to doOutside()
to be able to notice that an exception happened there.
NOTE: The Future
was replaced with a simple Thread.start()
in Groovy 2.1.0-rc-1 (see bug https://issues.apache.org/jira/browse/GROOVY-5074). That removes the exception trapping problem.