hibernatespringarchitectureweb-architecture

Web architecture: MVC, Lazy initialization, Data transfer Objects, Open Session In View, is there a consensus approach?


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:

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".


Solution

  • 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.