magpiebrain

Sam Newman's site, a Consultant at ThoughtWorks

Archive for ‘February, 2004’

I had some problems with this and found the documentation a little light on the ground, so I felt a little primer was in order.

So what is a proxy class?

Well, in Java terms a proxy class is a runtime-created class which acts like a class of a specified set of interfaces. “CGLIB”:http://cglib.sourceforge.net/ is capable of creating proxy classes without having interfaces – it can mimic a specific class.

Why would you want one?

In “Spring”:http://www.springframework.org (and other languages) proxy classes are used to allow the use of AOP interceptors. The proxy implementation calls the Interceptors before/after invoking the underlying object.

What is an Interceptor?

An Interceptor is a class which gets executed before, after, or around a method. By around we mean both before and after. Oh, and it can also be called when a method throws an exception.
Continue reading…

After looking for sometime at using XWork as a command driven framework for desktop clients, I decided to put that to one side for the moment to instead cooperate with “Keith Donald’s”:http://jroller.com/page/kdonald work on “Spring’s”:http://www.springframework.org/ Rich Client Platform (spring-rcp). As I mentioned before I was a little frustrated by XWork’s IoC framework – the fact that you had no control over how @Interceptor@, @Action@ or @Result@ objects were created. I started looking at the problem from the point of view of integrating Spring inside XWork, and ended up with the makings of a Command Framework completely implemented using Spring. The work’s very much at a prototype phase right now, and I’ll post more information as it comes together. I’m hopeful of getting it properly integrated with Keith’s first commits for spring-rcp, and as soon as I do I’ll post some example code.

After some badgering by “Simon”:http://www.brunningonline.net/simon/blog/, I’ve decided to start posting the occasional book review. As a voracious collector (and sometime reader) of books, I feel it is a duty to impart my knowledge on some matters, whilst at the same time whoring myself for a potential paid gig. Either that or to inflate my own sense of self importance, whatever.

Anyway, first up for treatment is Kent Beck’s “Test-Driven Development by Example(Test Driven Development – The Addison-Wesley Signature Series )”:http://www.amazon.co.uk/exec/obidos/ASIN/0321146530/qid=1077822818/sr=1-1/ref=sr_1_11_1/026-5985556-2226861. A rather slim tome in the context of computing books (which tend to value content over quality), it aims to describe the process of Test Driven Development (TDD for TLA fans) by a series of, you guessed it, examples. The first half shows the process being applied to solving a relatively straightforward use case. It succeeds well in managing to introduce the core processes of TDD, but at times the tone of false modesty Kent uses can really annoy me. I know enough of Kent Beck’s work to know that the guy cannot be as mediocre a programmer as he claims in the book, and for him to claim otherwise irks me somewhat.

The other problem the first section has is that in order to simply explain the TDD process, he has to use simple, small steps, which of themselves seem trivial and do not really help show some of the power of TDD. This can often be a problem with trying to describe computing technologies – by the time you’ve got an example simple enough to explain a technology, you’ve removed the need for using the technology in the first place.

Some of the early points are very well made however, this description being the single best argument for test cases I think I’ve ever seen:

In teaching TDD, I see this situation all the time – excellent software engineers spending 5 to 10 minutes reasoning about a question that the computer could answer in 15 seconds. Without the tests you have no choice, you have to reason. With the tests you can decide whether an experiment would answer the question faster. Sometimes you should just ask the computer.

At no stage during the first part is any guidance for setting up a TDD environment given. In addition, whilst JUnit is mentioned as the testing framework several times, no information is forthcoming as to how to run the tests yourself. This can be a bit frustrating to people who want to follow along with the examples from the beginning. This begins to be readdressed in the second part, where by way of a more advanced example, Kent decides to implement a JUnit type system using a TDD approach. In it you get a feel as to how JUnit works, but you still don’t actually know how to download, install and run it.

By choosing an advanced sample such as the implementation of a unit testing framework, Kent is clearly trying to kill two birds with one stone – describe JUnit and give a more advanced TDD example. He does of course make a rod for his own back – he is using the Unit testing framework he is creating (called xUnit) as the test framework itself. I’m sure many computer scientists get a hard-on for this self-referential coding but for my mind it needlessly complicates things.

Perhaps the most notable thing about this middle section of book is the change in programming language. The testing framework he develops is a written in Python. No doubt a boon for Python coders out there, this can’t but help make things a little awkward for those who picked the book up, saw the early sections are written in Java and thought this was the book for them. Likewise Python programmers may have some trouble understanding the Java examples in the initial sections, which would be required in order for them to follow the later Python code.

The real pay dirt for this book can be found in the final section. Here, Kent details a series of test patterns expanding on the early examples which give a fantastic overview of what you should test and how. For me, I found myself skipping much of the early stuff and focusing my attentions on these more complex topics, however I obviously lost out a little – I frequently found myself referring to the earlier chapters to better understand the topics being addressed.

Conclusion

All in all, Test-Driven Development can quite quickly explain to you what TDD is, and what its promises are. It does its best to extol its virtues, but I can’t help thinking that the only way to really be converted to TDD is to use it yourself. The lack of discussion on how to implement a TDD environment for yourself is disappointing, and the brief foray into Python confusing, however all in all this book is well worth a read for any of you interested in the topic.

