Matthias had a post on REST that gives a good background on what the options are for doing REST with JSF right now. As a quick, cross-cutting appraisal, it says a lot about the state of java right now: some talk in the 2.0 framework about tackling it, no specifics (read: 2020, if we're lucky), and then Ruby has a simplistic way to do it, and Seam already supports it, based on a standard (*JSR 311*). [Countless Java standoffs fall into this tripartite condition where officialdom is still a 5 year plan or two away (thanks Joe Stalin AND David Bowie), the new gee whiz, we can do anything by avoiding all protocol, convention, standard, and design discussion, and in the third spot, what looks like the sane condition, albeit, most of us cannot just drop into having Seam handle all our problems.]
But is the Seam version the ideal? This is one of the funny things about DI in general: shouldn‘t we be striving, as much as possible, toward something where the container can offer mostly prototypes whose sophistication is hidden in more generic factories? Anyone who has done a bunch of Spring knows, you end up defining a lot of DAOs or Repositories, injecting them all over creation, and mostly simple operations are performed on them to load state into beans that are useless without them. Kind of begs the question: what good is a bean container that issues items that are in a half-baked state.
Consider the case of reading a story from a news site. Most of the known universe would want to follow REST now and do something like
/joeblowsnews/story/19938, then have something parse that request and turn it into something that is requesting an entity of a given type (story), with a qualifier to help find it. We might even get sophisticated and have it try and handle multiple qualifiers, figure out which qualifier to use based on type, etc. But for this simplest case, ideally, what we would want is the bean container to just load the damned story bean so that we can just forward to the url and the story would appear.
How much work would that entail? Spring has the notion of using factory classes. The problem there is that now the domain model will suffer serious sprawl: for every loadable entity, there will be a corresponding Factory class. The Seam example here shows this as a ‘controller.‘ This does not fit my definition of a controller. It‘s loading stuff. It‘s a factory. For instance, suppose we have a StoryBeanFactory with a read method that takes a PK. The factory method takes in the key, has an injected Repository and it calls read on that.
I have said it before, I say it again: Prototype is the most underrated, under appreciated pattern in the Gang of Four catalog. Spring has made noble attempts to enhance the programmer's ability to regulate the infusion of state into items at the moment of creation A long time ago, when first people were starting to use objects, an antipattern popped up quickly: the object as just a temporary bucket that gets filled up, some procedure is invoked against/with it, then it gets thrown away. Isn‘t it sad how well this still defines our typical application approaches in lo 2009? Of course, so much of this boils down to scoping and conversations.
So to go back to the story. Here is how it should work:
- URL comes in conforming to some REST convention.
- An Interpreter is invoked and the little language (path) is converted into some normalized ui action. In our framework, we attempt to extract an entity type (Story), a qualifier (if 1, it is an ID) and a view type (often inferred, e.g., if it says nothing, just viewmode).
- Then the entity needs to be loaded. For this, we want the Factory I mentioned before, and we want to just pass the identifier.
- The request is redirected to the vew url.
- The view binds to a bean that references currentStory, which is defined as a prototype, with a factory method that references a StoryFactory.
- The Factory has a Repository (others might have other mechanisms for creation or rehydration). It turns around and loads the item from the Repo, using the identifier.
If the session included editing, we have a problem because we will need the bean in the controller after so it can be persisted. For this reason, though we are talking about Prototype, we are still going to have to scope this as a session bean. (I know, I know, or adopt Spring WebFlow..), and make the controller bean factory aware for now.
Ok, hammer nail here: this again looks like a good opportunity for code generation: to make the bean factories, especially when you consider the fact that if the object graph has subtypes in places, the factory can still load the bean, and when the facelet binds it, it will perform the appropriate downcast.