These components are specific to the Tomcat implementation, and their primary purpose is to enable the various Tomcat containers to perform their tasks.
A valve is a processing element that can be placed within the processing path of each of Tomcat’s containers—engine, host, context, or a servlet wrapper. A Valve is added to a container using the
The Tomcat distribution comes with a number of pre-rolled valves. These include:
- A valve that logs specific elements of a request (such as the remote client’s IP address) to a log file or database
- A valve that lets you control access to a particular web application based on the remote client’s IP address or host name
- A valve that lets you log every request and response header
- A valve that lets you configure single sign-on access across multiple web applications on a specific virtual host
If these don’t meet your needs, you can write your own implementations of org.apache.catalina.Valve and place them into service.
A container does not hold references to individual valves. Instead, it holds a reference to a single entity known as the Pipeline, which represents a chain of valves associated with that container.
When a container is invoked to process a request, it delegates the processing to its associated pipeline.
The valves in a pipeline are arranged as a sequence, based on how they are defined within the server.xml file. The final valve in this sequence is known as the pipeline’s basic valve. This valve performs the task that embodies the core purpose of a given container.
Unlike individual valves, the pipeline is not an explicit element in server.xml, but instead is implicitly defined in terms of the sequence of valves that are associated with a given container.
Each Valve is aware of the next valve in the pipeline. After it performs its pre processing, it invokes the next Valve in the chain, and when the call returns, it performs its own post processing before returning.
This is very similar to what happens in filter chains within the servlet specification.
In this image, the engine’s configured valve(s) fire when an incoming request is received. An engine’s basic valve determines the destination host and delegates processing to that host. The destination host’s (www.host1.com) valves now fire in sequence. The host’s basic valve then determines the destination context (here, Context1) and delegates processing to it. The valves configured for Context1 now fire and processing is then delegated by the context’s basic valve to the appropriate wrapper, whose basic valve hands off processing to its wrapped servlet.
The response then returns over the same path in reverse.
A Valve becomes part of the Tomcat server’s implementation and provides a way for developers to inject custom code into the servlet container’s processing of a request. As a result, the class files for custom valves must be deployed to CATALINA_HOME/lib, rather than to the WEB-INF/classes of a deployed application.
As they are not part of the servlet specification, valves are non-portable elements of your enterprise application. Therefore, if you rely on a particular valve, you will need to find equivalent alternatives in a different application server.
It is important to note that valves are required to be very efficient in order not to introduce inordinate delays into the processing of a request.
Container managed security works by having the container handle the authentication and authorization aspects of an application.
Authentication is defined as the task of ensuring that the user is who she says she is, and authorization is the task of determining whether the user may perform some specific action within an application.
The advantage of container managed security is that security can be configured declaratively by the application’s deployer. That is, the assignment of passwords to users and the mapping of users to roles can all be done through configuration, which can then be applied across multiple web applications without any coding changes being required to those web applications.
Application Managed Security
The alternative is having the application manage security. In this case, your web application code is the sole arbiter of whether a user may access some specific functionality or resource within your application.
For Container managed security to work, you need to assemble the following components:
- Security constraints: Within your web application’s deployment descriptor, web.xml, you must identify the URL patterns for restricted resources, as well as the user roles that would be permitted to access these resources.
- Credential input mechanism: In the web.xml deployment descriptor, you specify how the container should prompt the user for authentication credentials. This is usually accomplished by showing the user a dialog that prompts the user for a user name and password, but can also be configured to use other mechanisms such as a custom login form.
- Realm: This is a data store that holds user names, passwords, and roles, against which the user-supplied credentials are checked. It can be a simple XML file, a table in a relational database that is accessed using the JDBC API, or a Lightweight Directory Access Protocol (LDAP) server that can be accessed through the JNDI API. A realm provides Tomcat with a consistent mechanism of accessing these disparate data sources.
All three of the above components are technically independent of each other. The power of container based security is that you can assemble your own security solution by mixing and matching selections from each of these groups.
Now, when a user requests a resource, Tomcat will check to see whether a security constraint exists for this resource. For a restricted resource, Tomcat will then automatically request the user for her credentials and will then check these credentials against the configured realm. Access to the resource will be allowed only if the user’s credentials are valid and if the user is a member of the role that is configured to access that resource.
This is a new element, available only since 6.0.11. It allows you to configure a shared thread pool that is available to all your connectors. This places an upper limit on the number of concurrent threads that may be started by your connectors. Note that this limit applies even if a particular connector has not used up all the threads configured for it.
Every major Tomcat component implements the org.apache.catalina.Lifecycle interface. This interface lets interested listeners to register with a component, to be notified of lifecycle events, such as the starting or stopping of that component.
A listener implements the org.apache.catalina.LifecycleListener interface and implements its lifecycleEvent() method, which takes a LifecycleEvent that represents the event that has occurred.
This gives you an opportunity to inject your own custom processing into Tomcat’s lifecycle.
Sessions allows ‘applications’ to be made possible over the stateless HTTP protocol. A session represents a conversation between a client and a server and is implemented by a javax.servlet.http.HttpSession instance that is stored on the server and is associated with a unique identifier that is passed back by the client on each interaction.
A new session is created on request and remains alive on the server either until it times out after a period of inactivity by its associated client, or until it is explicitly invalidated, for instance, by the client choosing to log out.
The above image shows a very simplistic view of the session mechanism within Tomcat.
An org.apache.catalina.Manager component is used by the Catalina engine to create, find, or invalidate sessions. This component is responsible for the sessions that are created for a context and their life cycles.
The default Manager implementation simply retains sessions in memory, but supports session survival across server restarts. It writes out all active sessions to disk when the server is stopped and will reload them into memory when the server is started up again.
The default Manager takes attributes such as the algorithm that is used to generate its session identifiers, the frequency in seconds with which the manager should check for expired sessions, the maximum number of active sessions supported, and the file in which the sessions should be stored.
Other implementations of Manager are provided that let you persist sessions to a durable data store such as a file or a JDBC database.