Thursday, January 17, 2008

GUI Generator: Doco, doco, doco...

Gavin King (of Hibernate and Seam fame) once said "there's no such thing as an undocumented feature. If your users don't know about a feature, its a nonfeature".

With that in mind, I plan to spend the next few weeks working on as much documentation as I can for Metawidget, before I show it to anyone. I'm even going to pay some graphic artists to draw me an 'overview diagram' in the spirit of 'a picture is worth a thousand words'...

Tuesday, January 15, 2008

When the Eclipse P4WSAD plugin crashes...

Note to self: sometimes when Eclipse crashes (thankfully a pretty rare event), it will completely refuse to startup again because the Perforce P4WSAD plugin gets messed up.

The easiest way I have found to recover from this is to delete the folder:



Sunday, January 13, 2008

Concurrent MetaInspector

I spent today trying different ways of utilising concurrency within MetaInspector.

It's tempting because Inspectors are inherently threadsafe and immutable, so they can safely be run in parallel. There's a minor complication with having to make sure the order of merging is maintained, and I had to move some methods from private to protected static to allow access from a private static inner class, but otherwise it wasn't too bad (I mostly just used CyclicBarrier).

Then I noticed it didn't work.

It worked most of the time, but sometimes one or more Inspectors would fail. I tracked this down to not being the Inspector's fault, but the object that was being inspected: some of the getters in my JSF application use lazy-initialization, and some of them use FacesContext while doing so. FacesContext is a non-inheritable ThreadLocal, so isn't available to those Inspectors running on a different Thread.

So you can't just say to MetaInspector 'here are some Inspectors' and 'here's how many Threads to run them across'. Still, you can say 'here are some Inspectors and here are the groups I want you to run them in' and leave it up to the developer to specify which ones can safely run concurrently.

That does work.

However now the inspector-config.xml looks a bit weird. You don't have to use it if you don't want to, but I'm not sure this feature 'carries its own weight' enough to be part of the core API. You have this confusing interface with setInspectors and setConcurrentInspectors, and it may not be clear which ones run when:





There are other interesting approaches too, such as just using concurrency for the merging whilst letting the Inspectors run on the main Thread.

Still, in the interests of K.I.S.S., I'm leaving it all out. It just smells too much like premature optimization. Keen developers can still implement their own ConcurrentMetaInspector if they need to.

Tuesday, January 8, 2008

Hook, Line and Sinker

I've been making a conscious effort to pepper the Metawidget base classes with lots of subclass 'hooks' - to the point of making more fine-grained methods and classes than I usually would.

This is because I anticipate Metawidget being extended in an unusually large number of ways, by an unusally diverse range of third-parties. They'll be those who want to keep all the components but rework the layout, those who want to keep the layout but change the components, those who want to keep both the layout and the components but alter the validation etc. etc.

Thursday, January 3, 2008

Ask Your Father

Where possible, all Inspectors try and traverse their parent first to pick up any useful attributes such as @label. I tried having MetaInspector do this too.

It has the advantage that something like XmlInspector's metawidget-metadata.xml doesn't need to declare the whole path for cases like FooController/foo. It can just do...

<entity type="foo">

...rather than...

<entity type="FooController">
<property name="theFoo" type="foo">

<entity type="foo"/>

The problem is all Inspectors must act the same: I can't remove the parent lookup from all the other Inspectors, because they may be used independent of MetaInspector. Therefore, we have MetaInspector doing the parent lookup and then all the child Inspectors doing 'parent parent' lookups.

Also, having found the parent, traversing from the parent to the child generically is horribly inefficient, as the best we can do is create a DOM and look for its child. We cannot, say, use JavaBean calls to adjust the objToInspect.

Both of these problems can be worked around (at the expense of increasing the complexity of the Inspector API) by introducing a separate inspectParent method, and this has some interesting advantages.

For example when using manually overriden widgets, we don't want to inspect children - we only want to grab some parent details. But now we are looking at an Inspector API with both an inspectParent and an inspect method, where the latter inspects both the parent and the child. I feel this overlap would be confusing for Inspector implementors.

We could try inspectParent and inspectChildren methods, but then the normal case of inspecting both parent and children needs double the calls into the Inspector layer, and would have to return ill-formed chunks of inspection-result.xsd.

On balance, I've decided to keep the Inspector API simple (eg. just inspect) at the expense of a slightly more complicated metawidget-metadata.xml and slightly less efficient manually-specified widgets, because both of the latter cases are used much less frequently than the first.