Let's Swing!https://blogs.oracle.com/swinger/
A globally warmed, swing focused blog in the Participation Age.en-usCopyright 2006Mon, 12 Jun 2006 18:25:20 +0000Apache Roller BLOGS401ORA6 (20130904125427)https://blogs.oracle.com/swinger/entry/rss_one_stylesheet_to_ruleRSS: One stylesheet to rule them all?swingerhttps://blogs.oracle.com/swinger/entry/rss_one_stylesheet_to_rule
Mon, 19 Dec 2005 13:15:00 +0000Event bus<p><b>Bloglines and RSS parsing</b></p>
<p>
As you probably know <a href="http://blogs.sun.com/roller/page/swinger?entry=bloglines_is_cool">I've been exploring Bloglines services</a> to easily build just another RSS reader. The fact is that I have found no services to handle channels. This is, you cannot programmatically add/remove/update channels. Too bad. :-(
</p>
<p>
So, unless I'm completely wrong, we'll have to parse RSS ourselves.
</p>
<p><b>First approach: Rome</b></p>
<p>
The very first approach is, of course, <a href="http://rome.dev.java.net">Rome</a>, Sun's open source project for RSS parsing.
</p>
<p>
But, to be honest, Rome is too big for my liking, too powerful for my modest needs. It depends on JDOM (which, luckily, seems to depend on nothing else). Rome is very good to parse in detail all sort of RSS flavors. All I want it to have a least common denominator of different RSS flavors. RSS 0.91, RSS 0.92, RSS 1.0, RSS 2.0 and Atom 1.0 would be good enough, I think.
</p>
<p>
Furthermore, I'd like to do it myself so as to exercise Java XML APIs. After all I need to keep up with those things, it's some sort of hobby of mine ;-).
</p>
<p><b>SAX Parsing: the cost of speed</b></p>
<p>
So my very first approach was to go for speed, using SAX parsers. I've built a SAX handler that is chained with other different SAX
handlers for every different flavor of RSS.
</p>
<p>
And, to be honest, the thing works quite fast. SAX parsers consume little memory and run really fast.
</p>
<p>
But after all the experiment those SAX handlers looked to me quite similar to AWK scripts. This is: they're difficult to maintain. I don't think I'll be able to modify those RSS handlers myself within, say, one month from now.
</p>
<p><b>XSL to the rescue?</b></p>
<p>
So I thought, why not use an XSLT stylesheet to extract information from those different RSS flavors (RSS 0.91, 0.92, 1.0, 2.0, Atom 1.0) and <b>transform</b> those different flavors in a least common XML file? Then with a single SAX parser I'd be able to parse all sort of RSS flavor.
</p>
<p>
And, since all transformation is handled in a XML file (the XSLT stylesheet) it should be easier to maintain. Of course there's a cost for this ease of mainteinance: we're loosing speed.
</p>
<p>
I'm sort of tired now (it's difficult to write coherently, sorry by that), but I think a small diagram could explain things better. There we are:
</p>
<p>
<a href="http://blogs.sun.com/roller/resources/swinger/rss-xslt.png" title="click to enlarge"><img src="https://blogs.oracle.com/roller/resources/swinger/rss-xslt-small.png" alt="" /></a>
</p>
<p>
I've been doing some tests and, well, there's some lack of speed. But I think it's worth the effort. Simpler, smaller, easier to maintain, no dependencies... I like it.
</p>
<p>
What do you think? Any suggestions? Any way to improve the XSLT stylesheet? (By the way, the XSLT stylesheet can be found <a href="http://blogs.sun.com/roller/resources/swinger/rss.xsl" title="Click to get the XSLT stylesheet">here</a>).
</p>
<p>
Cheers,<br/>
Antonio
</p>https://blogs.oracle.com/swinger/entry/bloglines_is_coolBloglines is coolswingerhttps://blogs.oracle.com/swinger/entry/bloglines_is_cool
Thu, 17 Nov 2005 10:00:00 +0000Event busLive from <a href="http://www.turismo.sevilla.org">Sevilla</a>. Foggy this morning, but lots of sun in the afternoon!
<p>
Someone suggested buildling an RSS Feed Reader/aggregator as a sample Swing application, just to experiment with different ways to organize the model, the view and the controller.
<p>
And, since I don't really like any RSS feed readers around, I thought it could be a good idea.
<p>
The fact is that, as in <a href="http://blogs.sun.com/roller/page/jonathan?entry=the_future_of_office_productivity">Jonathan's case</a>, I need a high mobility RSS feed reader. I switch computers all the time, so I need to store my preferred RSS feeds somewhere in the Internet. I can't rely on a local hard disk, either.
<p>
So I happened to pass by <a href="http://www.bloglines.com">bloglines</a> and I noticed their excellent <a href="http://www.bloglines.com/services/">REST services</a>. Really cool. They keep all your RSS feeds for you, and cache them, and then allow you to retrieve them using a simple HTTP call.
<p>
And that's exactly what I need. They provide a simple RSS storage mechanism for me. For free. They keep all my RSS feeds there. And, more interestingly, they parse them for me. They worry about RSS 0.91, RSS 0.92, RSS 1.0, RSS 2.0, Atom 1.0 and whatever-the-version-is version and parse them for me. And they produce clean RSS 2.0 instead.
<p>
So I think that it may be a good idea to build a Swing rich client application that consumes bloglines <a href="http://en.wikipedia.org/wiki/REST">REST services</a>.
<p>
That rich client application could then be stored somewhere in the Internet. And, being downloaded using JNLP, I could then have a truly mobile RSS feed reader.
<p>
Cool.
<p>
Greetings from Sevilla,<br>
Antonio<p>https://blogs.oracle.com/swinger/entry/let_s_get_it_organizedLet's get it organizedswingerhttps://blogs.oracle.com/swinger/entry/let_s_get_it_organized
Fri, 11 Nov 2005 12:45:00 +0000Event bus<p>
What a week, dude. Lots of things to do. Little time for funny activities. And the coming
one is even worse, much more traveling (back to Sevilla again). I'll try to post some
photos of Sevilla and the "tapas" they have there.
<p>
The fact is that I've received different emails through my blogging alias. Apart of omnipresent
spam I've received a couple of mails asking about the event bus, and about the
organization of the model, the view and the controller in Swing applications.
<p>
<b>Let's get organized</b>
<p>
So I thought it could be a good, illustrative idea to show different ways to organize things
in Swing applications. Different ways to architecture the internals of a GUI application.
<p>
And, before going any further, I thought it could be a good idea to ask you all what you think
of this. Say I am to write an application using the Presentation Model paradigm, and then
rewrite it using the Model View Presenter approach. And then rewrite the first one using
an event bus, and do the same with the second one. Something like this:
<p>
<ul>
<li> Presentation Model, no event bus.
<li> Model View Presenter, no event bus.
<li> Presentation Model, event bus.
<li> Model View Presenter, no event bus.
</ul>
<p>
(Any other suggestion is, of course, welcome).
<p>
And then, after watching those four, see how things could be further improved. Or even write a comparison of them all. Some sort of guidelines for choosing which one better fits your needs.
<p>
So, my questions is, is it worth the effort? What do you think?
<p>
<b>Doing what?</b>
<p>
The application should be useful, of course. I suggest doing some sort of
easy to use bookmark manager. Since I use different computers I have different set of
bookmarks in different places. I'd like to store those in, say, Google's gmail (as a
plain jar file, say). Any other ideas about useful (little) applications are
welcome, too.
<p>
Thanks for any ideas and have a restful weekend (I will ;-)),<p>
Antoniohttps://blogs.oracle.com/swinger/entry/domain_models_value_models_swingDomain Models, Value Models, Swing Modelsswingerhttps://blogs.oracle.com/swinger/entry/domain_models_value_models_swing
Fri, 21 Oct 2005 10:30:09 +0000Event bus<p>
The fact is that blogging requires time. And if you're short of time then you don't blog well. You don't explain yourself. You don't get understood. And, since blogging is about explaining yourself, then you fail as a blogger.
<p>
That simple. That difficult.
<p>
And I think that's what has happened with my latest posts. Someone has warned me about it. Thanks for that. If it ever happens again, if I ever don't explain myself, then just ask. Please warn me about this. After all this is an interactive place. Don't be afraid to criticize or just complain! That's part of being interactive! ;-)
<p>
So I'm trying to connect the model to the bus. The idea is that whenever the model changes then events are generated and sent through topics in the bus to the view (that is responsible for painting them).
<p>
And this, although easy to explain in a few lines of blogging, is quite difficult to do in practice. Before rushing into the code I like doing some research. After all, that's the fun part of this! So please let me explain what I'm looking at, let me share that with you, just in case you want to add any idea!
<p>
<b>Models: domain models, value models, Swing models</b>
<p>
So, how many kinds of models are there? What do we mean by model? What's the "model" in the "Model-View-Controller" paradigm? What is a domain model? What a value model? How do Swing models (DocumentModel, ButtonModel and ListModel) relate to those? Why is <a href="http://www.vogue.es/moda/rad7174f.shtml">Laura Ponte</a> such a great model? (Oh, well, just because she's galician too? :-D )
<p>
Most of these questions are answered at the <a href="http://www.jgoodies.com/articles/binding.pdf">Swing Data Binding Framework</a> by <a href="http://www.jgoodies.com">Karsten Lentzsch</a> (well, Karsten doesn't talk about Laura Ponte, sadly ;-) ).
<p>
To be honest, Karsten's binding framework is the most interesting framework I've seen around for handling the model in a Swing application. Well, in fact is the <b>only</b> framework I know of for handling the model. Or do you know of any other out there?
<p>
Let me explain what I understand of it (and what I don't) and why this binding framework (that has been around for some time) is so interesting to me.
<p>
<b>Domain models</b>
<p>
(Many different definitions here, I'll try to explain my preferred one. I know there're different versions and definitions, but the following one is good enough for the purpose of this blog. I wouldn't like to discuss on this ;-) ).
<p>
Domain (object) models represent a conceptual vision of a system. The types of objects your software will be dealing with. The objects you design to deal with a business problem. Class diagrams or entity-relationship (ER) database diagrams are usually good enough to visualize domain models.
<p>
Of course, you want your domain models to be independent of the user interface. Domain models usually live in the business tier, whereas the views live in the presentation tier. And even when your application is not multi-tiered, you still want to separate them. To reuse your domain in another applications (or to exploit your domain model from different user-interfaces, such as a command line and a GUI).
<p>
For an example of a domain model you can see <a href="http://www.theserverside.com/articles/content/JDODomainModel/Figure1.gif" target="top">this image</a> taken from <a href="http://www.theserverside.com/articles/article.tss?l=JDODomainModel">this article at The Server Side</a>.
<p>
As Karsten's explains in his article, Domain models can be built with plain Java Beans (Plain Old Java Objects or POJOS). I have to agree. Java Beans is the easiest way to do it. Having a Domain Model designed as a set of POJOs is simple, is serializable (can be persisted to the disk or to an object oriented database) and, if you use bound properties, you can have Observers listen for changes on the domain model. (And that's exactly what I want to do with an event bus, for instance).
<p>
But as Karsten's nicely explains in his article, it's probably not a good idea to make your view depend directly on your domain model. (That's what he calls "Direct Adapters", the reasons why this is not a good idea are explained in slide # 43 in his article).
<p>
A similar thing happens in J2EE applications. Usually in J2EE applications you make your domain object model persistent using Entity Beans, DAOs, JDO, Hibernate or a mix of those. The "conceptual vision of the system", the domain model, can then be persisted in a database. But when building J2EE applications you don't really want to make your view depend directly on your domain model. You prefer to use the <a href="http://java.sun.com/blueprints/corej2eepatterns/Patterns/TransferObject.html">Transfer Object Core J2EE Pattern</a> in your servlets and JSPs. (If you're not familiar to Transfer Objects you can think of these as a small photograph of a part of your model). You also want to use View Helpers, and different other J2EE patterns in your view.
<p>
<b>Value Models</b>
<p>
So how to avoid the problem of making your view directly depend on your domain model?
<p>
Well, of course, by using an indirection. Make your view depend on something, say Value Model, and then make that (the Value Model) depend on your domain model. You've got the indirection. There's no (direct) dependency. Problem solved. This Value Model is explained in slide #44 of Karsten's article.
<p>
And that's the way a (nice) J2EE application works too. Make your views depend on your transfer objects, and make these be a (partial) copy of your domain model. Make your views depend on business delegates, but not on all the internals of your business tier.
<p>
Introducing indirections between two parts of your software makes dependencies between these controllable. Allows you to build a single point of contact, a logical frontier between tiers. Keeping the indirection under control means keeping the dependency under control.
<p>
If this indirection layer is correctly built then things are easier to maintain. What is interesting about Karsten's binding system is that this indirection layer seems to be correctly built. He uses a "universal model" (ValueModel) to separate the view from the domain model (see slice #47 for details on the ValueModel). So the <b>view has to deal with a single type of objects: ValueModels</b>. And not with the specifics of the domain model you're building. Views become reusable. Views become isolated from the domain model. And this simple concept makes things easier when building Swing applications: the domain model is focused in the business problem and the view is focused in correctly handling ValueModels, whatever they contain.
<p>
<b>From domain to value models (to SwingModels)</b>
<p>
So how to transform domain models to value models while keeping them in sync? As Karsten's suggests: by using BeanAdapters and PropertyAdapters (slide #52). These "adapters" listen the domain model for PropertyChanges. Whenever a property changes in the domain model the change is automagically transformed into a change in the ValueModel, and viceversa. Easy to do. Reflection as needed. The powerful java.beans.\* package into action.
<p>
There're several issues with this approach, namely avoiding syncing before the user presses an "OK" button, or handling lists and table models. Karsten keeps on explaining these issues in the following slides. Check his article for further details on these.
<p>
Karsten explains as well how to make different SwingModels use ValueModels. There're adapters for these. Again check his article for further details.
<p>
<b>From domain to value models: by bus??</b>
<p>
So why talking about all these models here? How do they relate to an event bus?
<p>
Well, if you go take a look at Karsten's article, at slide #54, you'll see something like this:
<p>
<pre><code>
private void initComponents() {
Album album = getEditedAlbum(); // 1
ValueModel aValueModel =
new PropertyAdapter( album, "classical" ); // 2
JCheckBox classicalBox = new JCheckBox();
classicalBox.setModel(
new ToggleButtonAdapter( aValueModel ) ); // 3
</code></pre>
<p>
So what this basically says is that in order to initialize the views of your components
you have to get a reference to the domain model ((1) Album here) and then build a ValueModel
from it (2) and then build your GUI with the ValueModel (3).
<p>
Note that your GUI components (classicalBox) need only a reference to the ValueModel,
and may be completely isolated from the domain model. What I mean is that you don't need your
domain model to compile your GUI. You could refactor the code above and remove completely
the "Album" class by hiding it in another class. By using some sort of ValueModel factory or something.
<p>
What I really mean is that you could do something like this:
<p>
<center>
<a href="http://blogs.sun.com/roller/resources/swinger/MVC-DomainModel-ValueModel.png"><img src="https://blogs.oracle.com/roller/resources/swinger/MVC-DomainModel-ValueModel-small.png" border="0"></a>
</center>
<p>
This is, make your domain model notify changes using the bus. Let me try to be more specific: instead
of writing
<pre>
<code>
ValueModel aValueModel = new PropertyAdapter( album, "classical" );
</code>
</pre>
(which means: create a new ValueModel that is notified whenever the property "classical" in "album" changes)
use the bus to rewrite the view as:
<pre>
<code>
// Create a new value model
ValueModel aValueModel = new ValueModel();
// That is notified of PropertyChangeEvents whenever
// an event is received through the "album.classical" topic
bus.addEventListener( aValueModel, "album.classical" );
</code>
</pre>
and rewrite the domain model as:
<code>
<pre>
// Get a reference to an Album in your domain model
Album album = ...
// Make the "album" bean send PropertyChange events when
// properties change.
// When the "setClassical()" method is invoked on the Album bean
// then a PropertyChangeEvent will be sent through the
// "album.classical" topic in the bus
bus.addEventSource( album, "album" );
</code>
</pre>
<p>
So you completely isolate your view from your domain model. You can make them
change independently. You don't need domain models to compile your GUI
(just ValueModels).
<p>
<b>So that's what I'm investigating now</b>
<p>
So that's why I've been writing about Java Beans and PropertyChangeEvents
and PropertyChangeSupport lately. I am trying to build a suitable domain model
using just plain JavaBeans. Plain POJOs.
<p>
And I will like to reuse Karsten's binding library to attach things to the
bus. After all I think Karsten's binding library is the most comprehensive
mechanism to tackle the model in Swing. Or is it not? Do you know of any other
framework/library to do it? What do you think of this? Do you think it appropriate
or just too complex?
<p>
Am I following the KISS principle? Or do you think this is too elaborate just to use models?
(This is, shall I continue this or not?).
<p>
As always all feedback is greatly appreciated.
<p>
Have a good weekend,<br>
Antonio<br>https://blogs.oracle.com/swinger/entry/apt_modelsApt modelsswingerhttps://blogs.oracle.com/swinger/entry/apt_models
Mon, 17 Oct 2005 09:40:39 +0000Event busExtremely busy weeks behind (and probably ahead too) so I've been unable to post anything interesting for a while. Sorry by that.
<p>
I am currently thinking on how to better build the models for Swing applications.
<p>
And, of course, I'm thinking of annotations ;-)
<p>
<b>JavaBeans for me, please</b>
<p>
I would like to build models using JavaBeans (Plain Old Java Objects, or POJOs, say). I would like each property of my JavaBeans to automatically generate PropertyChangeEvents for me.
<p>
Of course that's not very difficult to do. I could use java.beans.PropertyChangeSupport to do that.
<p>
Let's see an example. Let's say I want to model a Person with two properties: full name and email. I could build a JavaBean like this:
<p>
<pre><code>
package com.sun.antonio.models;
import java.beans.\*;
public class Person
implements java.io.Serializable
{
private String fullName;
private String emailAddress;
private PropertyChangeSupport pcs;
public Person() { pcs = new PropertyChangeSupport(this); }
public String getFullName() { return fullName; }
public void setFullName( String aFullName )
{
String oldName = fullName;
fullName = aFullName;
pcs.firePropertyChange( "fullName", oldName, fullName );
}
public void addPropertyChangeListener( PropertyChangeListener pcl )
{
pcs.addPropertyChangeListener( pcl );
}
// removePropertyChangeListener and get/set EmailAddress below removed
}
</code></pre>
<p>
The code above is simple to write. I could use a java.beans.VetoableChangeSupport too, to add support for
vetoable changes. (If you need more information on JavaBeans or bound properties or constrained properties <a href="http://java.sun.com/developer/onlineTraining/Beans/beans02/page3.html">you may want to read more on the topic</a>).
<p>
But although simple to write (and to read) it requires too many lines of code. I'm too lazy to do that donkeywork. I'd prefer using a shorter, more compact notation for defining my JavaBeans.
<p>
And, although I don't really like code generation stuff, I thought of using a code generation mechanism to generate my JavaBeans.
<p>
<b>The incredible autogenerated JavaBean</b>
<p>
The very first approach could be, of course, <a href="http://xdoclet.sourceforge.net/xdoclet/tags/java-tags.html">XDoclet JavaBean tags</a>.
<p>
So I thought of downloading and setting up XDoclet on my wonderful NetBeans 5.0 Beta. But then I thought that it could be a good idea to use something similar to JAXB 2...
<p>
<b>The incredible XML mapping</b>
<p>
I happened to <a href="http://weblogs.java.net/blog/kohsuke/">pass by Kohsuke Kawaguchi's Blog</a> where I could read:
<p>
<pre><code>
@XmlRootElement
class Point {
@XmlElement
public int x;
@XmlElement
public int y;
Point(...) { ... }
}
</code></pre>
Hey! He was defining the XML mapping of a Java object in Java using annotations. This is cool!.
<p>
I wanted to do that, too. What about writing something like this?
<p>
<pre><code>
@JavaBean
class Person
{
@Property( type=BOUND ) private String fullName;
@Property( type=CONSTRAINED ) private String emailAddress;
}
</code></pre>
<p>
This is, I could define a JavaBean annotation and a Property annotation so that classes and attributes marked with these could be used to generate the code I had to write by hand at the top of this entry. Those annotations could automagically create PropertyChangeSupport and VetoableChangeSupport for me, and fire appropriate PropertyChangeEvents when required (on the setter methods).
<p>
The idea seems to be interesting. What about this?
<p>
<pre><code>
@JavaBean
@XmlRootElement
class Person
{
@XmlElement @Property( type=BOUND ) private String fullName;
@XmlElement @Property( type=CONSTRAINED ) private String emailAddress;
}
</code></pre>
<p>
This is, if I use annotations for JavaBeans I can mix these with JAXB2 annotations, so that all my model can be persisted to XML too.
<p>
But using annotations for JavaBeans seems to be nothing new.
See, for instance, <a href="http://www.damnhandy.com/?page_id=17">damnhandy's blog</a> on ideas on how to do this.
<p>
<b>Apt models</b>
<p>
One of the nice things about annotations is that you can generate both source code and class files from them
using <a href="http://java.sun.com/j2se/1.5.0/docs/guide/apt/GettingStarted.html">the apt tool</a>. I'm experimenting
with it right now. Maybe I'll post some examples here.
<p>
<b>And, well, NetBeans, of course...</b>
<p>
Since building an APT based tool to generate JavaBeans seems a little bit too elaborated to me, I
thought of building a NetBeans plugin.
<p>
And, well, the fact is that... none is needed!!! NetBeans has already a built-in command to do it. It generates
PropertyChangeSupport for me (or even VetoableChangeSupport). And takes all the hassle of hand-writing
property change listeners and firing property change events.
<p>
Since this is a little bit hidden feature, I think it's better to show the process with some screenshots.
<p>
First of all I create a plain Java class as usual (File/New/Java Class). And call it, say, Person.
<p>
Then I open the class in the Project Window until I can see the "Bean Patterns" node. Like this:
<p>
<center><img src="https://blogs.oracle.com/roller/resources/swinger/nb-propertiesmenu.png" border="0"></center>
<p>
Then a dialog appears. In this dialog you can choose what type of property you want to create
(plain, bound, constrained). The nice feature is that NetBeans automagically creates a PropertyChangeSupport for
you.
<center><img src="https://blogs.oracle.com/roller/resources/swinger/nb-newproperty.png" border="0"></center>
<p>
The generated code looks like this:
<pre><code>
/\*\*
\* Utility field used by bound properties.
\*/
private java.beans.PropertyChangeSupport propertyChangeSupport = new java.beans.PropertyChangeSupport(this);
/\*\*
\* Adds a PropertyChangeListener to the listener list.
\* @param l The listener to add.
\*/
public void addPropertyChangeListener(java.beans.PropertyChangeListener l)
{
propertyChangeSupport.addPropertyChangeListener(l);
}
/\*\*
\* Removes a PropertyChangeListener from the listener list.
\* @param l The listener to remove.
\*/
public void removePropertyChangeListener(java.beans.PropertyChangeListener l)
{
propertyChangeSupport.removePropertyChangeListener(l);
}
/\*\*
\* Getter for property fullName.
\* @return Value of property fullName.
\*/
public String getFullName()
{
return this.fullName;
}
/\*\*
\* Setter for property fullName.
\* @param fullName New value of property fullName.
\*/
public void setFullName(String fullName)
{
String oldFullName = this.fullName;
this.fullName = fullName;
propertyChangeSupport.firePropertyChange("fullName", oldFullName, fullName);
}
</code></pre>
Which is good enough for me, just with a few clicks.
<p>
<b>Conclusion</b>
<p>
So, although generating JavaBeans with apt (or xdoclet) may be a cool feature, I think I'll stick
with NetBeans at the moment. The generated code is excellent and, well, the feature is already
integrated in my favourite IDE.
<p>
Anyway maybe I'll come back to annotations in the future to generate code... What about
a @TableModel annotation that automagically generates a TableModel for you? What about a
@ListModel one? And, of course, are you using annotations for your model? Would you like to?
What do you think of using the APT tool to generate source code for your Swing applications?
(Any ideas/rants/complaints are, of course, welcome).
<p>
(Note to NetBeans team: you've earned a free beer whenever you happen to visit Madrid).
<p>
Happy modelling,<br>
Antonio<br>
<p>
<b>UPDATE:</b>
<p>
It seems Core Java II vol. II (Chapter 13) has some examples of APT Annotation Processors to build BeanInfo (I don't own Core Java II yet, I think I should go buy it, right?)
<a href="http://www.goshen.edu/~dhousman/cosc315/corejava2/v2/v2ch13/Property/">Sample code here</a>.
<p>https://blogs.oracle.com/swinger/entry/annotations_dynamic_proxies_and_talkingAnnotations, dynamic proxies and talking modelsswingerhttps://blogs.oracle.com/swinger/entry/annotations_dynamic_proxies_and_talking
Tue, 11 Oct 2005 08:25:51 +0000Event bus<p>
Since it's a long time since my last (interesting) post I thought I could give you all a little update on the
current status of affairs. What I've been reading and how things are going.
<p>
I'm receiving comments and email from many of you. Let me comment on (some of) these. And let me talk again about the
bus driver.
<p>
<b>Annotations, what for?</b>
<p>
Ingo (who is currently writing his master thesis, good luck, Ingo!) has asked me why and where
do I want to use Annotations for the event bus.
<p>
Well, to be honest annotations are not really needed at all. You can use plain old listeners for
event handling.
<p>
But although not neccessary they may be useful. Let me briefly explain why I think they may be of interest.
<p>
Handling events in Swing is easy but, from my point of view, requires lots of code. You have to create a listener,
whether anonymous or not, and then make the listener do what you want. And then remove it in case of need.
That requires several lines of code. We can make things easier (note that writing less code is not always a good idea if you write less legible code. But discussing that will require another entry ;-) ).
<p>
<b>Easier event handling I: dynamic proxies</b>
<p>
One way to make things easier is by using Dynamic Proxies. These "Dynamic Proxies" are a way to build
classes dynamically (i.e., while the application is running) that implement some interface you want.
Say you have an ActionListener interface. You can dinamically build an object (a dynamic proxy) that
intercepts all calls to methods in the ActionListener interface. So when someone calls the method
"actionPerformed( ActionEvent ae )" the dynamic proxy will intercept that call. Then you can do
whatever you want there. Say send the ActionEvent to a bus of events, for instance.
<p>
The small UITopics implementation we talked about earlier just does this. It dynamically builds listeners
for those interfaces you want and redirects all events there to a topic in the bus. So the call:
<pre>
<code>
JButton myButton = ...;
TopicManager tm = ...;
tm.addEventSource( myButton, "mybutton.events", ActionListener.class, MouseListener.class );
</code>
</pre>
(If you're new to UITopics just think that TopicManager is a weird, unappropiate name of the Event Bus).
<p>
That code builds two proxies, one that intercepts calls to all methods of ActionListener and another
one that intercepts calls to all methods of MouseListener.class. And then redirects all events
to the "mybutton.events" topic in the TopicManager.
<p>
To clarify. The code above is rougly equivalent to this:
<p>
<pre>
<code>
JButton myButton = ...;
TopicManager tm = ...;
myButton.addActionListener( new ActionListener()
{
public void actionPerformed( ActionEvent ae )
{
tm.sendEvent( myButton, "mybutton.events", ae );
}
} );
myButton.addMouseListener( new MouseListener()
{
public void mousePressed( MouseEvent me )
{
tm.sendEvent( myButton, "mybutton.events", me );
}
... // idem mouseReleased, etc.
public void mouseClicked( MouseEvent me )
{
tm.sendEvent( myButton, "mybutton.events", me );
}
} ();
</code>
</pre>
<p>
Note that the three lines above using dynamic proxies are equivalent much more lines using
normal listeners.
<p>
Using dynamic proxies for event handling is a very old technique. More info
can be found at <a href="http://java.sun.com/products/jfc/tsc/articles/generic-listener2/">java.sun.com</a>
and <a href="http://www.javaworld.com/javaworld/jw-11-1999/jw-11-events.html">www.javaworld.com (1999)</a>.
<p>
<b>Easier event handling II: annotations</b>
<p>
The second way to make things easier in event handling is by using annotations. Since dynamic proxies
are built dinamically for building listeners, why not take advantage of annotations to dinamically (too) define how
listeners expect events to be received?
<p>
UITopics uses annotations to define how listeners want to receive events. From which topic, and on which thread.
That makes things easier to code.
<pre><code>
@TopicListener( topicName="mybutton.events", isAsynchronous="true" )
public void myMethod( TopicManager tm, ActionEvent ae )
{
... // asynchronously handle ActionEvent
}
</pre></code>
<p>
Note that by using dynamic things you (may?) loose strong typing. Applications may fail at runtime if these are
not correctly tested. By using dynamic things you make things easier to develop at the expense of static
(compile-time) safety (<b>you've been warned ;-)</b>).
<p>
There's an interesting article on using annotations for event handling <a href="http://www.javaworld.com/javaworld/jw-10-2005/jw-1003-mvc_p.html">at JavaWorld</a>. Note that the article is dated October 2005. As you can see things are moving in this field. The article contains interesting ways to annotate listeners. (Interesting ideas for the bus, too).
<p>
<b>Event driver revisited: is it MVC or MVP or PM or what?</b>
<p>
In my last post I suggested we could use the model to send events to the views through the bus.
I am still digesting <a href="http://www.jgoodies.com/articles/patterns-and-binding.pdf">one of the latest (Aug. 2005, PDF, English)</a> of <a href="http://www.jgoodies.com/articles/">Karsten Lentzsch's articles</a> entitled "Desktop Patterns and Data Binding for Swing". You may know Karsten because of all <a href="http://www.jgoodies.com">JGoodies</a> goodies (including the Looks Look and Feel, his Binding and Validation and tons of other good stuff).
<p>
Karsten is one of my gurus. Reading his articles is always interesting. That one of Aug. 2005 is also interesting. He shows the differences between MVC, Swing MVC, Model View Presenter (MVP) and the Presentation Model.
<p>
I like Model View Presenter. I like hearing that "MVP holds the GUI state <em>once</em>", whereas "PM holds it <em>twice</em>".
<p>
For further reading you can <a href="http://www.object-arts.com/OldStuff/Patterns/MVP.htm">see a nice description of MVP</a> or even see <a href="http://www.object-arts.com/educationcentre/Tutorials/CreatingAnApplication.htm">how to build an application using MVP</a>. Note that
<p>
<blockquote>
It is much cleaner to design and build the core of the system, the domain model, first and then to add the user interface classes subsequently.
</blockquote>
<p>
I agree. I think we all do. The model should be the bus driver.
<p>
<b>Listen: the model is talking</b>
<p>
So, if the model is so important, how should the bus listen to it? If the model is changed, how is it supposed to
notify the bus? Which topics/channels/interrupt levels should be updated? How should we name them?
What is the <b>easiest way</b> to do this?
<p>
Most Swing models talk themselves:
<ul>
<li>javax.swing.Document talks javax.swing.event.DocumentEvents to javax.swing.event.DocumentListeners.
<li>And javax.swing.tree.TreeModels talk javax.swing.event.TreeModelEvents to javax.swing.event.TreeModelListeners.
<li>(include the Swing model you want here)
</ul>
<p>
So one way to plug-in these events to the bus is using Dynamic Proxies as well. Dynamically building event listeners
that automagically redirect the events to the bus. The first approach could be:
<p>
<pre>
<code>
TopicManager tm = ...;
javax.swing.Document document = ...;
tm.addEventSource( document, "document.events", DocumentListener.class );
</code>
</pre>
As we did above with components. The code above will make the model redirect all DocumentEvent's from the
given document to the "document.events" topic. Make your Swing components listen to these topics (using the
actuators we talked about earlier) and you're done.
<p>
But, is there any <b>easiest</b> way to connect the model to the bus? A different way? Simpler? More effective? ...
<p>
<b>Talking beans?</b>
<p>
... I think there is, but I'm not sure if this is a good idea or not. Let me explain it to you and please provide
feedback on it.
<p>
Imagine you build your model with Java Beans (i.e., POJOs; also known as Value Objects or Transfer Objects).
You may use a PropertyChangeSupport to
fire property change events whenever you "set" any property in your bean.
<p>
Using PropertyChangeSupport and firing property changes is way more easy, from my point of view, that
building custom events (DocumentEvent, TreeEvent, ListSelectionEvent, etc.) and listeners and the methods
used to work with those (fireDocumentEvent, etc.).
<p>
Now, wouldn't it be interesting to attach those Java beans to the bus? What about adding PropertyChangeListeners
to the bus <em>and using the property names as a suffix for topic names</em>? We could use the property names
as part of the topic name.
<p>
Take for instance you have a "Person" JavaBean that models your user data. Say that the "Person" JavaBean
has two properties: name and lastName. The idea is to attach "Person" to the bus on topic "user" and have
the "setName()" and "setLastName()" automagically send PropertyChangeEvents through the
"user.name" and "user.lastName" topics.
<p>
<b>Summary and next steps</b>
<p>
So in this post I've explained a way to attach objects to the bus. Event sources (such as Swing components, macro-components or the model) can be attached to the bus using dynamic proxies. Event listeners can be attached to the bus by using annotations. More work is needed to find a set of
interesting annotations. As Tim suggested in previous comments, we could explore SYNC, ASYNC, SYNC_SWING, ASYNC_SWING for threading.
<p>
In the coming weeks (I'm too busy right now with different customers) I'll try to experiment how well the model is being attached to the bus (using those PropertyChangeSupport objects). Always trying to make things simple.
<p>
After that, once the model can be easily plugged into the event bus,
I think we could experiment on threading and vetoing.
<p>
Any ideas, critics and suggestions are, of course, welcome.
<p>
Happy swinging,<br>
Antonio<br>https://blogs.oracle.com/swinger/entry/about_the_bus_driverAbout the bus driverswingerhttps://blogs.oracle.com/swinger/entry/about_the_bus_driver
Mon, 3 Oct 2005 12:10:32 +0000Event bus<p>
<b>Spot the difference!</b>
<p>
What's the difference between these two figures?
<p>
<table border="0" width="100%">
<tr><td><a href="http://blogs.sun.com/roller/resources/swinger/MVC.png" target="top"><img src="https://blogs.oracle.com/roller/resources/swinger/MVC-small.png" border="0"></a></td></tr>
<tr><td><a href="http://blogs.sun.com/roller/resources/swinger/MVC-2.png" target="top"><img src="https://blogs.oracle.com/roller/resources/swinger/MVC-small-2.png" border="0"></a></td></tr>
</table>
<p>
Which one do you think is the correct one? Which one do you prefer?
<p>
Well, if we try to follow the <a href="http://en.wikipedia.org/wiki/Model_view_controller">Model-View-Controller</a> paradigm,
then:
<p>
<blockquote>
<b>Controller: </b>This responds to events, typically user actions, and invokes changes on the model (but \*not\* the view).
<div align="right"><a href="http://en.wikipedia.org/wiki/Model_view_controller#Operation">(read more)</a></div>
</blockquote>
<p>
So it seems that the second one is the correct one. It's the model that notifies
the view about any change, and not the controller handling the view directly. (Of course
that's the way things are done in Swing, so that approach is possibly more intuitive than
the previous one, right?).
<p>
So I propose
being the model that pushes events into the bus whenever it is changed. The model
should drive the bus. Actuators will
then receive these changes and update the views accordingly.
<p>
The flow of events would then be as follows:
<ul>
<li><b>1. </b> Macro-components generate events, that travel the event bus using topics.
<li><b>2. </b> Controllers receive and coordinate these events, and modify the model accordingly.
<li><b>3. </b> The model fires events when changed, and these travel through the bus using
(one or more?) topics.
<li><b>4. </b> The actuators are updated of changes and update the view accordingly.
</ul>
<p>
Opinions on this? What do you think?
<p>
Since I'm afraid this is getting too academic let's see things by example.
<p>
<b>Opening files</b>
<p>
Let's assume the user wants to open a file.
<ul>
<li><b>1.</b>
The user
selects "File/Open" in the menu (or in a toolbar) and an ActionEvent is generated from the
menubar (toolbar) through the "menubar.events" or "toolbar.events" topics in the bus.
<li><b>2.</b> A controller is connected to both the "menubar.events" and "toolbar.events" topics and
asynchronously reads the file and creates a javax.swing.text.Document for the file.
<li><b>3.</b> The controller updates the model inserting this javax.swing.text.Document in the model (possibly in
the Swing thread). Once the model is updated it generates a DocumentOpenedEvent event through the
"model.documents" topic in the bus.
<li><b>4.</b> There're different actuators listening on this "model.documents". The "MenubarActuator" will
insert an entry in the "Recently opened" menu. The "EditorActuator" will open a new
editor tab and include the new javax.swing.text.Document in an EditorPane. The "StatusBarActuator"
will update the message in the status bar indicating that the file was opened.
</ul>
<p>
Note: if there's an IOException in step 2 above then steps 3 and 4 are not executed, but instead:
<ul>
<li><b>3.</b> The controller updates the model inserting an Exception in the model's "errors" list.
Once the model is updated the model itself generates a "ApplicationErrorEvent" through the
"application.errors" topic in the bus.
<li><b>4.</b> There're different actuators listening on this "application.errors" topic. The StatusBarActuator,
for instance, will show a red label with the error.
</ul>
Note there's no veto here: the controller detects the error and generates an event.
<p>
<b>Another example: closing the application</b>
<p>
<ul>
<li><b>1.</b> The user selects "File/Exit" in the menu (or clicks on the close window button in the window) and
an ActionEvent is generated from the menubar (or a WindowEvent is generated). These events
travel through the "menubar.events" or the "window.events" topics in the bus.
<li><b>2.</b> A controller is connected to both the "menubar.events" and "window.events" topics in the bus.
<li>The controller checks the model to see if all files are closed. If not then it will ask the user (in the event thread) if he wants to quit without closing. If the user selects "YES" then the controller updates the model indicating that the application has to be closed. If the user selects "NO" then the controller does nothing.
<li><b>3.</b> If the application has to be closed then the model fires an "ApplicationQuit" event through the "application.control" topic.
<li><b>4.</b> The "ApplicationActuator" releases all resources used by the views, closes and disposes all windows.
</ul>
Just one more example before continuing...
<p>
<b>Another example: saving</b>
<p>
Let's assume the user wants to save a file.
<p>
<ul>
<li><b>1.</b> The user selects "File/Save" in the menu (or clicks the save button in the toolbar).
An ActionEvent is generated from the menubar (or an ActionEvent is generated in the toolbar).
These events travel through the "menubar.events" or the "toolbar.events" topics in the bus.
li><b>2.</b> A controller is connected to both the "menubar.events" and "toolbar.events"
topics in the bus.
<li>The controller asynchronously saves the document (contained in a javax.swing.text.Document in
the model). And then updates the model indicating that the document is saved.
<li><b>3.</b> When the document in the model is saved an "DocumentSavedEvent" is sent through the "model.documents" topic.
<li><b>4.</b> There're different actuators listening on this "model.documents" topic. The "MenubarActuator" will disable the save menu (because the document is saved). The "StatusBarActuator"
will set a message indicating that the document was saved.
</ul>
What about errors? If there's an error saving the document in step 2 then the model
won't be updated and steps 3 and 4 above will not be executed. The behaviour could be
similar to the one when opening the file above.
<p>
<b>Vetoing and threading</b>
<p>
Note that in the examples above there's no need to veto events: it's controllers who are
responsible for handling errors and unsaved situations, so all the hassle about handling
vetoing in different threads just dissappears. Again, I can't think of a situation where
vetoing is strictly needed (any ideas here would be appreciated).
<p>
I think we need more brainstorming for the threading issues. Let's say we accept
the model as the bus driver. The one that rules actuators. Then that's probably a
good hint on how threading should work. The model should be modified by a single
thread, I suggest. So probably the easiest thing to do is to use the EDT as the
one responsible for modifying the model. So all events to actuators should be
genereated in the EDT. That's probably the easiest thing to do, right?
<p>
<b>State machines</b>
<p>
I keep on thinking of state machines in the background. Sorry I can't resist!
Interesting things I've found about state machines for GUIs and that need further
investigation:
<p>
<ul>
<li> <a href="http://www.wisdom.weizmann.ac.il/~dharel/papers.html">David Harel</a> (by the way: this guy has interesting papers on Graph Drawing algorithms using spectral methods; quite interesting if you're working in Graph Drawing arena) has interesting publications (and patents) on using <a href="http://www.wisdom.weizmann.ac.il/~dharel/SCANNED.PAPERS/Statecharts.pdf">Statecharts: A Visual Formalism for Complex Systems</a>.
<li> <a href="http://blogs.sun.com/roller/page/geertjan#how_wizards_work_part_3">NetBeans Wizards</a> use a state machine in the background. Each step contains a macro-component (the panel contents) and knows nothing about the rest. All navigation (Back/Next/Finish/Cancel) is stored in a WizardDescriptor.
<li> <a href="http://www.amazon.com/gp/product/customer-reviews/0201342782/ref=cm_cr_dp_pt/103-1067784-4283826?%5Fencoding=UTF8&n=283155&s=books">Constructing the User Interface with Statecharts</a> seems to be a good reading for me... ;-)
<li> <a href="http://www.flashsim.com/flash_simulation_book.html">Designing simulators in Flash using statecharts</a>
with <a href="http://www.flashsim.com/flash_gallery.html">interactive demos</a>. This is interesting. See the wrist watch, for instance. How difficult would be to implement one of those using normal listeners?
<li><a href="http://www.uidesign.net/1999/imho/nov_imho.html">Statechart Diagrams Problematic!</a> at uidesign.net
<li><a href="http://www.uidesign.net/Articles/Papers/ForUse2003LeanInteraction.html">ForUse 2003 : Lean Interaction Design and Implementation</a> talks about MVC-II, Mediator Pattern and StateCharts!
<li> Well, there're many more examples out there. Maybe UI design for mobile phones use statecharts too?
</ul>
<p>
I think the next step could be to modify the demo application to make the model drive the bus. Don't you think?<p>
Thanks for any suggestions,<br>
Antonio<br>
<p>https://blogs.oracle.com/swinger/entry/free_bus_tickets_for_everybodyFree bus tickets for everybodyswingerhttps://blogs.oracle.com/swinger/entry/free_bus_tickets_for_everybody
Wed, 28 Sep 2005 13:42:09 +0000Event bus<p>
First of all I'd like to thank everybody for taking the bus.
It's all of you that are making this a fascinating trip!.
<p>
After that I'd like to say that <b>everybody</b> has a free ticket for this bus. SWT, GTK, QT, wxWindows and even
MFC and .NET developers have a free ticket for this bus. This for free for everybody.
Although we're focused in a Swing implementation; you can probably apply it to your favourite
GUI toolkit, whether GTK or SWT or whatever.
<p>
Finally if you have trouble with written english then <em>puedes hablar español (yo haría
la traducción al inglés si tengo tiempo)</em>, <em>podes falar galego se queres</em>, <em>ou podes
tentar falar portugués (eu tentarei façer uma traducç&atilde;o)</em> (I'm not very good writting portuguese, though).
<p>
<b>Vetoing and threading</b>
<p>
As Nascif clearly explained, the problem with vetoing is that the caller thread blocks waiting
for feedback on the event. If the caller thread is the Swing thread (as it is in the current
implementation of many buses out there) then the Swing thread blocks. And that's a problem:
the whole GUI will freeze. One solution that comes to my mind is making the whole event
dispatching through the bus in a dedicated thread (Tim has suggested this too, I think).
Nascif has also re-introduced the idea of state machines.
<p>
As Tim has nicely expressed vetoing is useful for easily handling error conditions. You send the event
to the macro-components and you're able to see if the thing worked or not. Take for instance: you
send a save action and wait to see if the data was actually saved (or if, on the contrary, an IOException
was generated and the data could not be saved). In order to alleviate the thread-wait problem
Tim has also suggested sending feedback on success by using an state topic.
<p>
(Well, I don't know if I'm giving credit to everybody correctly, but you can check yourself
in the comments section for the previous post).
<p>
What I think is a problem with event vetoing is delivering the <b>same event</b> through
different actuators/mediators <b>in different threads</b>. In the actual implementation of UITopics
you may send an event to topic listeners in different threads (either in the Swing thread or
on a worker thread). In the curent implementation it's the topic listeners who are responsible for
deciding if they want to receive the event in the Swing thread or in a worker thread. Now, invoking different topic listeners in different threads and waiting for an exception to be thrown (or any other mechanism of vetoing) may be somewhat hard to do.
<p>
Anyway I'd like to introduce GASM and ASML2 before going any further. I've done some little research
and found <a href="http://www.eecs.umich.edu/gasm/">GASM</a> by accident (Google helping ;-) ).
I think it's worth a look before deciding about vetoing and threading.
<p>
<b>State machines under discussion... or not?</b>
<p>
Different people have suggested using state machines. After all, since controllers just
receive and send events... couldn't they be programmed as state machines?
Now, isn't it worth to evaluate how difficult writting state machines in Java is?
Isn't it worth evaluating it now, before deciding on vetoing?
Isn't it that vetoing is just a fork/join in a state diagram? I'm sure you all agree. Let's be
open-minded to different alternatives and, after seeing as many as possible, let us
agree on a final decission.
<p>
So I've found GASM. <a href="http://www.eecs.umich.edu/gasm/">GASM</a> is defined as
"A Formal Method for Specification and Verification".
<p>
Wow. The "Formal" adjective looks a little bit scary, doesn't it?.
"Formal" is usually related to complex things. Maths are formal and are usually difficult
to grasp. But "specification" and "verification" sound good. I think I'd like my big Swing
application to be as verified and specified as possible.
<p>
So I entered the <a href="http://www.eecs.umich.edu/gasm/intro.html">GASM Introduction</a>
and found that GASM has the following desirable characteristics: precision, faithfulness,
executability, scalability, generality and <b>understandability</b> (quoting:
"ASM programs use an extremely simple syntax, which can be read even by novices as a form of pseudo-code").
<p>
Now, that is interesting. "Extremely simple" and "novices" and "pseudo-code" sound good. Maybe
this "formal" thing is not too complex after all.
<p>
So I kept on reading a little bit more and found that Microsoft research
has already defined an <a href="http://www.research.microsoft.com/foundations/asml/">Abstract
State Machine Language v2.0</a> that seems to be implemented in .NET. Quoting:
<blockquote>
"It is an executable specification language based on the theory of Abstract State Machines. The current version, AsmL 2 (AsmL for Microsoft .NET), is embedded into Microsoft Word and Microsoft Visual Studio.NET"...
</blockquote>
Well, it seems lots of people are working on ASML as a way to formally
verify software. It seems Microsoft is embedding powerful state machines
in complex GUI software. That's a hint. After all Microsoft Word is a huge GUI application.
I think we all would like our big Swing applications being
formally verified. Right?
<p>
So, my final questions (and sorry to just keep doing questions all the time). Shall we
go take a look at state machine implementations out there? Give the a try? Or is this
just out of scope and we should concentrate on the event bus instead?
If defining a state machine in another language but Java, which language should it be?
SMC's <a href="http://smc.sourceforge.net/">FSM</a> language (compiled to Java)?
Or an interpreted language such as JPython, XML, Groovy or Scheme?
<p>
I'd appreciate any opinions, suggestions and critics. I'm getting too confused ;-)
<p>
Thanks in advance,<br>
Antonio<br>
<p>
P.S.: There's no problem in using JDK 1.4. Annotations could be substituted in some way using
reflection or other mechanisms when adding/removing topic listeners. The only requirement I can
think of is using Doug Lea's concurrent utilities (adopted in JDK 5.0 as java.util.concurrent).
<p>
P.S.II: Hierarchical listeners: Shouldn't be too difficult to do, I think. What about keeping
a topic-listener map in a <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/SortedMap.html">SortedMap</a> and then using
<a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/SortedMap.html#subMap(java.lang.Object,%20java.lang.Object)">submap</a>
to fetch a subset of the map? (The "trie" or "Patricia Trees" data structures could be of help here too, that way you could fire events to "\*action" or "file\*", this is, by using either suffixes or prefixes).
<p>https://blogs.oracle.com/swinger/entry/the_bus_from_the_planeThe bus, from the planeswingerhttps://blogs.oracle.com/swinger/entry/the_bus_from_the_plane
Tue, 27 Sep 2005 11:00:58 +0000Event bus<p>
Before rushing into the actual implementation I'd like to show you a 10000 feet view of the bus. Just in case you want to give some feedback/suggestions. What I am thinking of is something like this (click to enlarge):
<p>
<center>
<a href="http://blogs.sun.com/roller/resources/swinger/MVC.png" target="top"><img src="https://blogs.oracle.com/roller/resources/swinger/MVC-small.png" border="0"></a>
</center>
<p>
So basically there're three parts:
<ul>
<li>View: formed by the macro-components and, possibly, some "actuators" (more on this later).
<li>Controller: formed by the mediators. Contains the business logic. Has read/write access to
the model. Receives events from the components through the bus (component-events), through specific topics (XXX-event). Sends commands (application events) to the bus through specific topis (XXX-command)
Does not contain any instances of the view.
<li>Model: formed by data (current clipboard contents, currently selected file, whatever).
</ul>
<p>
So what I am thinking of is something like this:
<ul>
<li><b>1.</b> Components send components through their specific topics towards the controllers.
<li><b>2.</b> Controllers coordinate component events. May veto (discard) events depending on the
model. Controllers may modify the model.
<li><b>3.</b> Controllers create and send application events (commands) through specific channels in the bus. These events are business specific and need not be related to components.
<li><b>4.</b> Actuators receive application components from the bus and modify the view accordingly. These actuators are the only responsible for holding instances to components.
</ul>
From my point of view controllers are what we've called "Type II aggregators" (no instances to the view, no dynamic dependencies) whereas actuators are "Type I aggregators" (instances to the view, dynamic dependencies).
<p>
(Well, I hope I've made myself clear. If not then just email me!)
<p>
<b>Doubts, design decissions, help appreciated</b>
<p>
<ul>
<li>Vetoing. Shall we need actual vetoing of events? I think it's enough if controllers just ignore/react
to events depending on the model. Can you think of an example where I could need vetoing for events? Tim, any idea about this?
<li>No component-controller dynamic (runtime) dependencies. With the approach above I think we have dynamic decoupling of components and controllers. What I mean is that we don't need macro-components instantiated before controllers are instantiated. If components are absent then there's no problem for controllers. Controllers may be instantiated independently of components. This is right I think (am I right here?)
<li>Component-controller static (compile-time) dependencies. In order to compile the controllers I'll need to have component events in place. This is, there's a static dependency between components and controllers. I don't think this is an issue, unless you need to compile controllers and components independently. I can't think a reason why these static dependencies are an issue. Any scenarios you can think of?
</ul>
(Diagrams are <a href="http://blogs.sun.com/roller/resources/swinger/diagrams.sxi">here</a>, <a href="http://www.openoffice.org">OpenOffice/StarOffice</a>, 9Kb, right-click/Save As... to download).
<p>
Thanks for any ideas!<br>
Antonio<br>https://blogs.oracle.com/swinger/entry/by_bus_or_on_footBy bus or... on foot?swingerhttps://blogs.oracle.com/swinger/entry/by_bus_or_on_foot
Mon, 26 Sep 2005 11:37:04 +0000Event bus<p>
So I've been receiving some mails with some questions and suggestions. And, to be honest,
I'm confused. Too many ideas. Brainstorming is working!!
<p>
Some of the ideas were about
the site design. I've taken some into account (a friend of mine helped me
with the HTML, well, <b>that's</b> difficult!). Expect some more changes in the coming
weeks as time permits. Entries are more organized now in
(hopefully useful) categories. I've also included some links to other interesting blogs, too.
Feedback is greatly welcome.
<p>
So I decided to share with you my concerns, just once more, in order to try to clarify things.
(So, please, help me here).
<p>
There we go:
<p>
<b>Question I: Is this "Event Bus" a new "pattern" or not?</b>
<p>
Someone suggested this "event bus" approach was some sort of pattern. I've been reviewing the "Observer Pattern" in my copy of "Design Patterns" during this weekend. And reading Design Patterns I've found interesting stuff I'd like to share with you. Just to try to
clarify my thoughts.
<p>
Let me quote Design Patterns just a moment, please:
<p>
<blockquote>
"Define a one-to-many dependency between objects so that when one object
changes state (our macro-components), all its dependents (listeners) are notified and
updated automatically"
<p>
<div><a href="http://www.amazon.com/exec/obidos/tg/detail/-/0201633612/104-5356561-8720719?v=glance">Design Patterns</a> - <a href="http://www.dofactory.com/Patterns/PatternObserver.aspx">Observer pattern</a></div>
</blockquote>
<p>
D'oh!! One-to-many what?? Dependencies, you say?? Wait, wait, wait. Wasn't it <a href="http://www.joelonsoftware.com/articles/fog0000000007.html">"Find dependencies... and eliminate them"</a>??
Isn't that the problem? Yes! The Observer Pattern is the problem!
The macro-components of my Swing applications (the Observables/Subjects)
keep "one-to-many" dependencies with the listeners (the Observers).
<p>
That's why my StatusBar is a listener of the FilesystemViewer, and the
FilesystemViewer is a listener of the Menubar! And the Editor is
a listener of both the FilesystemViewer and the Menubar!
And that's why I'm having
chains of listeners, and thus chains of dependencies. And that's why I'm
having so many problems with large Swing applications!!
<p>
So let's define a new pattern!! Let's call it the Event Bus Pattern!! Pretty much
as Martin Fowler calls it an Event Aggregator.
<p>
Well, er... no.
<p>
That would be just plain <a href="http://blogs.sun.com/roller/page/swinger?anchor=overpatterning_pattern">Overpatterning</a>, I think. Isn't it?
<p>
Let's keep on reading.
<p>
Please allow me to quote here an excerpt of Design Patterns. Again. Please bear with me.
<p>
<blockquote>
<em>Encapsulating complex update semantics.</em> When the dependency
relationship between subjects (macro-components) and observers (listeners) is particularly complex,
an object
that maintains these relationships might be required. We call such an object
a Change-Manager (i.e., the Event Bus equivalent). Its purpose is to minimize the work required to make
observers (listeners) reflect a change in their subject (macro-components). For example, if an operation
involves changes to several interdependent subjects (macro-components), you might have to ensure
that their observers (listeners) are notified only after <em>all</em> the subjects (macro-components)
have been modified to avoid notifying observers (listeners) more than once.
<p>
<div align="right">Design Patterns - Implementation, paragraph 8</div>
</blockquote>
<p>
So, as you can see, the Event Bus was already defined as early as 1994!!
(Well, I think the "Change-Manager" is not exactly an Event Bus because the
one-to-many dependencies are still kept there between Subjects and Observers,
but it's a rough approximation, thoughts?).
<p>
But, wait, there's even more. Go see section Implementation.7 and you'll
see <b>aspects</b> defined, something similar to "topics", "interrupt-levels"
or "channels". Isn't it? (Or is it that I see topics everywhere? ;-) )
<p>
But, wait, wait, there's even more!!
<p>
At the end of section Implementation.8 I read:
<p>
<blockquote>
... ChangeManager (EventBus) is an instance of the Mediator pattern.
In general there is only one ChangeManager, and it is known globally.
The Singleton pattern would be useful here.
</blockquote>
(Note that ELF is using singletons for their event bus).
<p>
So, as you can see, Mediators were already in place in Event Buses
in 1994!!
<p>
<b>Question II: Is this "event bus" really needed for big Swing apps?</b>
<p>
Jim asked if this "event bus" approach is required for big Swing applications.
<p>
This is, shall we go by bus or just on foot with simple Listeners?
I'd say this "event bus" is <b>not</b> needed, but <b>may</b> be helpful (what do you think?)
(In the sample application there's an asynchronous listener for logging
events to System.out, for instance, and building it is extremely easy).
<p>
Typical medium-size Swing applications have usually some
sort of controller. Usually mixed with view logic. You can see
an example in the <a href="http://blogs.sun.com/roller/page/swinger?entry=mandelbrot_update_with_new_fonts">Mandelbrot Explorer</a> source code. Take a look at the
MandelbrotViewController.java class. That's a ZoomListener,
ShiftListener, PropertyChangeListener and ProgressPaneCancelListener.
All in one. It aggregates events from different views.
And then it coordinates them. It's a mediator instance.
<p>
But by doing things through "event buses" you may make
things easier. It's easier to encapsulate these "mediators"
in separate classes, attached to the bus. Don't you think?
<p>
<b>Question III: Aren't we generating tons of events?</b>
<p>
Well, it depends. Don't you generate lots of Actions?
I'd say Swing "Actions" encapsulate event listeners, right?. Actions tend
to be more powerful "ActionListeners". So, what about
changing Swing actions into, say, ApplicationEvents through the bus?
EditAction, OpenFileAction and the such would then be transformed
into EditActionEvents, OpenFileActionEvent or, as Tim suggested,
EditCommandEvent, OpenFileCommandEvent.
<p>
So, from my point of view, yes: it generates lots of events. But that's
not a problem, I think. Thoughts?
<p>
<b>Example</b>
<p>
<a href="http://blogs.sun.com/roller/resources/swinger/uitopics.jnlp"><img src="https://blogs.oracle.com/roller/resources/swinger/uidemo-shot.png" alt="UITopics demo Screenshot"></a>
<p>
I'm almost done with <a href="http://blogs.sun.com/roller/resources/swinger/uitopics.jnlp">the sample application (JDK5.0 Java Web Start)</a>. I'll talk of it in the coming weeks as a basis for discussion. It's built with Type I aggregators
(controllers with instances to the view). <a href="http://blogs.sun.com/roller/resources/swinger/UITOPICSDEMO-src.jar">Source code</a> is available (<a href="http://blogs.sun.com/roller/resources/swinger/uitopics-src.jar">uitopics</a> and JDK5.0 required).
<p>
I think mediators (package net.java.uitopics.demo.controllers) are not that difficult to read, right? Any suggestions?
<p>
Cheers,<br/>
Antonio<br/>https://blogs.oracle.com/swinger/entry/take_the_bus_yourself_fridayTake the bus yourself!!swingerhttps://blogs.oracle.com/swinger/entry/take_the_bus_yourself_friday
Fri, 23 Sep 2005 09:44:45 +0000Event bus<p>
<p>
So you may want to <a href="http://blogs.sun.com/roller/resources/swinger/uitopics-src.jar">take the bus yourself</a> and see how well it goes.
<p>
Note that this is an alpha version and I'm still experimenting with it (I'm working out a demo). I'd suggest you generating javadoc.
<p>
It's just six classes, but don't panic! Of those six just two are public (and one of them is not a class but an annotation).
<p>
This is one of my Type I aggregators:
<p>
<pre><code>
public class StatusMessagesMediator
{
private Statusbar statusbar;
public StatusMessagesMediator( Statusbar aStatusbar )
{
statusbar = aStatusbar;
}
@TopicListener( topicName="filesystem.events" )
public void onFilesystemEvent( TopicManager aTopicManager, FilesystemEvent anEvent )
{
switch( anEvent.getEventType() )
{
case FilesystemEvent.SELECTION_TYPE:
statusbar.setStatusMessage( anEvent.getFile().getName() );
}
}
}
</code></pre>
<p>
To attach the mediator (aggregator) to the bus just write:
<pre><code>
StatusMessagesMediator mediator = new StatusMessagesMediator();
topicManager.addTopicListener( mediator );
</code></pre>
To attach a macro-component to the bus just write:
<pre><code>
FilesystemViewer viewer = new FilesystemViewer();
topicManager.addEventSource( "filesystem.events", viewer, FilesystemEventListener.class,
ActionListener.class, <em>(any other EventListener class here)</em>... );
</code></pre>
(Note that you specify listener types and not events, sorry).
<p>
I decided to post it here just because the java.net project is still under approval (maybe they're surprised it's just six classes ;-) )
<p>
During this weekend (if time permits) I'll think about building a Type II aggregator using a Type I aggregator. (Hint: split the aggregator above into two ones. One with instances and another without instances, change topic names, done?)
<p>
Sorry for the short post (I'm in a hurry now). Enjoy it. Have a good weekend. Keep Swinging,<br/>
Antonio<br/>https://blogs.oracle.com/swinger/entry/traffic_lights_for_the_eventTraffic lights for the event busswingerhttps://blogs.oracle.com/swinger/entry/traffic_lights_for_the_event
Fri, 23 Sep 2005 00:58:39 +0000Event bus<p>
Wow! This is warming up. Thanks all for your comments, emails, and for taking the bus with me!
<p>
There're lots of interesting things in your comments so I'll try to review them all,
as time permits, and express what I think. So <b>please</b> correct me if I'm wrong.
Get ready for one of the biggest blog entries in the Internet! (Sorry by that :-()
<p>
<b>Event Buses and Event Queues</b>
<p>
As Kevin points out there're similarities between event buses and the AWT Event Queue.
After all, let's be honest, both are ways to deliver events to listeners!
<p>
In fact I think that taking control of the event queue may be of great help
in GUI development. It allows you to be asynchronous. It allows you to take
control on event delivery. I've taken a look at
<a href="http://foxtrot.sourceforge.net">foxtrot</a> (as you know foxtrot is a
well known framework for handling asynchronous operations in Swing) and found that...
they're taking control of the event queue too!! See:
<blockquote>
In contrast, Foxtrot lets the Event Dispatch Thread enter but not return from the listener method, instead <b>rerouting the Event Dispatch Thread to continue dequeuing events from the Event Queue</b> and processing them. Once the worker thread has finished, the Event Dispatch Thread is rerouted again, returning from the listener method.<br />
<div align="right"><a href="http://foxtrot.sourceforge.net/docs/foxtrot.php">read more</a></div>
</blockquote>
But, wait, there're many more examples out there! As Jonny (thanks, Jonny, I didn't know about it!)
kindly pointed out we have the <a href="https://elf.dev.java.net/">Event-Listener Framework (ELF)</a>, too.
<p>
So it seems taking control of the event queue is key to ease things.
Taking control of the event queue seems a powerful idiom.
Now, what is the
difference between an event bus and a controlled event queue? Don't they both deliver
events?
<p>
Well, as far as I understand, the main difference may be explained with this drawing...
<pre><code>
+---------------+ +----------------+ +-------------+ +-------------+
| | | | | | | |
| ActionManager | | EventResponder | | AntModule | | AntModule |
| | | | |(ProjectNav) | |(SourceEdit) |
+---------------+ +----------------+ +-------------+ +-------------+
| \^ \^ \^
| | | |
ActionEvent EventObject AntEvent AntEvent
| | | |
v v v v
/---------------------------------------------------------------------\\
/ \\
< EventBus >
\\ /
\\---------------------------------------------------------------------/
| \^ \^ \^
| | | |
EventObject ChangeEvent BuildEvent EventObject
| | | |
v | | v
+---------------+ +----------------+ +-------------+ +--------------+
| | | | | | | |
| Console | | ProjectProxy | | Ant | | (Your Module)|
| | | | | | | |
+---------------+ +----------------+ +-------------+ +--------------+
</code></pre>
<p>
... that I've copied (without permission!! ;-)) from <a href="http://www.jajakarta.org/ant/ant-1.5/docs/projects/antidote/design.html">the antidote design document</a> (antidote is a GUI for Apache's ant).
<p>
This is, I think that the event bus delivers events the same way an event queue does, but <b>it's the
single point of contact between components</b>. Or, as the Antidote design
document nicely explains:
<blockquote>
"In order to keep the coupling among application modules to a minimum, a single
point of reference is needed for coordination and data sharing."
</blockquote>
(Note that this is exactly what ELF does, too).
<p>
<b>Topics, Channels and ... interrupt levels!</b>
<p>
Note as well that the Antidote design document describes different topics
(or channels) to deliver events. They call them "interrupt levels".
<p>
If you read carefully you'll see a VETOING topic, a MONITORING topic, and a RESPONDING interrupt level.
Now, don't these look similar to the ones Tim has been suggesting since the very first day?
Add to these interrupt levels a "COMMAND" topic (where the Open/Save/Close events are delivered)
and a "STATE" topic (where the Opened/Saved/Closed events are delivered) and you're
(I think) pretty much solving Tim's concerns (Am I right here, Tim?)
<p>
Note, though, that Antidote seems to deliver events (interrupt levels) to <b>all</b>
bus components. Whether they're interested in listening or not. We may refine
this a little bit to avoid bothering components with events they're not intersted in.
<p>
<b>Traffic lights for bus lines</b>
<p>
And here we come to the tough part. Decide how to coordinate that
event traffic. Decide which events go in which bus lines. Define how many
topics. Place some traffic lights somewhere.
<p>
After all, as <a href="http://www.looselycoupled.com/opinion/2004/bradl-save-infr1206.html">Ronan
Bradley (CEO, PolarLake)</a> clearly stated, the ESB is just a communication mechanism. The mediation,
the orchestration, is the tough part.
<p>
So I can think of different mechanisms and I would like your feedback on this.
<p>
<b>I. Event aggregators as event sinks</b>
<p>
The very first approach is having one or more listeners of the bus holding instances of
other components. These aggregators will receive different events from
different components in the bus. And will then orchestrate them, making direct
method calls on those components. Note that these are listen-only aggregators.
<p>
<ul>
<li>One of these aggregators (status bar aggregator) would listen the bus for the "FileSelected" and "FileOpen"
events and then invoke the "statusBar.setMessage(...)" on the status bar.
<p>
<li>Another of these aggregators (editor aggregator, say) would listen the bus for the "FileOpen" event
(coming from either the menu bar or the filesystem viewer) and then invoke
the "editor.open(...)" method of the editor.
</ul>
<p>
Building such aggregators is simple. All macro-components
have a single listener: the event bus. And the event bus, in turn, has one
or more listeners: the aggregators.
<p>
Furthermore, aggregators can talk themselves through the bus.
So they're event sinks, but may produce (simulating) events from
the components to fire action in another aggregator. For instance,
an aggregator could post a "FileOpen" event in the bus, so the
"editor aggregator" workflow above will be executed.
<p>
This approach is modular too. You can add different aggregators.
Adding new features to the GUI requires new aggregators. All
control logic is in the aggregators, that manipulate
the data model and deliver pieces to components. Components are just pasive views
between the user and the controller.
<p>
In this approach macro-components are loosely coupled. You don't mix
listeners between components. You don't have the status bar listening
the filesystem viewer, nor the editor listening the menu bar. One-to-one
listeners are gone. Instead
all components have a single listener: the event bus.
<p>
With this approach there's no need to deliver command events to components, either,
because aggregators invoke methods on them directly.
So there's no need to veto events. No command events.
No need to worry about locking problems:
the order of reactions to events is fully controlled, in Java, in the aggregators.
<p>
I think this approach architects all this event handling in three layers. See:
<ul>
<li>A view layer, with
macro-components, responsible for visual display of data and primary user event
handling.
<li>A bus layer, responsible for routing events from components to aggregators.
Events may be delivered either synchronously or asynchronously.
<li>An aggregator (controller) layer, responsible for handling events from components,
coordinating them and manipulating the data model.
</ul>
Maybe a small diagram clarifies things a little bit?
<p>
<img alt="Type I aggregators" src="http://blogs.sun.com/roller/resources/swinger/type1-aggregators.png" border="0">
<p>
<b>II. Event aggregators as event producers</b>
<p>
The second approach I can think of is similar to the previous one.
"Type II" aggregators will listen the bus for component events, too. But will \*not\*
have any instances pointing to the components. Instead of making direct method calls
these aggregators would just send events, command events, to components.
<p>
<ul>
<li>The "status bar aggregator" could receive the "FileSelected" and "FileOpen"
events from the bus and then <b>send</b> a "setMessage" event through the
"statusbar" "command" channel.
<li>And another of these aggregators, the "editor aggregator",
could receive the "FileOpen" coming
from the menu bar of the filesystem viewer and then <b>send</b> an "open" command
event through the "editor" "command" channel.
</ul>
<p>
This approach seems to be very powerful (does it not, Tim? ;-)).
<p>
Since there's not a direct link
between macro-components, these may be replaced (by mock macro-components in order
to do some gradual functional tests) or may even be absent (and command events
would then be simply ignored).
<p>
You could even run the whole aggregators with a bus... without a GUI!. Replace all
macro-components with mock objects (responsible for receiving and sending events)
and you could exercise the whole controller logic.
<p>
You could even substitute
the presentation logic and reuse the controller logic. So you could have a view layer
with SWT and another view layer with Swing, and swap between them both without touching
a single line of the controller logic.
<p>
Note also that I say "statusbar" "command" channel and "editor" "command" channel, so
I suggest having different "command" channels for different components, and not just
a single "command" channel to all components. By doing so I think we get rid of
vetoing and the lock problems Tim points out (am I right here)?
<p>
So, to summarize, these "Type II" aggregators would just replace direct
method calls (and instances) with command events directly delivered to components
(through each component's command channel).
<p>
These "Type II" aggregators would be similar to state machines.
You would need for these something similar to Antidote's "ApplicationContext" to keep
track of state. You could even program them
with, say, the <a href="http://smc.sourceforge.net/">SMC's FSM language</a> (instead of
using BPEL, which is only for orchestrating web services in ESBs).
<p>
Or you could use some sort of Workflow engine. After all an aggregator just receives
and sends events (and keeps state and access the model for data). So some sort of
workflow mechanism may be helpful here?
<p>
May be is that the future of GUI development? Using some sort of declarative
language to manipulate GUI behaviour, once a good set of macro-components is in place?
Having workflow editors to program GUIs? Who knows. Maybe we'll have something similar to
<a href="http://www.netbeans.org/images/screenshots/4.1/nb_midp_visual_editor.png">NetBeans
MIDP Visual Editor</a> for building J2SE GUI Applications.
<p>
<b>This is a long one</b>
<p>
Sorry for such a long post. It's lots of things to think of!
<p>
Now, what do <b>you</b> think? Which one would you prefer? Type I aggregators or Type II aggregators?
You may already know my preference: I like simple things! ;-)
<p>
I'm wishing to discuss. Come on, <a href="http://www.sun.com/emrkt/share/philosophy.jsp">participate</a>.
I'm working for a draft implementation and I'll let you know whenever is ready.
<p>
Happy Swinging,<br/>
Antonio<br/>https://blogs.oracle.com/swinger/entry/let_s_take_the_busLet's take the bus. The Swing Event Bus.swingerhttps://blogs.oracle.com/swinger/entry/let_s_take_the_bus
Wed, 21 Sep 2005 12:07:23 +0000Event bus<p>
So continuing yesterday's entry about SOA for Swing and event buses, I thought
it could be a good idea to take the Swing Event Bus first. Just to explore how far
we can go with it.
<p>
I received some emails (and just one comment, thanks Tim!) on this so
I thought it could be a good idea to share my thoughts with you (well,
after all that's what a blog is about, right). But, more importantly,
I would like you so thare ideas with me. So let's participate, suggest
(and criticize, of course).
<p>
<b>Our starting point</b>
<p>
To clarify let's assume we have an application with just four major
macro-components:
<ul>
<li> A Filesystem Viewer (FV). A component that visually shows the
contents of the file system. Say with a JTree or a JTreeTable.
This component is responsible or detecting selections of files,
double clicks and drag-and-drop operations.
<li> A Status bar (SB). Responsible for showing status messages.
<li> An editor window (ED). Responsible for opening text files.
<li> A Menu bar (MB). With the usual actions for opening files, etc.
Of course some of the items in the menus are enabled and disabled
depending, say, on the type of the file and the status (saved/unsaved)
of the editor.
</ul>
Yesterday I described some of the horrors of the Observer pattern in
complex GUIs. This is, how the event-source to event-listener one-to-one
relationship is a nightmare for big applications. There's another
description of some of the problems at
<a href="http://martinfowler.com/eaaDev/OrganizingPresentations.html#observer-gotchas">
Martin Fowler's</a> site (see "Observer Gotchas"), just if you're interested. (By the way,
you may find <a href="http://martinfowler.com/eaaDev/EventAggregator.html">the event
aggregator pattern</a> of interest too).
<p>
So, to summarize, we want do build a Swing Event Bus that efficiently delivers
events generated by these macro-components. Either synchronously or asynchronously.
Our main objective is to make these macro-components as loosely coupled
as possible. Ideally each one of these four macro-components will know
<b>nothing</b> about the rest, although they will be orchestrated and
will jointly cooperate to build the user interface of a simple text editor.
<p>
(I would like to add a feature here too: the whole thing should be
extremely <b>simple</b> to use).
<p>
<b>Design Idea I: Different bus lines?</b>
<p>
Now let's see how other people are doing this. Let's see further
by standing on the shoulders of giants. Let's learn from what it's
already done.
<p>
The very first feature that comes to my mind is the need for
different bus lines. This is what JMS calls Topics and what Werx calls
Channels.
<p>
The benefit of this, of course, is that we don't have to deliver
the events to <b>all</b> bus listeners. We don't have to stop the bus
in all bus stops in the city. We reduce the number of bus stops to those
in the bus line. Events are delivered (through a channel/topic) to
a subset of listeners. And the traffic is more efficient, and our qualities of
service improve.
<p>
<b>Design Idea II: Separating concerns</b>
<p>
I like <a href="http://en.wikipedia.org/wiki/Separation_of_concerns">separation of
concerns</a>. Each macro-component must be responsible for its own GUI. Events
internal to the macro-component should be handled internally, using
event sources and event listeners as usual.
<p>
The macro-components should communicate with the outside world by posting
specific events to a topic/channel in the bus. For instance, the FV could
generate FileSelectedEvents and FileDoubleClickedEvents to the "FV" topic
in the bus. And the editor could post EditorSaveEvent, or whatever other,
in the "editor" topic in the bus. Don't you think?
<p>
<b>Design Idea III: Mediator Pattern?</b>
<p>
As Tim suggested there should be a mediator somewhere to coordinate
events and macro-components. I think the Mediator Pattern fits nicely:
<blockquote>
The Mediator pattern uses an object to coordinate state changes between other objects. Putting the logic in one object to manage state changes of other objects, instead of distributing the logic over the other objects, results in a more cohesive implementation of the logic and decreased coupling between the other objects
</blockquote>
Do you think this is a good idea? I see the controller in the MVC here, right?
If so, shall this Mediator have
direct references to the macro-components? I mean, there're two ways for
the mediator to command something to the macro-components:
<ul>
<li>A) Having references to macro-components. Say the mediator has
an instance of the "EditorPanel" and just invokes "Editorpanel.open( aFile )".
<li>B) On the other hand this mediator could just send an EditorOpenEvent
through the "edit" topic of the bus, so that the editor opens it.
</ul>
I'm afraid that A) above is asking for trouble. I was wondering if that by
using "B)" above things should be easier to test functionally? I mean,
by storing (and then repeating in order) events received
in the bus we could make functional
tests easier to reproduce. Am I right here?
<p>
<b>Design Idea III: Inversion of control</b>
<p>
I received a pointer to Mike Aizatsky's article about <a href="http://www.onboard.jetbrains.com/articles/ldi/">Inversion
of Control</a> with listeners. I'm not very good at IoC so I don't know if this
applies or not here. Does it? How?
<p>
Well, that's all today (I'm too tired). I'd like to hear from you!<br/>
Cheers,<br/>
Antoniohttps://blogs.oracle.com/swinger/entry/soa_for_swing_event_handlingSOA for Swing (event handling scalability)swingerhttps://blogs.oracle.com/swinger/entry/soa_for_swing_event_handling
Tue, 20 Sep 2005 10:48:26 +0000Event bus<p>
<b>Why UI event handling may not scale</b>
<p>
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.
<p>
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.
<p>
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.
<p>
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.
<p>
<b>The SOA equivalence</b>
<p>
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.
<p>
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.
<p>
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.
<p>
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.
<p>
<b>The "Swing Event Bus" (and its events)</b>
<p>
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.
<p>
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.
<p>
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.
<p>
<b>You can use both, of course!</b>
<p>
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 <b>not</b> 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?
<p>
After all the "Swing Event Bus" should be used just to attain loose-coupling between
major macro-components. Using it <em>inside</em> a macro-component makes no sense at all.
<p>
<b>So, where is this Swing Event Bus?</b>
<p>
Well, the idea of using event buses for Swing has been around for a long time.
<p>
The first that comes to my mind (and probably the older one) is the
good, old, easy-to-use, withdrawn, almost-forgotten <a href="http://www.jcp.org/en/jsr/detail?id=33">InfoBus</a>
specification (we even had some implementations at java.sun.com).
<p>
But there're may others out there. There is <a href="https://somnifugijms.dev.java.net/">David
Walend's Somnifugi</a>, a lightweight JMS implementation. And <a href="http://www.werx.org">werx</a>, for instance.
<p>
And I'm not the first one to talk on this either.
<a href="http://d-haven.org/modules/news/article.php?storyid=12">Berin Loritsch</a>,
<a href="http://weblogs.java.net/blog/dwalend/archive/2004/06/somnifugijms_fo_4.html">David Walend</a>,
<a href="http://www.ryandaigle.com/pebble/2004/03/22/1079972827000.html">Ryan's Scraps</a>,
<a href="http://jroller.com/comments/ljn?anchor=did_swing_get_it_right">Lair Nelson</a> and
probably tons of others have talked on this before.
<p>
<b>So, why talking on this now?</b>
<p>
Well, you know I suffer badly from <a href="http://blogs.sun.com/roller/page/swinger?entry=frameworkitis_and_reuse">frameworkfobia</a>, 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 :-().
<p>
<b>Next posts</b>
<p>
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?
<p>
Food for thought. Cheers,<br>Antonio<br>https://blogs.oracle.com/swinger/entry/exception_topics_and_typical_exceptionsException topics and typical exceptionsswingerhttps://blogs.oracle.com/swinger/entry/exception_topics_and_typical_exceptions
Mon, 19 Sep 2005 10:45:33 +0000Event bus<b>Exception topics</b>
<p>
I'm still waiting for the <a href="http://blogs.sun.com/roller/page/swinger?entry=talking_topics_event_programming_revisited">UITopics stuff</a> to be approved by java.net. I cannot upload .jar files to my blog now (some sort of weird filtering or something), so there's nothing
I can do but wait :-(
<p>
I'm still shifting paradigm between the Observer pattern (used by Swing for event listeners) and the publish-subscribe paradigm that UITopics promotes. I'm still finding new idioms and new features.
<p>
Take for instance exception handling in GUIs. Imagine I have a Topic called "application/errors". Now, whenever I have an exception, I post an ExceptionEvent to that topic. Like this:
<pre><code>
...
TopicManager tm = getTopicManagerFromSomewhere();
try
{
doWhatever();
}
catch( Exception e )
{
tm.postEvent( "application/errors", new ExceptionEvent(e) );
}
...
</code></pre>
where an ExceptionEvent is a custom event...
<pre><code>
public class ExceptionEvent extends java.util.EventObject
{
public ExceptionEvent( Exception source )
{
super( source );
}
public Exception getException()
{
return (Exception) source;
}
}
</code></pre>
This is, I just send the event to the "application/errors" for whoever listeners may be there.
<p>
One topic listener just (asynchronously? yes, why not...) logs the stack trace...
<pre><code>
@TopicListener( topicName="application/errors", isAsynchronous=true )
public void logException( ExceptionEvent ee )
{
System.out.println( ee.getException().printStackTrace() );
}
</code></pre>
While another, in the Swing thread, shows a message dialog:
<pre><code>
@TopicListener( topicName="application/errors" )
public void handleExceptionWithPopup( ExceptionEvent ee )
{
JOptionPane.showMessageDialog(
... ee.getException().getMessage() ...
);
}
</code></pre>
This is somewhat powerful. I can attach (or deattach) any of the listeners.
I may have a listener for debugging purposes that prints out all exceptions.
I may even have a listener that logs all events into a topic and replays
them later on (to emulate user input).
<p>
Yes, definitely shifting paradigms is interesting.
<p>
<b>Typical exceptions</b>
<p>
On other news, I received my september copy of "Communications of the ACM" today.
I just opened it and I could read:
<blockquote>
<b>Can you spot the security flaw?</b><br>
<pre><code>
Try {
Byte [] text = AccessPlaintextData();
Byte [] password = GetPassword();
...
EncryptData( text, password );
...
} Catch() {
// exception code
}
</pre></code>
"This pseudo-code reflects a somewhat common flaw ... in .. M$$soft
Internet Information Server 4.0 ..."
</blockquote>
Now, remember that <a href="http://www.artima.com/intv/handcuffs.html">article at artima about checked
exceptions in C#</a>? In the article Anders Hejlsberg said "I see two big issues with checked exceptions: scalability and versionability."
<p>
Now, my conclussion after reading that article at Artima and the ad at magazine is: in C# there're no checked exceptions because of lack of scalability and versionability <b>at the cost of lack of security</b> (!?).
<p>
Well, it seems that after all James Gosling was right <a href="http://www.artima.com/intv/solid.html">when saying</a>:
<blockquote>
- What does "solid" mean?<br>
- James Gosling: Solid means you can run the software day in and day out. When the usual crazy things happen, the software survives.
</blockquote>
<p>
Now, I'm glad I have checked exceptions in Java!
<br>
Happy Swinging,<br>
Antoniohttps://blogs.oracle.com/swinger/entry/talking_topics_event_programming_revisitedTalking topics: Event programming revisitedswingerhttps://blogs.oracle.com/swinger/entry/talking_topics_event_programming_revisited
Sun, 18 Sep 2005 04:59:56 +0000Event bus<b>Introduction: the spark that lit the whole thing</b>
<p>
So I happened to pass by <a href="http://www.enterprisej2me.com/blog/java/?postid=115">Michael Yuan's Java blog</a> where I could read:
<pre><code>
@SwingAsynch
private double getPayment (...) {
// Takes a long time to return
}
</code></pre>
And, to be honest, I liked the idea of <b>using annotations for thread
programming in Swing</b>. So I decided to build a simple research, experimental,
project to be able to do that too. I'll call it <b>UITopics</b>.
Now to do thread programming in Swing I can write something like this:
<p>
<pre><code>
@TopicListener( topicName="application/compute", isAsynchronous=true )
public void doSomething( TopicManager aTopicManager, ActionEvent anEvent )
{
// Takes a long time to return
}
</code></pre>
<p>
Well, it's not exactly the same, but it's somewhat more flexible and powerful.
So let me explain how to use UITopics (and, please, if you've feedback on this
I'll greatly appreciate hearing from you).
<p>
<b>Talking topics: What topics are</b>
<p>
The whole idea of UITopics is talking topics. Topics are just strings of
your liking. Say "application/compute" or "application/fatalErrors" or
"application/log" or "Java is cool!!" or whatever other string you may
think of.
<p>
The idea is to <b>deliver events through topics</b>. Either Swing events or
any other events of your liking (as far as they extend java.util.EventObject).
<p>
Note that sending events through topics (and queues) is nothing new in UI programming.
<a href="https://somnifugijms.dev.java.net/">Dave Walend's SomniFugi</a>, for instance, just
does that (and many other things), too, by exposing a JMS interface for GUI programming.
<p>
<b>Talking topics: What topic listeners are</b>
<p>
And the idea is also to receive events using topic listeners.
Topic listeners are <b>any sort</b> of Java object of your liking.
The only requirements needed to build a topic listener are:
<ul>
<li>At least one method must be tagged with the @TopicListener annotation.
<li>The first argument must be a TopicManager.
<li>The second argument must be an event. Any event. (Say ActionEvent,
WindowEvent, EventObject, MouseEvent).
</ul>
So, for instance, this is a valid topic listener:
<pre><code>
public class MyClass
extends <b>WhateverOtherClass</b>
implements <b>WhateverYouWantInterface</b>
{
<b>@TopicListener( topicName="application/errors" )</b>
public void whateverMethod( TopicManager aTM, ActionEvent anAE )
{
System.out.println("An error was received");
}
<b>@TopicListener( topicName="application/eventlog", isAsynchronous=true )</b>
public void logEvent( TopicManager aTM, EventObject anEvent )
{
System.out.println("Event: " + anEvent
+ " received through topic : application/eventlog." );
}
}
</code></pre>
So this basically means that:
<ul>
<li>ActionEvents coming through topic "application/errors" will
be processed in the Swing thread by the method "whateverMethod".
<li>Any event coming through topic "application/eventlog" will
be processed in a worker thread (isAsynchronous=true) by the method
"logEvent".
</ul>
Well, you have to tell a TopicManager which instances of the
MyClass class will receive events. I mean, events are not delivered
automagically to all MyClass instances, you have to specify which
instances will receive events. By using code like this:
<pre><code>
TopicManager tm = new TopicManager();
MyClass myInstance = new MyClass();
MyClass anotherInstance = new MyClass();
tm.addTopicListener( myInstance );
</code></pre>
And, of course, events from that topic manager will only be sent
to the "myInstance" instance, and not to "anotherInstance" (because
that was not added as a listener).
<p>
I know this is a little bit weird and that I don't explain myself
too well. But take it easy with me and keep reading. It takes a little
time to change paradigms. I'll show a whole example below, later on.
<p>
<b>Talking topics: sending events</b>
<p>
So, who sends events to topics? How is this done?. I thought of
two ways to send events: using Swing components and doing it by hand.
<p>
<b>Sending events with Swing components</b>
<p>
Say you have a JButton and you want it to deliver ActionEvents and
MouseEvents through the "application/eventlog" topic. This is done
by writing:
<pre><code>
JButton myButton = new JButton("Press me");
TopicManager tm = new TopicManager();
tm.addEventSource("application/eventlog", myButton,
ActionListener.class, MouseListener.class );
</code></pre>
This basically means that all ActionEvents and MouseEvents
generated by the button are automatically routed to
all topic listeners listening on the "application/eventlog"
topic.
<p>
Not too difficult. Note though that you use "Listeners"
(i.e., "ActionListener.class, MouseListener.class") and not
events (i.e., not "ActionEvent.class, MouseEvent.class").
(I may be able to correct that in the future, but it's good
for me, anyway).
<p>
<b>Sending events by hand</b>
<p>
If you have a TopicManager at hand you may send events to
topics yourself. Like this:
<pre><code>
TopicManager tm ...
tm.sendEvent( "application/events", new ActionEvent(...) );
</code></pre>
<p>
That event will be posted to all topic listeners listening
for ActionEvents on topic "application/events".
<p>
<b>Summary</b>
<p>
So, to summarize (clarify?) UITopics looks like this:
<p>
<center>
<img src="https://blogs.oracle.com/roller/resources/swinger/uitopics-overview.jpg" border="0">
</center>
<p>
<b>So, where is the source for this?</b>
<p>
Well, I'm still entering it at Java.net (I hope they approve the project).
As soon as they approve it I'll post it for you to play with.
<p>
Happy Swinging meanwhile,<br/>
Antonio<br/>