Thanks to modern O-R mapping tools writing database-backed business applications became much easier. A lot of tedious code vanished, reading persistent entities from the database into main memory as well as writing back changes is about as easy as it can possibly get. The database is almost invisible - inserts, updates and deletes occur as side-effects of simple state-changes of in-memory objects. This facilitates the use of proper o-o design by pushing the SQL statements down (and out-of-sight) into some framework. Obviously, this is a good thing. Unfortunately, it comes at a price: Our shiny, pure-java domain objects are, almost invisibly to the innocent programmer, tied to the database state via some fairly complex machinery (the O-R-mapper).
After all, what ultimately matters in business application programming, is what your program does to the database (think of corporate policies restricting the programmer to use a fixed set of static SQL-statements only in an application). It is therefore essential to know exactly what you do to the DB when you call some method on your domain model. I will discuss this issue with special regard to web-applications and Hibernate as the O-R-mapper.
These 2 principles along with the general design of current O-R mappers like hibernate leads to the following basic pattern:
With regard to this basic pattern it is particularly noteworthy that:
A technically convenient while somewhat unrelated imposition is
A conversation is the lifetime of a working copy. The notion of conversations as something which can and should be independent of the usual web-application state-objects web-session and http-request came, as far as I know, up in the hibernate community (see http://hibernate.org/42.html).
Obviously most of the previous section's principles are about the correct implementation of conversations. A web-application sticking to these principles should support conversations as a scope of object lifetime with a longevity between a request's and a web-session's one.
Besides choosing the right longevity for a conversation, one has to decide on the cardinality of conversations. The JBoss Seam framework, for example, decides to let one user session have lots of active, concurrent conversations, spawned alongside with the user opening new windows or tabs of his web-browser. While this is technically impressive when compared to the rather rudimentary support for multi-windowed access to web-apps in other web-frameworks, I don't see a real need for it in most cases.
I'll conclude with refutations of some arguments which are often brought up against the previously sketched design.
The fact that a class can be compiled and instantiated using nothing but the standard Java SDK / runtime (that's what I take the term "POJO" to mean) does not imply that all of its behaviour is in its code, or more precisely in the code of the domain model which it is part of, combined with the specified Java runtime behaviour. Good O-R mappers like Hibernate (or even any of the more interesting recent Java frameworks will do all sorts of things to it, including replacing instances with instances of generated proxy classes, manipulating their byte code, adding technical state to their domain-specific state.
Dialog applications need state somewhere. With web-applications, you can choose to keep it
These considerations make the choice easy for typical intra-/extranet business applications. They usually involve complex logic and are used by a limited amount of concurrent users - who, when confronted with response-times above half a second tend to call for their old 3270 host terminals.
It's certainly a good thing to separate presentation logic from business logic. That does, however not imply that there has to be a "physical border" between them, so that domain objects must be treated like remote objects. That's rubbish from the very first days of EJB 1.x, which stays alarmingly popular - maybe due to the procedural style going with it - something which still appeals to a lot of people.