I’ve looked over the initial work done to integrate “XWork with Spring(Support for resolving component References in external IoC containers such as Spring)”:http://jira.opensymphony.com/secure/ViewIssue.jspa?key=XW-122. That proposed solution just used Spring to resolve external components – an @ExternalReferenceResolver@ is used to provide named objects, and a Spring specific implementation is created to access and retrieve objects from Spring itself. Whilst this does solve some of the limitations of the current XWork form of IoC, this feels Ugly – you are taking an incredibly flexible IoC framework and using one little part of it, whilst keeping your own more limited framework. I would like to see the existing XWork API become a wrapper on top of Spring. By all means keep the existing XWork configuration format, but extend it to support Spring-like features. Use Springs Interceptor’s, its invocations – leverage all of Springs excellent existing code. Fair enough, XWork then just becomes a thin wrapper on top of Spring, but you’ll end up with a more flexible command-driven framework, which would in all likelihood find far more use outside of WebWork than is currently the case. Once done, you can then remove the need for @Interceptor@, @Action@ and @Result@ methods – Spring doesn’t need them.
Note that anything I say regarding Spring can equally be applied to another type 2 or 3 IoC container.

When you configure your XWork application (be-it WebWork or something else), you define your Action, Interceptors which intercept Action invocation, and Results, which get executed when an Action returns. You have complete control over the implementation of these classes – beyond the fact that you need to implement some basic interfaces (@Action@, @Interceptor@ and @Result@ respectively), however you have absolutely no control over how these classes get instantiated by XWork at runtime – internally XWork just gets your class, and calls @newInstance@. The limit of control you have over how Xwork sets these objects up is in the form of String/Value pairs defined in the configuration.

So why is this a problem? Well, lets take the example of my “Swing/XWork prototype(A GUI framework using XWork)”:http://www.magpiebrain.com/archives/000181.html I posted earlier. In it I created an Interceptor to monitor the progress of an Action. As the Action is invoked and completed, my Interceptor calls methods on a @ProgressRegister@ object. The problem is that I cannot pass references to my @ProgressRegister@ object into the interceptor when created – I am forced into creating a Singleton method accessor on @ProgressRegister@. In an ideal world, I would be able to define my @ProgressRegister@ object, and tell XWork that this object instance should be passed in whenever my interceptor is created:



...







This is of course exactly how IoC frameworks like Spring and Pico container work (the @bean@ definition from above is actually lifted straight from a Spring XML file). Ideally, XWork’s configuration could be overhauled to use Spring internally, but this is a big job. Instead I have a compromise.

Lets imagine an Interceptor class called @SpringInteceptorFactory@ which implements @Interceptor@. It takes a single string parameter which equates to the name of another Interceptor defined in a Spring config file. When invoked by XWork, @SpringInteceptorFactory@ creates an Interceptor of the relevant type (with properly wired dependencies) and executes it accordingly. This same solution could be used to create @Result@ or @Action@ objects. I can’t escape the feeling that adding yet another config file (in the shape of a Spring XML definition) is going to complicate things, however if you were already going to use Spring (Or Pico/NanoContainer) perhaps its not that much hassle after all.

Thanks to a “post(Swing Action Architecture)”:http://jroller.com/page/bhagvank/20040222#swing_action_architecture over at Bhagvan K’s blog, I found a link to an article covering an “action architecture for Swing(An Easy Architecture for Managing Actions)”:http://www.javadesktop.org/articles/actions/index.html. Of special interest to me is that fact that the code defines an XML format for storing action information:


It also defines groups of actions, for example for use on a menu:




      ...


My SwingCommandFactory needs to be able to load this kind of information – the id of the actions will probably resolve to the names of the XWork defined actions (I am unsure how/if to handle xwork namespaces as yet). Assuming the code is opensource, I might use the XML format and parsing code for my framework – although I’d like to combine this kind of configuration with xwork.xml, it will at least be a good stop gap solution.

I’ve been looking into this whole XWork + Swing thing a little more, and have come up with a fairly simplistic example of how a Swing+XWork framework might look. If you want to follow the code I suggest you read my brief “XWork tutorial(A Simple Xwork Example)”:http://www.magpiebrain.com/archives/000180.html. Anyway, my example shows a simple window with a button and a progress bar. When clicked, the button invokes an XWork Action on a thread. A ProgressInterceptor records when the action starts and ends, and changes the state of the onscreen progress bar as appropriate.

The Action has to be run on a seperate thread, as otherwise it will be invoked on the Event thread, blocking any GUI updates until the action has returned. This means that the return from Action‘s execute method cannot be handled – we have moved from synchronous action invocation to asynchronous action invocation. The ProgressInterceptor calls methods on aProgressRegister singleton to tell it when an Action has started or stopped. I dislike the use of a singleton, but right now it is impossible to pass objects into an Interceptor (this is a nasty constraint of XWork – I might see how easy it would be to use Spring to create Interceptors). A ProgressListener gets registered with the ProgressRegister, and updates a JProgressBar as required.

Its actually a lot simpler than it sounds – check the code for yourself to see. It represents an afternoon of work so is a little rough and ready – you’ve been warned! To run the program the main class is org.magpiebrain.example.TestProgram. The code requires webwork1.0, OSCore, OGNL and commons-logging to run, all of which are included in the zipfile. If I decide to take this much further I will look into supporting SWT, so suggestions as to how easy this would be are welcome. Note that the only GUI feedback from the action is by the progress bar at present – I need to think about the interaction between the result of the Action and its impact on the GUI a little more.