Thursday, November 26, 2009

Metawidget: King of the Hill


Nice article here (at least I assume it's nice, my German is even worse than Google Translate's):


My thanks to the author.

Wednesday, November 18, 2009

We're Hiring!

Here's the job ad we're posting today. A chance to work from home, and work for me! What a dream job :)


Senior Java EE 5 (J2EE) Developer: $90,000 - $100,000 AUD
  • Small, focused team

  • Modern, well-crafted software

  • Work in city or from home
A rare opportunity to join our small consultancy team. We have recently received substantial investment from a leading Australian financial institution and we must grow to meet demand.

You will work side-by-side with one of Australia's premier Java EE developers, and be intimately involved in all design decisions.

You will be a pragmatic programmer. Software development will be in your blood: a natural instinct. You must be passionate about Open Source and Java EE. You will demonstrate advanced analytical skills; an eye for elegance and craftmanship; a passion for refactoring, unit testing, and delivering secure and robust code.

Your skills will include many of the following:
  • JBoss

  • JSF/RichFaces

  • XSL (T and FO) and XPath

  • EJB 3/JMS

  • JPA/SQL

  • Metawidget

  • HtmlUnit

  • HTML/CSS
In addition, you will have excellent communication skills and be comfortable interacting with stakeholders at all levels.

Work from home will be offered providing that you can demonstrate an appropriate working environment. You must be a citizen or permanent resident of Australia.

To help us sort applicants, include your CV and a 1 page overview highlighting your suitability for the role. Links to examples of your work (eg. web sites you have built, blogs you have written, Open Source contributions etc) will be highly regarded.

Please send your application to jobs@kennardconsulting.com.

Wednesday, November 11, 2009

Safely manipulating the component tree with JSF 2

The information in this blog post has been superseded. Please see Safely manipulating the component tree with JSF 2, revisited

The Problem

A common problem encountered by writers of dynamic JSF 1.x components (like Metawidget) was "at what point in the lifecycle can I safely manipulate the component tree"?

For a page's initital GET request, there weren't many lifecycle methods you could hook into - you basically had encodeBegin. For subsequent POST-backs there were a slew of hooks, including decode, processValidators and processUpdates, but none were at exactly the right place in the lifecycle to do safe component tree manipulation. What would be 'exactly the right place'? Namely:
  1. the component tree should be fully realized (ie. all parents and children should be set)

  2. the component tree should not have been serialized yet
Because there was no 'official' place, writers of dynamic JSF 1.x components had to resort to all kinds of tricks. As Ken Paulson wrote "...people use constructors, bindings, action methods... people create their own renderer which dynamically adds children each request". To which Jacob Hookum opined "what's actually needed is post component tree creation hooks, providing the ability to then modify the component tree".


The Saviour

Enter JSF 2. From the spec "System Events are introduced in version 2 of the specification and represent specific points in time for a JSF application". They are like the old PhaseEvents, but much more fine-grained. For the purposes of this blog, the SystemEvent we are interested in is PostAddToViewEvent.

To use it, first subscribe to the event in your UIComponent's constructor...

public class UITestComponent
   extends UIComponentBase
   implements SystemEventListener {

   public UITestComponent() {
      FacesContext ctx = FacesContext.getCurrentInstance();
      ctx.getViewRoot().subscribeToViewEvent(PostAddToViewEvent.class, this);
   }

...then, when it gets fired, you can safely manipulate the component tree ...

public void processEvent( SystemEvent event ) throws AbortProcessingException {

   FacesContext ctx = FacesContext.getCurrentInstance();
   UIComponent dynamicallyGenerated = ctx.getApplication().createComponent( "javax.faces.HtmlInputText" );
   getChildren().add( dynamicallyGenerated );
}


The Gotchas

While working through this solution, there were a number of gotchas I encountered. Huge thanks to Ryan Lubke for holding my hand through them:

First, you should use subscribeToViewEvent, not subscribeToEvent. The latter will mean the event subscription itself get serialized into the component tree, so you'll keep doubling up subscribers every time the page refreshes.

Second, you must hook into UIViewRoot's PostAddToViewEvent, not UITestComponent's. This is because, at the time UITestComponent's PostAddToViewEvent is fired, its children will not be initialized yet.

Third, you cannot use the @ListenerFor annotation to hook into SystemEvents from a UIComponent. This is because UIComponent implements ComponentSystemEventListener, and @ListenerFor is designed to ignore the SystemEventListener interface for any class that implements ComponentSystemEventListener.


The Ugly

There is, unfortunately, still a problem for certain types of dynamic component.

If your component, in its processEvent method, dynamically creates not just simple HtmlInputText components but nested components that are themselves dynamic, we have a problem. This is because the 'official' way to safely manipulate the component tree is through SystemEvents, but there is no official way to safely manipulate the SystemEvent list.

In the current release of the JSF Reference Implementation (2.0.1), attempting to dynamically create a component that in turn tries to subscribe to a SystemEvent will get you a ConcurrentModificationException. In future releases, there will not be an exception but the newly added SystemEvent will simply not fire, so your newly added dynamic component will never get an opportunity to populate itself.

This new issue is being tracked by the JSF RI team. Until it is resolved, JSF 2 can safely create dynamic components (a big step forward), but it cannot safely create dynamic components that themselves create dynamic components.

Suggestions welcome!