|
Why UI event handling may not scale
Event handling using event sources and event listeners doesn't scale.
Not at least if you don't take dependencies into account.
That's a fact. Let me explain.
Think of a Swing application as composed of major "macro-components". Say you have
an editor, a settings dialog, a status bar, a console window, a filesystem tree-view
for displaying file info, whatever you may think of.
If your application is small then it's probably ok to keep a one-to-one integration between
these macro-components. You make the editor a listener of the settings dialog. You make the
status bar a listener of the editor. You make the editor a listener of the filesystem tree-view.
Easy. Business as usual.
But if your application starts to grow then you're in trouble with a one-to-one integration.
After all if your application has "n" major macro-components then you need "n times n"
one-to-one integrations. If "n" is 10 then you need 100 one-to-one integrations. That's nightmare.
It's easy to have loops of listeners between major macro-components because it's difficult
for you to track dependencies, and you don't know who is sending what when.
Order of events starts being problematic. You're in serious trouble.
The SOA equivalence
That's exactly the same situation most of our customers are facing inside datacenters.
They're in trouble trying to integrate applications when the number of applications grow.
It's difficult for them to extract information from those, it's difficult for them to keep
information simple. Their information starts to be duplicated in different applications.
They're in trouble too.
That's one of the reasons why we've adquired SeeBeyond. To help customers clarify
the situation in the applications in their datacenters (and with the rest of the world too).
To integrate their applications easily. To reduce their TCO.
To make application development easier by using SOA, by easily orchestrating their
services in a coordinated way.
The best way to integrate different applications is, of course, by using an
Enterprise Service Bus, a major component of most SOA suites nowadays.
By using one of these integration becomes scalable.
"n" applications require just "n" connectors to the bus, and not "n times n" as before.
Easier. Linear scalability in place. Let's grow.
This ESB is responsible for routing the message between zero, one or more applications.
Either synchronously or asynchronously. And one application does not need to know
to which other applications is connected. That's the way to grow.
The "Swing Event Bus" (and its events)
And the same solution may apply to your Swing applications as they grow. You need
some sort of "Swing Event Bus" to integrate your macro-components. Your macro-components
send events to this Swing Event Bus and forget. They don't know who is responsible
for handling the event. There's not a one-to-one relationship between event sources
and event listeners. These are decoupled. You can now scale linearly, you can now
grow your application with another macro-component by attaching it to the event bus.
Of course the events transferred by such a "Swing Event Bus" are not "normal" events.
I mean, you don't want to transfer ActionEvents from the "File System Viewer" to the "Editor"
and the "Status Bar". "Normal" ActionEvents tell nothing to you. You don't mind what the
action command of the event is. You don't even mind what the source of the event is.
It may be an internal button of the "File System Viewer", a double click on a file or
a popup menu.
Through that "Swing Event Bus" you probably want to deliver custom events. Say a
"RequestFileOpenEvent", that contains (for instance) the name of the file.
Then the "Editor" and the "Status Bar" will receive that "RequestFileOpenEvent" from the
"Swing Event Bus" and react appropriately. The editor will probably try to open the file and
the status bar will probably show a "Opening file XXX" message.
You can use both, of course!
Of course the "Swing Event Bus" may be used for intra-macro-component event handling.
This is, you can use such a "Swing Event Bus" to communicate in-between the components
(buttons, popups, menus, lists, tables) of your macro-component (the "editor", say).
But that's probably not a good idea. It violates the KISS principle. There's no
great benefit of having a loose-coupling between a button and a menu item inside the editor, right?
After all the "Swing Event Bus" should be used just to attain loose-coupling between
major macro-components. Using it inside a macro-component makes no sense at all.
So, where is this Swing Event Bus?
Well, the idea of using event buses for Swing has been around for a long time.
The first that comes to my mind (and probably the older one) is the
good, old, easy-to-use, withdrawn, almost-forgotten InfoBus
specification (we even had some implementations at java.sun.com).
But there're may others out there. There is David
Walend's Somnifugi, a lightweight JMS implementation. And werx, for instance.
And I'm not the first one to talk on this either.
Berin Loritsch,
David Walend,
Ryan's Scraps,
Lair Nelson and
probably tons of others have talked on this before.
So, why talking on this now?
Well, you know I suffer badly from frameworkfobia, so I try to do things myself as much as I can.
That, and because I need working out my annotations in Java 5, is the reason why I'm
working on UITopics. (Yeah, still waiting for java.net approval :-().
Next posts
This looks interesting, doesn't it?
Now let me ask one question: should events transferred through the
Swing event bus contain any logic at all or not? What does the
SOA simile suggest?
Food for thought. Cheers, Antonio
|
Before we go down the road of creating a bus like system I think it is important to differentiate between the two basic types of events : CommandEvents and StateEvents (i.e. OpenFile and the resulting FileOpened). These two types of events indicate action (which may be vetoed) and reaction in a application and it is important to understand that the objects listening for CommandEvents will (most likely) not be the object listening for StateEvents. The objects that listen for CommandEvents would be the generators of state events. This is akin to having controllers (mediators) that handle the interactions of macro-components and their effect upon the state of the application via a system of categorized events. The events would be delivered to sinks which can be hooked into the bus, as a place to register for or deliver a specific type of event.
Here's an example:
SystemCommandEvent OPEN_SYSTEM, CLOSE_SYSTEM, SAVE_SYSTEM, REFRESH_SYSTEM, etc...
SystemStateEvent SYSTEM_OPENED, SYSTEM_CLOSED, SYSTEM_SAVED, etc...
ModeCommandEvent CHANGE_MODE, START_MODE, STOP_MODE, etc...
ModeStateEvent MODE_CHANGED, MODE_STARTED, MODE_STOPPED, etc..
CursorCommandEvent START_CURSOR, STOP_CURSOR, etc...
Each Command event has an associated State event. Each event type (Mode, System) has an associated sink or support object (i.e. - ModeSupport, SystemSupport) that handles the delivery and registry of Command and State events possibly via the bus. The support object can then determine whether it needs to deliver the event via the bus (i.e. a START_CURSOR event may be delivered via the EventQueue), and how it should be delivered (sync, async). This allows the macro-components of the application to communicate CommandEvents to each other and have macro or micro components listen to the resulting StateEvents, while allowing and orderly means or components to access events, and allowing each category (even each type) of events to determine how it will be dispatched via the sink.
This architecture is fairly simple to create and allows for greater flexibility when those unexpected requirements pop up. Let me know what you think...
Enviado por Tim Osten en septiembre 20, 2005 a las 10:11 PM CEST #
Thanks for your comment!! Sorry for my late reply but I can't blog as frequently as I would like to :-(
I was thinking that it could be a good idea having different bus lines. Say topics (JMS) or channels (werx). So we could have a command topic and a state topic, and route the command events through the first and the state events through the second. What do you think?
Regarding the support object I think it's a great idea. I think it's an application of the Mediator Pattern:
Don't you think?
I'll try to post later on these ideas to try to see how well they fit together. This is something like brainstorming.
I just hope to be up to the task of discussing all these issues with you all!
Cheers
Antonio
Enviado por Antonio en septiembre 21, 2005 a las 08:35 PM CEST #
Enviado por codecraig en septiembre 22, 2005 a las 02:30 PM CEST #
Enviado por Will en septiembre 23, 2005 a las 12:51 PM CEST #