magpiebrain

Sam Newman's site, a Consultant at ThoughtWorks

Archive for ‘February, 2004’

I’ve been playing around with “XWork”:http://wiki.opensymphony.com/space/XWork a little today, attempting to work out how it all hangs together. I thought I’d share a simple XWork example I worked up as it should give you a simple introduction to the internals of XWork.

Scenario

We want to invoke a bit of code and return a result. We would like to provide transparent logging.

The Action

First, we define the action


public class ExampleAction implements Action {
    public String execute() {
        return "Done";
    }
}

The execute method will get invoked, and will return a value. We have to extend Action which I do not like, and we also throw exception form our exectue method which I dislike hugely, but understand the reasons for both.

The configuration

We define a config which declares our action, and defines the inteceptors we will use. “Interceptors”:http://wiki.opensymphony.com/space/Xwork+Interceptors are objects that get invoked before and after the action does. We are going to use two standard interceptors, one to log the action, the other to time it. We define an InterceptorStack which we can reuse – an InterceptorStack is simply a set of Interceptors that get invoked.











Now define our action and configure the use of the debugStack




Invoke the action

Very simple this:


try {
  ActionProxy proxy = factory.createActionProxy("default","TestAction", null);
  String result = proxy.execute();
  System.out.println("Calling action returns " + result);
} catch (Exception e) {
   //handle
}

For the future

I’m going to look at creating a Swing framework that uses XWork. I can already feel an UndoRegistrationInterceptor coming on…

[Updated 18:45 22-02-2004]: Jason Carreira pointed out that I don’t need to create an ActionInvocation from my proxy, I can exectue the Proxy directly. The code has been changed accordingly.

[Updated 19:31 22-02-2004]: Jason Carreira pointed out other bonehead mistakes – updated 🙂

[Updated 19:31 22-02-2004]: Code fix – thanks to Brian Buckley.

Advertisements

Thanks to a comment from Jason Carreira made on my “post(Thoughts on an MVC framework for Swing)”:http://www.magpiebrain.com/archives/000178.html, I was pointed in the direction of XWork. XWork is a view agnostic command pattern framework, originally developed as the core of “WebWork 2”:http://wiki.opensymphony.com/space/WebWork2.
XWork is a little different to my design – here actions are not the thing that does something, they signify the intention to do something. Additionally actions can be intercepted by Interceptors before being run.

Components are not fully de-coupled from the framework itself – when writing your own Action for example you have to subclass the Action interface. There is also no concept of a view as such within XWork – this is left to specific uses of XWork (such as WebWork). In general XWork seems close to my suggested design, but not as flexible. It would probably benefit from being reworked to use a more fully featured IoC engine internally (such as Spring or Pico) which would then allow coupling to the framework to be removed. That said its highly unlikely I would ever be able to develop something as fully featured as XWork on my own. I’ll have a play tonight and see whats involved in getting a simple Swing interface to use XWork – that will be a proper test of just how flexible it can be.

Rational

There are many MVC web frameworks, but as far as I can see there are very few MVC frameworks for Swing (I actually don’t know of any, but there might be some out there). Outlined here is the rough design for one. Please note that this is in the very early stages of design, no code exists for it, and I might not do anything with it. Comments are nonetheless appreciated.

The View

The view would be a GUI Interface. Each view would provide the data necessary to perform some action – it might be a simple ‘OK’ button, or it could be a full blown multi-tabbed interface.

Mapping to an action

Our views cannot themselves perform a submit to an associated action – they know nothing of the action itself. On their own, they are of little use. If we take the view that a view can map to only a single action at any time, we could pass in contextual information to the view to handle submits. Here, a MappingContext object encapsulates this particular form/action mapping.


public class ExampleView {
  private MappingContext _mappingContext;

  public ExampleView(MappingContext context) {
    _mappingContext = context;
  }

  ..

  public void submit()
  {
    _mappingContext.submit(this);
  }
}

The advantage of this is that we can put our submit code wherever we like. A disadvantage is that a view instance can only be coupled to one action at a time. I am unsure as to whether or not this is actually a problem or not. We are coupling to an interface here, introducing a dependency to the underlying framework. I don’t like this, but cannot think of a way out of this at the moment, other that using AOP to generate the submit method. Using AOP might work, but I am unsure how to support submission to different action classes Dependant on the current context of the view – some further reading on AOP might enlighten me.

As for actually getting the view to display, well that would be achieved using a little bit of proxy magic. We do not want to enforce that our implementation implements interfaces, or worse still that it needs to be a Component subclass. Instead, we just create a method to return a displayable object, and in our framework configuration we’ll tell the controller what method to invoke to get it.
The controller will do this by creating a “Dynamic Proxy object”:http://java.sun.com/j2se/1.3/docs/guide/reflection/proxy.html#examples to wrap our form.

