Last updated : 01/10/2002; 18:20:46

Joe's Jelly

Joe Walnes rambling on and on about Software Development, Java and Extreme Programming.

NAVIGATION >>

/WIKI /WEBLOG /THOUGHTWORKS /OPENSYMPHONY /EMAIL

:: ELSEWHERE
xp developer wiki
c2 xp wiki
the server side
javaworld
sd magazine
jakarta

:: BLOGS
Mike Cannon-Brookes
Graham Glass
Paul Hammant
Elliotte Rusty Harold
Darren Hobbs
Patrick Lightbody
Charles Miller
Brett Morgan
Rickard Öberg
Mike Roberts
Sam Ruby
Joel Spolsky
James Strachan
Clemens Vasters

:: INVOLVEMENTS
SiteMesh
QDox
MockDoclet
OSCore
OSUser
PropertySet
RichTags
Marathon
SiteMesh C++
Alt-RMI
Jelly MockTags
more...
:: BACKLOGS
September 2002
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30          
Aug   Oct



Click here to visit the Radio UserLand website.

:. 10 September 2002

  6:11:56 PM  

Happy birthday Rickard and Google. Seperated at birth?


  1:47:44 PM  

Essential Blogging

Essential Blogging, by O'Reilly. Grrrreat... :)


  1:41:13 PM  

 WebWrock!

I'm going to join in the game of talking about why WebWork rocks. Here’s my personal list of reasons (saving the best for last – no don’t look ahead yet).

Actions are not coupled to the web.

As already stated, an action implementation has no dependencies on the medium. Actions can be used for web-apps, distributed swing apps, SOAP services, EJBs, JMS actions, workflow engines, etc. Oh and actions don't necessarily have to be written in Java either.

Yes, I really have built an application (albeit proof of concept) that has a web front end and a .NET GUI front end that both use the same actions!

The power of commands.

The command pattern is pretty powerful. Entire actions can be serialized, transported over networks, persisted, etc. When building distributed systems a dispatcher could ensure that each action is executed on the most suitable server.

By extending Action to create UndoableAction, each action that is executed can be kept in a queue and undone if the user hits cancel at the end of their session. Actions can be decorated too... for example any action can be decorated with something that manages security or transactions in a declarative way (a la EJB).

Inversion of control.

As used in Avalon, actions have external context objects passed into them rather than looking them up. This means the container that hosts the object is responsible for passing in anything of interest. As an example, if your action cares about the user session, it implements SessionAware and has a setSession(Map) object. This will then automagically be passed in when the action is deployed and other containers (such as unit-tests) can pass in their preferred implementation. This typically leads to much cleaner and decoupled code. Okay, it doesn’t sound that exciting, but it makes a big difference when you’re coding.

Customization and extensibility.

The design of WebWork is incredibly simple and clean. Virtually all aspects of it can be overridden and extended.

For example, you could create your own interface such as ShoppingCartAware and have WebWork automatically pass in the current user’s shopping cart for any action that implements the interface (this is something I do frequently). Or you can create your own ActionFactory that dynamically loads actions from Jython scripts in a database (this is something I do not so frequently). Or you could implement your own error handling mecanism. Etc etc….

Test first

I saved the best for last. I can write user-interface actions test-first! Not just unit-test them, write them test first! Yes yes yes! Test first! (Okay, you get idea)…

Example story : To get to the download area, the user must enter a valid email address which will be added to our mailing list.

So, I write the tests:

public void testValidEmailAddress() {
  // setup mock.
  MockMailListManager mailListManager = new MockMailListManager();
  // expect mailListManager.addAddress("joe@truemesh.com") to be called.
  mailListManager.addExpectedAddAddressValues("joe@truemesh.com");
  // execute action
  EnterDownloadAction action = new EnterDownloadAction();
  action.setEmailAddress("joe@truemesh.com");
  action.setMailListManager(mailListManager);
  String result = action.execute();
  // verify results
  assertEquals("downloads", result);
  assertNull(action.getError());
  mailListManger.verify();
}
public void testInvalidEmailAddress() {
  // setup mock.
  MockMailListManager mailListManager = new MockMailListManager();
  // expect mailListManager.addAddress() to never be called.
  mailListManager.setExpectedAddAddressCalls(0);
  // execute action
  EnterDownloadAction action = new EnterDownloadAction();
  action.setEmailAddress("aaaaaabbbbbbINVALIDEMAILxxc");
  action.setMailListManager(mailListManager);
  String result = action.execute();
  // verify results
  assertEquals("error", result);
  assertEquals("No email address entered", action.getError());
  mailListManager.verify();
}

Obviously they don’t compile yet. Now I see I need to create a class called EnterDownloadAction with setEmailAddress(), setMailListManager() and getError() methods – so I do. (I already have a MailListAware interface which the action implements to ensure that WebWork will set the action at runtime). Because I’m passing the MailListManager into the action (inversion of control) rather than looking it up internally, I can pass in a MockMailListManager that will fail the test if its addAddress() member is called in the correct manner.

Now the test compiles – woohoo. Red bar! At least I’m testing something correctly.

Now I fill in the methods of the action and the bar goes green. And I’m happy. Well actually this happens in much smaller steps than this, but you get the idea.

Test first web-apps… once again… wooohooo!


  9:02:17 AM  

Velocity vs JSP..... have your gelatinous cake and eat it.

2 years ago, I swore by JSP for the view layer in web-apps. Although I always avoided scriptlets, I loooved using taglibs to neatly encapsulate functionality. Having tags for iterating, formatting, widgets, caching, layout and kitchen-sinks really appealed. But I ran across some downers too - certain expressions represented with tags got very complicated, WYSIWYG designers didn't cope with tags too well, tags aren't the most innovative things to write and it's very hard to use JSP outside the scope of web-apps.

Mike sent me an email about this time raving about his idea to extend JSP to allow tags to be written in JSP fragments as an alternative to implementing convoluted classes and descriptors. That would have been nice.

1 year ago, I changed my mind and moved over to Velocity. For reasons unexplained I went from hating the syntax to loving it (maybe it was because I was learning Ruby at the time). I realised that 98% of things I did on the view-layer fell into the category of writing a value out or flow control - Velocity is ideal for this. Things that didn't fall into that category either got moved out of the view layer or encapsulated into macros. Ahhh, the karma. But JSP tags are far more practical than Velocity macros. Ahhh, the dilemma.

0 years ago, I'm looking at hybrid approach to both of these - that word again .... Jelly.

Let's think about it:

  • Jelly is not coupled to any particular layer so it can be slotted in to the view-layer easily.
  • Velocity like expressions can be used to access values.
  • Tags can be defined be written as classes easily.
  • Tags can also be written using scripts of composite Jelly tags (Mike's suggestion).
  • There is already a huge library of useful tags available for Jelly.
  • Jelly can be unit-tested very thoroughly using JellyUnit and MockTags.
  • It doesn't use any funny syntax outside the scope of XML.
  • Because it's XML it can easily be pre/post-processed to provide additional functionality.
  • It solves all of my above problems.

So, if you're daring, give Jelly a go as your web view technology - it's the ideal hybrid of JSP and Velocity.

And yes, it is SiteMesh friendly on web-apps.... :)


Web-design by John Doe from open source web design.