Solving Swing's MVC Deficiencies 2

Posted by ryan
at 11:27 AM on Monday, March 22, 2004



The MVC design pattern is widely recognized as the preferred patter for developing UI-type applications, whether they be web applications or

more traditional client applications. While there are an abundance of widely accepted and quite mature MVC web frameworks, there are very

few for Swing applications. I believe this is because Swing does a good job of solving the “M” and the “V” portions of “MVC”, while leaving the “C” portion open.

Swing provides native support for using models, having a rich set of model interfaces and abstract classes for most of their UI components; I.e.

TableModel, TreeModel etc… Views are defined by the rich ui components that are driven by these models. It is when tying together the

interactions between the models and views (the controller portion) that Swing’s paradigm falls apart. Swing’s event/listener model is what can be

considered the controller part of the MVC, but is much too diffucult to maintain is it manifests itself as a graph of events and actions to listeners.

Thus Swing’s native controller is an unmaintainable myriad of event to listener to bound object relationships:

So while it’s clear that there is control logic, it’s all seperated between various listeners that are responsible for which bound objects to manipulate

upon which events. In addition, when forming these listener to event relationships you have to have a way to retrieve the reference to the actual

object you need to add the listener to. The same goes for getting the references to the bound objects that the listeners will need to manipulate.

What results is that you have to expose every object that wants to be a part of this system of events and listeners, independent of whether or not

it’s good design to expose these objects.

The first step to solving this problem is to consolidate the control logic into a more respectable, singular controller entity:

Instead of maintaining seperate listeners for every event, the controller has exposed methods to capture all system events and perform the

necessary response actions to the bound objects. While this consolidates the control logic, and forms a controller entity, it still does not clean up the

relationships between objects or the need to expose every object that needs to be part of this eco-system. I.e. the controller still must know of every

event and every bound object. What we need is a way for each event to log the event to a registry, and for each bound object to specify which

events they want to be notified of. Going even one step further, we need a more generic way for the bound objects to specify which events they

want to be notified of and not to refer directly to the event. This sounds a lot like the bus paradigm to me.

When an event occurs the object firing the event places an event message on the event bus. Any object that wishes to respond to an event can register itself with the event bus to be notified on the applicable events:

In this model, none of the events need to know anything about the bound objects and none of the bound objects need to know about the events.

And instead of having one big conglomeration of event/object bindings in the form of a controller, we can allow the bus to marshal event messages

to any object that cares about them. This offers the perfect seperation of logic without sacrificing flexibility.

In code I imagine this event model will manifest itself like so;

<i>Event firing object</i>
public void onEvent1() {
    EventBus.placeEvent(new Event("event1", this.eventContext));
}

<i>Event receiving object</i>
public void handleEvent(String eventId, EventContext context) {
    if(eventId == "event1") {
        aTextField.value = context.getProperty("userId");
    }
}

Thinking even further of the type of configuration and enhancements that could be applied here:

  • Events can be further organized by a heirarchical set of topics. So an event could be send on the “ui.mouse.movement” topic with an id of

    “panelHover”. Any bound object that has registered itself to listen to the “ui.mouse” topic would get notification of this event. This would make

    things like logging and other such wide-area functionality very basic to implement. The logging object would just register itself for the root or all

    (”*”) topic to receive notification of every event.
  • Using such frameworks as spring, or even utilizing aspect-oriented-programming, we can fully wire events to event bus to listening objects

    using an external XML configuration file. For instance, we can say which events are sent to which topics, and can then specify which objects

    listen to events of which topics. We can even specify which methods to execute when a particular event is received.
    <events>
        <event objectClass="com.ryandaigle.ui.MyButton" 
    eventClass="java.awt.ActionEvent" topic="ui.button" />
    </events>
    <receivers>
        <receiver-ref id="logger">
            <subscribeTopic id="ui.*" />
        </receiver-ref>
    </receivers>
    
    Now granted there is a lot here that I haven’t solved yet, but you get the idea.

I haven’t had a chance to look at how to maximize XWork in Swing, although

I’ve heard some rumblings about it recently. I’ve also been intrigued with Spring’s spring-rcf but have yet to see any code or documention for it.

My hope is that one of these two, or the combination thereof will implement a decoupled event bus-like model. It just seems to be the prefect model

for Swing/Java UI applications.

Comments

Leave a response

  1. Parsi VenkatJune 18, 2006 @ 02:19 PM
    Thanks for the beautiful explanation of things. Im a novice who is hooked up with "How is MVC in Swing Component and Swings Application". Any other Info please send me. Thanks a lot...
  2. Wilmer GloverDecember 21, 2007 @ 10:09 PM

    uterogestation planetarily rampingly trielaidin isanemone matchstick zephyranthes uneventful ECB keeps interest rates on hold http://www.expresspress.com/

Comment