The Action

Our action is responsible for processing a view input, performing something, and returning a result. Our action implementations do not need to implement any interfaces. The web application framework can detail which method should be the entry point for the action, or a default can be assumed. Above we called submit on our MappingContext . Behind the scenes we are invoking are creating a Dynamic Proxy object to wrap the action class and provide an interface suitable for our framework.
We could overload our entry point method in order to handle submits from several views:


public ExampleAction {
  public void submit(ExampleView view) {
    //handle view
  }

  public void submit(AnotherView view) {
   //do something else
  }
}

And this will be handled by the framework.

The controller

The controllers job is to read the configuration, and produce the View/Action instance mappings when requested. This is clearly a task for an IoC framework. Configuration could be a simple XML file:







The display attribute tells the controller which method it should call on the view to get the displayable component, and similarly submit details the method to call on the action to invoke it. Of course, sensible defaults could be used.

Had you noticed?

That none of this is actually bound to Swing? Or any display technology? The display method that you create on your view can return anything you like – you just have to be in a environment that can display it. For Swing, another framework would wrap this and assume that the Object is a Component. I have the feeling I’ve reinvented something else out there, or else this is useless. Feedback would be appreciated.

My posting has been somewhat infrequent of late, primarily due to time being spent job hunting. It actually went rather smoothly, however both of the jobs I was looking into had some rather rigorous application and interview procedures. Having successfully navigated both rather tortuous processes, I’ve made my choice and will be starting my new job by the end of March (don’t ask who – I ain’t going to tell). Hopefully between now and then I can knock some items off my todo list, such as:

* Site redesign (probably going to be less radical than I originally thought)
* Upgrade MT version and various plugins (Textile, MT-Blacklist)
* Research for future articles (one at the use of CSS+JSP, NanoContainer, perhaps IoC life-cycle)
* Finish my Fowler->Rest Of The World pattern dictionary (where our hero attempts to work out the mapping between Martin Fowler’s pattern names, and the names everyone else actually knows)
* Steam clean my carpets…

Well, you get the idea.

I’ve written an article giving a brief introduction on IoC for Java.net, and its been published today. For those of you already familiar with the concept it’s probably not terribly useful, but hopefully it’ll serve as a gentle introduction for those that have yet to look into it.

I’ve been semi-lurking of late on the PicoContainer’s developer mailing list, where much of the discussion has been over to the topic of the refactoring of the existing PicoContainer, PicoExtras and NanoContainer products. Given the nature of the list, the focus of the refactoring work has primarily been in order to make development and reuse of the products within other projects easier – quite often the topic of build dependencies gets mentioned. Given that I want to use PicoContainer/NanoContainer at work, it got me to thinking as to what I would need the projects to have in order for me to be able to use them. More generally, what do I need from any Opensource project in order for me to justify its use in a development project, be it Opensource or Commercial? On a post to the list, I summed this up as being able to say to my colleagues (be they fellow developers or management): “That’s what it is, here’s what it does, here’s how to use it and that’s why we are using it”.

That’s what it is

An Opensource project needs an identity. That is to say it needs a name, and something along the lines of (I’m going to hate myself for saying it) a mission statement:

Project Zebra aims to provide an Opensource, cutting edge monochrome solution to the ongoing shortage of food for lions.

It should also be available in a nice, downloadable package (or one or two at most). I want to be able to say “I just downloaded it, we have the Jars”, not “I started up SmartCVS and grabbed the most recent version”.

Here’s what it does

This should be more specific than a mission statement. I want a feature list, and perhaps even a nice comparison matrix if there are similar products available. If I can’t work this out from looking at your website for less than five minutes then why do you have one?

Project Zebra can:
* Merge into black and white foliage
* Look like a horse and yet not be able to be riden
* Provide either black zebras with white stripes, or white zebras with black stripes

Here’s how to use it

Probably the most important thing – good documentation and example programs. I may well be able to work out how to use project Zebra by looking at the code, but what about the developer sitting next to me who might have to fix my code when I’m on holiday? Having no documentation or examples might be fine for in-house development, but please be nice to your potential users.

That’s why we are using it

You need to be able to justify your use of project Zebra, and this can only be done if the previous questions can be answered. If your Opensource project cannot answer the above questions when asked of it, perhaps it should, or perhaps you should reconsider who exactly your target audience is.

Brad Choate has announced the latest version of “MT Textile”:http://www.bradchoate.com/mt-plugins/textile, which I use on this site for formatting my posts. The new version includes all kinds of new features, the support for footnotes and creation of search strings for Amazon, imdb and Google being of special interest to me.

I’ll be upgrading to this latest version when I finally get round to upgrading my MT install – but you lot don’t care as I don’t allow Textile formatting for comments 🙂