Help

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.

5 comments:
 
25. Sep 2007, 21:01 CET | Link

I was having a similar thought yesterday as I was implementing my first conversation transaction design of a Seam app. I went looking in JBoss Seam: Simplicity and Power and saw there were two ways I could do it for my architecture--the manual flush and the one transaction per conversation. I couldn't really figure out why I would chose one over the other--except perhaps that the manual flush means you might see stale data outside the conversation. So then I tried searching through the Seam examples to see which approaches were used. And I pretty much didn't find either of them in use (much to my surprise--hopefully I didn't just miss it). Googling didn't turn up much either. Maybe that's not a great example, but I guess the bottom line is it's just going to take time for the community to learn the tradeoffs of the various approaches. Eventually there will be in the trenches knowledge available. With Seam, there always seems to be more than one way to do things. That's a good thing of course, but it makes it harder when you're getting started and you want to make informed choices.

BTW, thanks for the code sample on processing custom annotations on components--that might come in handy.

ReplyQuote
26. Sep 2007, 06:15 CET | Link

Clark,

What you are referring to are application transactions (or optimistic transactions). If you want details on how to use them, I strongly recommend that you check out the /Implementing conversations/ chapter of Java Persistence with Hibernate. I feel that the authors (the same guys that brought you Hibernate) do a great job of explaining the reason for the manual flush and why seeking to avoid transactional methods during an application transaction is an anti-pattern.

Unfortunately, the JPA spec does not support manual flushing, but the more people that are aware of the problem, the greater the chance it will get fixed.

Application transactions will also be covered in Seam in Action.

 
27. Sep 2007, 15:38 CET | Link

I've now committed some fixes to CVS and made it work with the new build Pete was writing about yesterday, so if anyone wants to try out the wiki software and deploy it: Get a Seam CVS checkout and build Seam with 'ant build'. Then go into /examples/wiki/ and and check the README.txt.

 
15. Nov 2007, 22:39 CET | Link

I also recommend the book /Java Persistence with Hibernate/, it is one of my favorite books on the topic.

 
28. Nov 2007, 10:01 CET | Link

Nice read. In addition to the book Java Persistence with Hibernate what else you guys recommend reading?

Post Comment