Solving Swing's MVC Deficiencies

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.

The Need for Another Type of J2EE Object Scope 1

Posted by ryan
at 11:21 AM on Thursday, March 18, 2004



So it seems like directly manipulating the session is the defacto way to store cross-request objects in WW2 (and every other paradigm?) [see my previous post]. (Thanks for the advice, Jason. It’s active community involvement like this that makes projects such as yours and many other so successful). This got me thinking that the default scopes provided by the J2EE spec are pretty limiting, and that a good framework should provide a way to define intermediate scopes. Specific to WebWork 2, it seems like what needs to be defined is a lifespan of the various properties of the action. In my case I wanted the user property to span several actions. How about having property scopes defined in the xwork.xml like so:

<action ...>
  <property name="user" scope="session" />
  ...

This allows the scope of each property to be defined outside the actual action without the need for directly manipulating session maps etc…. However, it is not as flexible as to allow the lifespan or scope to be set to a finite number or types of actions. What we need is a kind of a scope in between a request and a session. How about being able to define an action sequence as a scope in xwork.xml?

<scopes>
  <scope type="actionSequence" name="userSequence">
    <action-ref name="getUserAction" />
    <action-ref name="saveUserAction" />
  </scope>
</scopes>

Then scoping your action properties like so:

<action name="getUserAction" ...>
  <property name="user" scope-ref="userSequence" />
  ...
</action>
<action name="saveUserAction" ...>
  <property name="user" scope-ref="userSequence" />
  ...
</action>

When the two requests occur in sequence or are chained, the user property of each action will be assured to be the same object. This would allow the flexibility of defining object lifespans beyond the limited request/session/application scopes that are now provided.

You could even go one step further and allow regular expressions when defining the action-ref attribute of each scope, so that all actions of a certain family can be grouped:

<scopes>
  <scope type="actionSequence" name="userSequence">
    <action-ref name="*UserAction" />
  </scope>
</scopes>

Just seems like a way to tightly define specific property lifespans within the context of the application flow… Comments are welcome.

How To Integrate Spring with WebWork 2

Posted by ryan
at 12:48 PM on Monday, March 08, 2004



This article has since been moved to the WebWork 2 wiki.

I recently started to work with WebWork 2, Spring and Hibernate 2 in an effort to utilize some of the more popular open source frameworks and libraries out there. While the Hibernate 2 documentation was quite complete and integration efforts went smoothly, as did getting WebWork 2 set-up, getting Spring integrated with Webwork 2 (or vice-versa actually) turned out to require some tweaking.

I started out using the original WebWork documentation to get Spring to initialize Webwork actions, but it appears that a lot has changed since the days of WebWork 1.x. This will be my attempt to clarify some of those changes and to list the steps necessary to get the two to play nicely. Please comment with clarifications or corrections!

WebWork 1.x (these are assumptions based on the 1.x documentation mentioned above)
It seems that the way you got Spring to initialize WebWork 1.x action classes was to add this line into your webwork.properties file:

webwork.action.factory=webwork.action.factory.SpringActionFactory

so that WebWork would know to use Spring’s view of the world to create actions. The WebWork action classes would then need to be declared in the Spring applicationContext.xml file so that Spring would know directly of the action objects. Upon invocation of an action, WebWork would know to first use the SpringActionFactory to try and create an instance of the requested action which would ask Spring to create the object using its configuration. If there was no Spring definition of that action object, then WebWork would use it’s normal instantiation methods to create that action. Well, things have changed slightly since WebWork 1.x.

WebWork 2 In WebWork 2 (the functionality actually exists in XWork), you specify relationships from action classes to other objects in XWork’s xwork.xml file instead of Spring’s applicationContext.xml file. So if you have an action class that utilizes a DAO, instead of having a bean definition like so in applicationContext.xml:

<bean id="myAction" class="com.ryandaigle.web.actions.MyAction" 
singleton="false">
  <property name="DAO">
    <ref bean="myDAO"/>
  </property>
</bean>
<bean id="myDAO" class="com.ryandaigle.persistence.MyDAO" 
singleton="true" />

you move the action definition to xwork.xml and keep the DAO definition in applicationContext.xml so that xwork.xml looks like:

<action name="myAction" 
class="com.ryandaigle.web.actions.MyAction">
  <external-ref name="DAO">myDAO</external-ref>
  <result name="success" type="dispatcher">
    <param name="location">/success.jsp</param>
  </result>
</action>

and applicationContext.xml looks like:

<bean id="myDAO" class="com.ryandaigle.persistence.MyDAO" 
singleton="true" />

Notice how there is the external-ref element in the action definition that points to an object that Spring is managing. There are several things that need to be in place for the external-ref to work, but I just wanted to give an overview of what has changed before going into the specific steps.

