More on the wiki road map

Posted by    |      

I was traveling last week (see picture) when Gavin posted about the wiki road map and didn't have much time to elaborate.

What we actually call wiki is a small platform that we are building to run some of our websites, most notably the website you are looking at right now and the upcoming /seamframework.org/ community site. Gavin already explained why we are building this from scratch, the primary reason being that we want to build it on and with Seam.

For me it is also about learning how to write a real application with Seam and JSF. There are some unique and new challenges you have to face if you have the typical Struts-HttpSession-StatelessFacade-DAO background. We are chatting about this frequently and it's obvious that the introduction of new contexts and contextual wiring of components at runtime radically changes the programming model. This is a chat excerpt from yesterday:

Christian: there is some hope that it will all sort itself out with more patterns
Gavin: it takes time to develop the intuition about what is good to do
Gavin: remember the first time you wrote OO code :)
Christian: well the thing is, it's difficult to understand the state your system is in
Christian: which is now so much more important
Christian: and it's already a pain with imperative programming
Gavin: interesting thing to say
Gavin: i dont know what you mean
Gavin: you mean there is no central orchestration?
Christian: when you write code, you push the state of the system forward in little steps
Christian: and for every line you need to visualize in your head what it is now
Christian: which is with seam no longer limited to your current stack of operations
Christian: you need to think about the contexts as well
Gavin: don't you need to anyway?
Gavin: even if you don't have a proper model of these contexts
Gavin: thats what i always found....
Christian: hm
Christian: well, no
Christian: session is easy to do - even if it ends up being buggy
Christian: but page and conversation are a challenge if you add the JSF lifecycle as well

There are so many new ways of solving architectural problems that inevitably some of them turn out to be bad ideas in the long run while others work very nicely. This is also becoming an FAQ on the Seam forum, so we as a developer team need to provide more guidelines (and probably a pattern catalogue) for Seam users.

Seam as a project is now more than 2 years old, the first presentations Gavin was showing internally at JBoss - and I don't think many people understood what he wanted to say at the time :) - date back to a developer meeting in 2004. So the good news is that some of the more obvious design patterns are already emerging and that we just need to finish formalizing them. Others are still open for debate.

For example, the code running this website has about 130 classes and 50 TODO items. Most of the TODOs are not minor problems but go something like this:

    @Observer("Wiki.started")
    public void scanForSearchSupportComponents() {
        log.debug("initializing search registry");

        // Fire an event and let all listeners add to the given collection
        // TODO: Is this smarter than PreferenceRegistry scanning approach?
        Set<SearchSupport> searchSupportComponents = new HashSet<SearchSupport>();
        Events.instance().raiseEvent("Search.addSearchSupport", searchSupportComponents);

This scans the application space after deployment and startup and finds every component that wants to integrate with the full text indexing/search capability of the platform (based on the excellent Hibernate Search integration with Lucene). The way this is done is a registry that fires an event on startup and any component that wishes to register adds itself to the collection that is passed around as the event payload.

We need similar functionality for preferences, every component that brings its own set of customizable properties needs to be known. But there I used a completely different approach:

    @Observer("Wiki.started")
    public void scanForPreferenceComponents() {
        log.debug("initializing preference registry");

        // Register the meta model by scanning components with @Preference annotation
        String[] boundNames = Contexts.getApplicationContext().getNames();

        for (String boundName : boundNames) {
            if (boundName.endsWith(".component") && !boundName.startsWith("org.jboss.seam")) {
                Component component = (Component) Contexts.getApplicationContext().get(boundName);

                if (component.getBeanClass().getAnnotation(Preference.class) != null &&
                    !preferenceComponentsByName.containsKey(component.getName())) {

                    log.debug("Registering preference component: " + component.getName());

What happens here is that I get all the components from the application context (Seam registers component metadata there), find out which have a @Preference annotation, and then build my own metadata for the registry. I'd argue that the event/listener approach is more elegant. I think many applications need an application-level registry of metadata and it comes up regularly on the forums as well. So what is the pattern going to be and which variations are good and bad practice?

P.S. If you want to try out this application or just look at the code - beware, the example above should make it clear that it's not all very beautiful - here are some pointers: It's released under the LGPL and you can find it in the examples/wiki/ directory of the Seam 2.0 package. You can look at the source online or get it from Seam CVS. We have a separate JIRA component called Wiki for any bug or improvement reports.


Back to top