swing and spring integration – threading - part4
Typically, GUI applications have the issue that the UI itself runs in its own thread and follows some type of event-driven design. Multi-threaded GUI’s are hard to write. The event dispatching model will typically have a way to run tasks on its thread that works with (versus against) the UI system. In swing, the EDT is the event-dispatch-thread and performs this function for java swing.
If we are running a system that is suppose to handle publishing and consuming by handlers that are typically tied to the EDT, how do we arrange for all of the channel activities to be on the right thread?
One way, not so safe, is to ensure that the channel and entire infrastructure is created an runs on the EDT. We can do this by wrapping the entire program in a SwingUtilities.invokeLater(…) method to launch the program. If you look at the demo code, this is what we do. So we seem safe, at least, until we are publishing and consuming in a side thread because of a long running task or some other scenario that allows messages to be injected into our channels from outside the EDT. This leads to the second approach.
The second approach is to ensure that an message dispatching occurring inside the channel occurs on the EDT. If a subscribing message handler has a long running task it needs to run, it can cerate one using normal threading and integration techniquies e.g. see here. However, regardless of the thread where a published message is created, we want to ensure it runs on the EDT. To do this, we simply need to add an executor to the main publish and subscribe channel. The spring integration namespace config provides a task-executor attribute to attach an executor to use for dispatching events. What do we use for this attribute? We can create a very simple SwingExecutor. Lets assume that you want the swing executor to invoke its dispatch using “invoke later” to avoid a potential deadlock under invoke-and-wait. Because it uses invoke-later, you’ll need to be cognizant of timing issues related to the running of the dispatch to a handler and any sequenced updates/changes that are important to your code.
The code for the executor is:
And the configuration is: