Unfortunately, Sun produced a set of blueprints, articles and interviews that caused an entire generation of enterprise developers to follow the false prophet of stateless architecture. That's hardly surprising, considering:
1) Applications have state.
2) If you can produce a segment of the application that is stateless, that simply means that you have delegated the state management to a subsequent segment.
3) For J2EE applications, that typically means that you have delegated the state management to a database.
4) For high-scale applications, that typically means that the database needs to run on a big box.
5) Sun sells big boxes.
Don't get me wrong: Stateless applications are easier to build, and if databases scaled linearly and big boxes didn't cost any more than small boxes, then stateless would be the way to go. (With a typical ecommerce site transactional mix, a 64-CPU server running Oracle may provide only five or ten times the transactional throughput of a 2-CPU Dell box running Microsoft SQL Server, but it could easily cost a thousand times as much.)
The problem is that stateless J2EE applications tend to create a SPOB (Single Point Of Bottleneck), they tend to scale poorly, they tend to perform poorly, and they tend to be terribly expensive to scale.
Combine that with the fact that J2EE took a large amount of business logic from the database tier and moved it "up to" the J2EE tier, adding the cost and latency of at least one external request to a database for every "business logic" operation. (Compare the performance of a complex PL/SQL stored procedure with the same logic implemented in Java using JDBC to grab and update data from the database. For kicks, repeat the same exercise with entity beans.)
Combine that with the use of the intranets and the web itself to provide many of these J2EE applications across an enterprise or even to the general public, and the user load on these systems can surge much higher than previous iterations of the same application.
There are only two choices:
1) Put the logic back into the database.
2) Move at least some of the state up into the J2EE tier.
We chose to support the second route by providing the means (Coherence) for J2EE applications to share and manage data in the J2EE tier, and since the scalability problem typically only shows up when you start to cluster the J2EE tier, we implemented the data sharing itself as a cluster.
The result of having some state available for use in the J2EE tier can be amazing. In one of our customers' applications, the average page time dropped from over 15 seconds down to 18 milliseconds (three orders of magnitude improvement -- without even using content caching!) and the database utilization dropped by well over 90%. Another (an ASP) hosts several thousand fully dynamic (and very stateful) web sites from a single cluster, and their database utilization per customer dropped by well over 90%.
Almost every J2EE application that I have seen that scales and/or performs poorly does so because it doesn't make efficient use of state in the J2EE tier.
Peace,
Cameron Purdy
Tangosol, Inc.Coherence: Shared Memories for J2EE Clusters