Anais Nin once said that we don’t see things as they are; we see them as we are.
I’ve always found that an interesting idea to keep in mind, and I mention it now because I’m bubbling over with enthusiasm because of how much I enjoyed Gavin’s presentation. He said a lot of things that really resonate with me because they seem related to ideas that I’ve passionately defended a lot.
I want to think that my enthusiasm for what Gavin has said is based on the genuine agreement with his statements, rather than me superimposing my beliefs on what he said. I want to believe that I’m seeing Gavin’s statements for what they are, rather than for what I am. But who knows. I’ll try to fill out my thoughts here.
Gavin began the session with a demo in which he created a Seam application using some tools in the JBoss Eclipse IDE. He had a few tables, and using his tools he generated Hibernate bindings, EJB stuff and a whole, simple Seam application.
He then started up his app and showed how he could view, create and update records in his database.
I’ve seen this sort of demo many times: IBM, BEA and a variety of other vendors have tried to impress upon me how neat this stuff is. Gavin went the other way. He shrugged the demo off, saying that he thought that it kinda did what Ruby on Rails does, but that it’s probably not going to be what you use for a production app.
Never having heard of Seam before, at this point I wondered: is Seam just an answer to Ruby on Rails. For a moment, Gavin seemed to move on to other discussion points, and I was left with that question for a while.
He mentioned, quickly, that Seam made use of two technologies that he’s quite fond of. First: Java Server Faces (JSF). JSF is similar to, but a competitor of Tapestry.
Gavin told us that he didn’t expect to enjoy JSF, based on his reading of blogs and the like, but found himself pleasantly surprised. He also highly praised Facelets and implied that Seam owed a lot to that tool.
Gavin then jumped in to a lengthy discussion about EJB 3. His first point was one that resonated well with me. He went into an extended diatribe about the crazy attitude that people have about Stateful Session Beans in EJB. People will avoid Stateful Session Beans like the plague, based on a (he claims) ill-founded belief that the performance for them is a problem.
He put a lot of blame at the feet of WebSphere, saying that because their initial implementation of Stateful Session Beans is so bad, people have developed terrible programming habits to compensate.
This claim was central to a high-level theme that he developed: that state management in J2EE (or now “Java EE 5”) applications is poorly understood, and such applications are replete with a number of major problems:
- Multiple window web applications are generally broken — key quotation: “I can count on one hand the number of web applications I’ve use that could do what operating systems could do in 1981.” The root problem is that people use the HttpSession object to hold application state, rather than use Stateful Session Beans.
- That application validation logic is in the wrong place in an application — that this is properly a function of “business logic objects” (and hence, part of the model), rather than “presentation logic”. Most applications tend to stuff rules (even trivial rules such as “the description can’t be longer than 100 characters) into the presentation tier. I believe that’s wrong, and so does Gavin King.
- Because of the use of the HttpSession object, most web applications leak memory. Too many applications find it hard to demarcate the proper begins and ends of individual conversations, and so data just collects in the HttpSession until your application tips over.
- Finally, the notion of a “flow” is weakly defined. The application doesn’t really have any construct that properly models the “web flow” or even the “business process flow”. And that seems like an important failing in one the most significant parts of good object-oriented design.
I could probably go on at length about each of these points. I’ve had long arguments with other senior application designers and I’d almost hit the point where I’d come to believe that either:
- I was completely on the wrong track, and I needed to critically examine my thoughts; or
- I was “right”, in some crazy, architecturally pure sense, but that my rightness wasn’t meaningful on a practical level (and that I really should just learn to love the bomb and get on with life).
As a result, Gavin’s presentation was a huge breath of fresh air for me. Here was a celebrated Java expert saying the things that I’ve come to believe.
But, hey, I need to remember the Anais Nin quotation. Maybe I’m just superimposing my own biases on Gavin’s words.
At this point in the presentation, Gavin returned to his discussion of Seam and proposed the following objectives:
- simplify Java EE 5 by filling a gap (namely, the gap created by poor application state handling); and
- improve the usability of JSF
He further went on to suggest that Seam has the potential to bring business processes (and, specifically, jBPM) to the masses.
He also hoped that Seam would “deprecate so-called stateless architectures”. He argues that managed application state provides more robust, more performant and richer user experiences.
His session was full of great little diatribes. He complained, deeply, about the idea that so many applications write their state to databases (“the database is the least scalable part of the application.”), and then use complicated caching technologies to get around the performance problems that ensue when developers fail to address the original problem. “The original problem being,” he said, “that WebSphere didn’t have a very good implementation of stateful session beans.”
Here’s a concept that’s a little bit outside of my comfort zone, and which I’m rolling around in my head.
Gavin talked about using Hibernate Validator as a key tool for handling business rules. One would create an entity, as follows:
@Entity public Document @Id Long id; @Length(max=100) String title; @Length(max=1000) String summary; String content; // getters and setters }
The special annotations would define important rules (in this case, rules about the maximum length of the fields).
Seam is designed to use these validation rules to help implement front-end validation rules.
The reason that this is a bit outside of my comfort zone is that I still feel like this kind of validation is the responsibility of some kind of simple business process or business rule, rather than something that’s the responsibility of the entity. I can see benefits to what he’s done, here, but I need to mull it over in my head.
More on Business Processes
There were points in the presentation that I was interested in an in-depth conversation about how he defined various process-like things. I’m used to using a categorization of processes that looks like this:
- Command processes are very simple business process. Looking up my account balance is a simple command process. It lives in the context on one request, but it has its own rules (am I authorized? Should the request be logged? Am I charged money to see my account balance?)
- Tasks are more complicated business processes performed by one usef. They often span multiple screens of an application, and require a few interactions with the database (each in its own transaction). Booking a hotel is one such operation. Gavin seemed to use the term “Conversation” to describe this particular type of process.
- Workflow processes are the most complicated type of business processes, and are accomplished by multiple people, sometimes over spans of days or weeks. I think Gavin just calls these Processes.
Partially, Gavin’s use of terminology derives from jBPM, and I suspect that if I had greater familiarity with jBPM that I’d get his point better.
At one point, Gavin used this definition:
“A conversation that is significant in terms of the overarching business process is called a “task”
I need to roll that around in my head for a while, and figure out what it means.
The demos he gave were great. He showed us a wonderful “book a hotel room” application. Opened up two different browser windows, booked two different hotel rooms in a way that could often cause data mish-mash problems (y’know: “I’ll just stuff the hotel you’ve selected into the HttpSession”), and everything sang.
Then someone quipped up: “what happens if you use the back-button, now?” Gavin grinned, hit the back button and the application refused to return the user to a screen that represented the “middle” of a conversation. It was glorious.
Other “Outside My Comfort Zone” Moments
Gavin doesn’t seem to believe in the revolutionary-ness of dependency injection. He thinks that far too much chatter about dependency injection is going on , and he basically said that he can’t get a good sense of why dependency injection is supposed to be so cool.
He denies that dependency injection is easier to test (and I agree with him; it’s not easier to test — most people just don’t seem to be able to figure out MockInitialContexts). The only thing he views as relevent is that JNDI uses checked exceptions; he seems to feel that that’s the only thing that makes Registry-type lookups different than dependency injection.
I’ve really come to enjoy working with dependency injection containers, so Gavin’s comments are challenging to me.
So it was even more interesting when, moments later, Gavin dissed Spring. The reason for his dislike of Spring made sense in the context of everything else he’d said. He viewed that Spring is designed around the big stateless application model that Gavin disagrees with.
To be clearer about his objection, he suggested that when you get to the A-ha moment of stateful application systems, you get to a point where you can imagine dependencies changing over time, based on the state of a process or conversation. This, he felt, wasn’t something that Spring’s dependency injection could handle because it was based on the idea of a stateless system.
A key phrase he used was “contextual components” — the idea that components in stateful web applications need to live in some kind of context. He tried to clarify this by talking about a poorly-understood notion in Hibernate: the idea of persistence contexts (or “Contextual Sessions“, as it’s known in the Hibernate docs).
When you read a Hibernate object from the database, and want to hold on to it for a time period in which the user may try to update or change it, one often hits the problem of trying to perform your change in a different session from the one in which the object was originally read. In a stateful world, what one wants is some notion of a “persistence context” — a period around which the object is considered to be still connected to the database.
The solution, he claims, is a persistence context that has the same life as the conversation. This, he suggests, is even much better that the common open session in view pattern.
Interesting (and challenging) ideas.