What flaws do you see in the following design, (and what would be your ideal architecture suggestion) for a typical web 3-tier application?
My current blueprint approach is very roughly this (assuming Java, Spring, Hibernate, JSP)
Controller
Stateless, potentially wrapped with a read only transaction (to avoid lazy init exceptions), get's entities from persistence storage via the service only, passes them to the view as the model. Conducts business logic on them (should the BL be in the service layer only?), passes back to the service layer for persistence if required.
Pros: For read-only transaction wrapping - only one connection, no redundant hits for the same persistent entity, utilizes query cache better, service layer shouldn't "know" request parameters, or required init graph span, avoid lazy init exceptions.
Cons: The read-only transaction approach can be risky, controllers are not the ideal Business Logic hanging place... very hard to do JUnits (your input is a request...)
View
Non transactional (access to non lazy collections / members will result in a lazy init exception)
Pros:
The view author shouldn't affect by mere dot notation the performance of the application (e.g. cause N+1 selects due to lazy initializing a large collection.
Also in disconnected clients (Flex, or other Rich Clients) lazy initialization remotely is either non supported, or just not a smart thing to do
Cons: the controller / service / DAO must prepare carefully the right graph of entities for the view, and may be overshooting (performance) / undershooting (lazy init exception). a myriad of server side methods can cause clutter as there is a Cartesian product to the number of permutations an entity graph can be initialized
Model
Using the persistent objects as is, (no data transfer objects), state is saved in the session.
Pros: no need to rewrite POJOs, reuse of existing entities, session state is more secure than hidden fields state handling.
Cons: Bad for disconnected frameworks, risk of saving stale disconnected objects, risk of locking issues, overriding other's data, requires optimistic locking sometimes.
Service
Transactional, doesn't know the request scope, calls a DAO layer for actual persistence storage access. this is where the BL should classically be, but it seems the BL leaks to the controller side over and over.
DAO
Contains atomic persistence storage facade, ignorant of the BL, or any context
Finally, the question:
What would you fix in the above architecture?
Do you think (like me) it is a quite common approach (with some minor differences, such as open session in view, etc)? Or is it the first time you see it and I'm doing something terribly wrong (or right)?
How do you solve it in your applications? Do you use your entity POJOs also for your model and view? or do you wire it up to simpler UI beans (all fully initialized and secure)?
This may be a subjective question, but I'm sure there are clear best practice design patters that cluster to one, two or three max general "religions".
Overall, it seems like a very good architecture. If you haven't already read it, I would recommend Martin Fowlers Patterns of Enterprise Application Architecture, which describe every subject in your question.
It is not clear from the question how large an issue you expect performance to be. In my experience, the performance bottlenecks are rarely where you think they are, and the sooner you find them, the easier it is to change the architecture to match.
You are right that testability is a major concern. I have used Martin Fowlers Passive View-pattern with some success. You should also take a look at Supervising Controller, from the same site.