Steps for Configuring Spring/WebWork (XWork) Integration:

  1. Get the files you need to externally resolve Spring beans. I’ve bundled them all here. They were originally spread between two JIRA issues filed against XWork 1.0 (see references below). This zip includes the source, the class files (so you can just include it in your classpath) and my example configuration files. Either extract the source files into your application, or put the file onto your classpath. (You may want to take the applicationContext.xml and xwork.xml files out, I don’t know if they’ll override your files… They’re just there as an example configuration).
  2. Now, let’s get your XWork configuration file (xwork.xml) to resolve external references. XWork resolves external references (using the external-ref element) by utilizing an external reference resolver per package. You specify your external reference resolver as an attribute of the package element:
    <package name="default" extends="webwork-default" 
    externalReferenceResolver=
    "com.atlassian.xwork.ext.SpringServletContextReferenceResolver">
    
    This SpringServletContextReferenceResolver class reference is a class not part of the XWork distribution written as an extensions for XWork/Spring that I got from this JIRA issue filed against XWork addressing this Spring integration effort. (I have bundled it with the rest of the necessary files later on down for your convenience). This class will intercept all external-refs and resolve the references using Spring’s context. There is also a SpringApplicationContextReferenceResolver included in the zip file that will allow you to resolve Spring references for applications not executing within the web context. But as this is a WebWork/Spring article, the servlet resolver is what we need to use.
  3. Now we need to add the XWork reference resolver as part of the interceptor stack you’re using. This will allow any references to be resolved (using the reference resolver you specified in the externalReferenceResolver attribute). This is how I’ve added that interceptor:
    <interceptors>
      <interceptor name="reference-resolver" class=
    "com.opensymphony.xwork.interceptor.ExternalReferencesInterceptor"/>
      <interceptor-stack name="myDefaultWebStack">
        <interceptor-ref name="defaultStack"/>
        <interceptor-ref name="reference-resolver"/>
      </interceptor-stack>
    </interceptors>
    <default-interceptor-ref name="myDefaultWebStack"/>
    
  4. As I briefly outlined before, you can now reference Spring beans that your action classes need in xwork.xml:
    <action name="myAction" 
    class="com.ryandaigle.web.actions.MyAction">
      <external-ref name="DAO">myDAO</external-ref>
      <result name="success" type="dispatcher">
        <param name="location">/success.jsp</param>
      </result>
    </action>
    
    And that’s all we have to do to xwork.xml to let XWork know how to resolve references to Spring’s managed beans.
  5. Now let’s setup our web environment to properly notify Spring and our external reference resolver of the web context. We do this by adding two context listeners to your application’s web.xml file:
    <listener>
    <listener-class>
    org.springframework.web.context.ContextLoaderListener
    </listener-class>
    </listener>
    <listener>
    <listener-class>
    com.atlassian.xwork.ext.ResolverSetupServletContextListener
    </listener-class>
    </listener>
    
    The first listener is Spring’s that you would need independent of whether or not you were integrating with WebWork 2. The second listener is our external resolver’s that will use the servlet context to retrieve Spring’s application context. This is the link between WebWork and Spring.
  6. At this point, we’ve set up Spring and our XWork reference resolver to work within a web context, and we’ve told XWork how to resolve external references to Spring. We’re done! Fire it up and let me know if there are some steps I’ve missed or assumptions I’ve made that I shouldn’t have.

References
- Here is my bundled source, class and example configuration files (that contains all the needed referenced files below); webwork2-spring.jar
- My searching started with the original WebWork 1.x + Spring documentation and comments on the Wiki; http://wiki.opensymphony.com/comments/Spring+Framework+Integration
- The Wiki pointed me to the two JIRA issues that contained the source files for the reference resolvers:

Credits
Judging by the comments etc… of the JIRA issues filed against XWork, it appears that Ross Mason (of Atlassian?) is the man to thank for the external reference resolver code. And of course we have to thank the people of Spring and WebWork 2 for making this all possible.

Please let me know if I’ve missed anything.

XML document design; When to use attributes vs. elements

Posted by ryan
at 1:39 PM on Thursday, March 04, 2004



My development team is in the process of designing some XML documents for use as a local file persistence format. The question has come up of when to use attributes vs. when to use elements.

I am of the following opinion:

  • Use attributes to represent singular, primitive data. For instance, the id of a user, the name of a user, the dob of a user would all be attributes because they are, well, attributes of the user.
  • Use child-elements to represent collections of items or complex types. For instance, the address of a user or the dept. of a user would be represented as a child element.

For example, a user XML element should be structured as

<user id="1" firstName="Ryan" lastName="Daigle">
    <address street="xxx My Street" city="My City" />
</user>

And not:

<user>
    <id>1</id>
    <firstName>Ryan</firstName>
    <lastName>Daigle</lastName>
    <address>
        <street>xxx My Street</street>
        <city>My City</city>
    </address>
</user>

Upon looking at this, it seems a bit extreme. Would anybody contest these document structures or have their own set of guidelines for when to use attributes vs. elements?