Session Management, Replication and load-balancing with sticky sessions
The HttpSession provided by Servlet specification is, for most cases, an ideal context for storing user state and data in memory. However, this context can only be obtained from the reference of the request object.
Suppose you want to push frequent updates to the user from the server-side, this context would not be available without access to the request object. If such data is stored in the database, for every user request, the database would have to be accessed to check for and retrieve updates, leading to severe loss of performance and scalability. The ideal place to store this data is in memory. In the absence of access to the user’s HTTP request, you would look for some other means to store this data – possibly a distributable and replicable cache such as JBossCache or Terracotta. Frameworks such as Hibernate can be configured to use such caches for second level caching. This somewhat limits the usefulness of sessions to store user related data in memory. Of course, they still have their usefulness with respect to transparent access to cookies.
But the point of this discussion is anyway not restricted to the usual browser-based thin HTML GUI web applications, but rather with respect to other special cases that we have enumerated earlier in the premise. In fact, web-services exposed for client applications using either SOAP or REST APIs are designed to be as idempotent and stateless as possible. So, in such applications, one would not need HttpSessions anyway.
If you need session identifiers just for tracking that the connected device or client has been authenticated before, this can also be achieved simply by using custom logic for creating and storing sessions in memory and even replicating them across the cluster. It is also fairly trivial for the client application to use URL-rewriting or URL parameter or embed the session identifier in the application protocol itself to use this session identifier. Or, one may use JBossCache and Terracotta for this purpose as well. For a simple use like this, a custom solution may offer more freedom and developer control than using HttpSession.
This brings us to the discussion of load-balancing with a web-server reverse proxy using sticky sessions. Most application servers and containers provide plug-ins for major web-servers like Apache HTTPD. With these plug-ins the web-servers can do a reverse-proxy for application servers or containers and in case of fronting an entire cluster, they can identify the correct backend server to stick the user to. However, by using Apache HTTPD’s mod_proxy and mod_proxy_balancer, one may easily achieve these objectives for any custom HTTP server or engine. I have successfully done so myself and would soon be posting an article for the same.
For the scenarios under discussion, JSP support is clearly not required.
Declarative security (by adhering to JAAS Security Standards)
Servlet containers provide adherence to Java Authentication and Authorization Service (JAAS) Security standards. This feature is undeniably extremely useful for web-site based applications. However, as a user of JAAS myself, I have found it very difficult to understand and extend, especially when I did not have the option of using ready-made Servlet container JAAS plug-ins. For example, I once had to authenticate and authorize users from an Oracle Internet Directory credential repository, for which I had to make a custom JAAS module. Configuring custom JAAS modules is not standardized across containers and can be quite non-trivial.
JAAS is not the only option. For example, one may use Spring security (formerly known as Acegi). Especially for the case when you do not have to extend the authentication and authorization for container resources like EJB or use it in JSP scripting with Servlet request API like isUserInRole(..) or getUserPrincipal(..), it is better to implement a simple and custom security module rather than overly complicating the whole thing just to adhere to standards. Besides, as discussed in the case of Communications, Multi-threading and Request-Response lifecycle, you cannot be absolutely aware of how the Servlet Container of your choice actually operates beneath the layers and for all you know, it could be sub-optimal for your scenario.
By definition, a container is one that would run the whole show- managing the life-cycle of your application and resources. It is the container that starts up and passes control to your application, not the other way round. While this helps in having a standard deployment and packaging contract for your application, it can be sometimes an unnecessary pain, especially for the scenarios enlisted in the premise. Containers may have elaborate steps to deploy and update applications and may take time to startup and shutdown due to the vast array of services that they have to gracefully start and stop. It is rather a welcome feature that some containers like Jetty or Tomcat can run as embedded engines, that is they can be started up by the application by using appropriate API.
There is one other aspect that becomes trivialized by the deployment contract of Application Servers and Containers. Typically Application Servers can deploy any number of web and other JavaEE applications within a single instance and all these applications can share the server resources. This is not necessarily a good thing because, after all, each instance is a single JVM or process and if it crashes, it can bring down all the applications hosted in it. Also, the applications need not always share the same application server resources and the sharing would in fact be detrimental, considering that, unless properly configured, all applications may be sharing the same thread-pool or JDBC connection pool and competing with each other for resources. These points are often overlooked and application developers forget that they have to plan how to deploy their components in different application server instances.
Standard HTTP request-response API
The Servlet Specification provides a standard API for HTTP server side applications, albeit with certain constraints and loss of freedom. If however, you choose to use a Server or Engine, they too would provide facilities to access HTTP headers, URL parameters, request body and so on. The lock-in to specific API has not been so much of a concern to users of Apache Commons HTTP Client, Spring, Hibernate, as long as the API suits the purpose to a T.