4. Configuration de Tomcat

4.1. Introduction

La configuration de Tomcat passe par l'édition du fichier server.xml qui se trouve dans le répertoire conf de l'installation. Ce fichier XML se découpe en différents éléments, qui correspondent à des notions propres à Tomcat, que nous allons voir une par une. Ces éléments XML se divisent en deux groupes. Le premier est constiué des éléments conteneur : Engine : Host et Context. Ces éléments s'imbriquent les uns dans les autres suivant des règles très précises, et sont obligatoires. Le second groupe est constitué d'éléments facultatifs et flottants, au sens où ils peuvent être placés dans les différents conteneurs : GlobalNamingResources, Resources, Realm et Valve.

4.2. Élément Server

L'unique élément racine Server modèlise un serveur Catalina dans sa totalité. Catalina est le nom du serveur proprement dit, alors que Tomcat est le nom du projet complet. Tout ce qui est défini dans cet élément est global au serveur, et sera donc appliqué, entre autres, à toutes les applications web qu'il supporte. Techniquement, un server est un élément XML, et une interface Java : org.apache.catalina.Server. Cet élément supporte trois attributs :
  • className : la classe d'implémentation de l'interface org.apache.catalina.Server. En principe on n'en change pas, et l'on peut omettre cet attribut, qui prendra alors sa valeur par défaut.
  • port : le port d'arrêt ( shutdown ) de Tomcat. Ce port ne correspond pas au port HTTP écouté par Tomcat, mais à un port sur lequel Tomcat reçoit la commande de s'arrêter. Lorsque l'on tape la commande shutdown sur l'invite de commande, cet ordre est émis, et Tomcat s'éteint alors.
  • shutdown : la commande envoyée sur ce port.
Seul l'attribut port est réellement susceptible d'être modifié. Cette modification est même nécessaire si l'on installe plusieurs Tomcat en même temps sur une même machine. L'élément server accepte trois type d'enfants : des Listener, un GlobalNamingResources et des Service

Exemple 2. Exemple d'élément Server

 <Server  port="9005"  shutdown="SHUTDOWN">

	 <!-- contenu de l'élément -->
	
 </Server>

4.3. Élément Service

Un service est un container dans lequel on peut trouver autant de sous-éléments Connector que l'on veut, et un unique sous-élément Engine. On peut définir autant de services que l'on veut au sein d'un serveur donné, à condition qu'ils diffèrent tous par leurs noms. Cet élément possède deux attributs :
  • className : nom de la classe Java qui implémente l'interface org.apache.catalina.Service. Peut être omis, dans ce cas l'implémentation par défaut est choisie.
  • name : nom logique de ce service, doit être unique au sein de tous les services définis dans un serveur.

Exemple 3. Exemple d'élément Service

 <Service  name="Catalina">

	 <!-- contenu de cet élément -->

 </Service>

4.4. Élément Connector

Un connecteur est un objet Java capable d'écouter un port précis et comprenant un protocole précis. À chaque protocole supporté par Tomcat est associé une classe Java de connecteur. Chaque connecteur dirige ensuite les requêtes qu'il reçoit au moteur de servlets défini dans ce service. Donc un moteur de servlet donné peut répondre à des requêtes en provenance de plusieurs ports, et suivant des protocoles différents. Quel que soit le connecteur choisi, un certain nombre d'attributs sont toujours disponibles :
  • port : le port que ce connecteur écoute.
  • enableLookups : autorise ou non les requêtes DNS lorsqu'une servlet invoque la méthode request.getRemoteHost(). Une requête DNS est un processus éventuellement coûteux. Si enableLookups est à false, alors request.getRemoteHost() retourne l'adresse IP plutôt que le nom de domaine associé.
  • maxPostSize : la taille maximale des requêtes POST supportée par ce serveur. La valeur par défaut est fixée à 2Mo. Une valeur de -1 signifie qu'il n'y a pas de limite.

4.4.1. Connecteur HTTP

Le connecteur HTTP supporte le standard HTTP/1.1, et permet à Tomcat de fonctionner comme un serveur web à part entière.
  • maxThreads : indique le nombre maximal de requêtes que ce connecteur peut traiter à la fois (une requête est traitée dans son propre thread par le connecteur HTTP). Au-delà de cette limite, les requêtes sont placées dans une file d'attente.
  • acceptCount : taille maximale de la file d'attente des requêtes. Si des requêtes supplémentaires arrivent, alors elles sont rejetées.
  • protocol : cet attribut peut prendre deux types de valeur, un nom de protocole, tel que HTTP/1.1, ou un nom de classe. Les trois classes supportées par défaut sont :
    • org.apache.coyote.http11.Http11Protocol : correspond au protocole HTTP/1.1 standard.
    • org.apache.coyote.http11.Http11NioProtocol : correspond au protocole HTTP construit sur l'API NIO.
    • org.apache.coyote.http11.Http11AprProtocol : correspond au protocole construit sur l'APR (Apache Portable Runtime, qui est la librairie runtime utilisée par Apache 2.2).

4.4.2. Connecteur AJP

Le connecteur AJP communique avec un autre serveur web, en utilisant le protocole AJP. Il existe deux connecteurs de ce type :
  • JK 1.2.* : permet de communiquer avec tous les serveurs web qui supportent le protocole JK ;
  • mod_proxy : permet de communiquer avec Apache 2.2.*.

Exemple 4. Exemple d'éléments Connector

 <!-- Port standard d'écoute de requêtes HTTP sur le port 8080 -->
 <Connector  port="8080"  protocol="HTTP/1.1" 
            connectionTimeout="20000" 
            maxThread="100"  maxCount="100"
            redirectPort="8443" />

 <!-- Port standard d'écoute de requête Apache AJP/1.3 sur le port 8009 -->
 <Connector  port="8009" 
            protocol="AJP/1.3" 
            redirectPort="8443" />

4.5. Élément Engine

L'élément Engine modélise le moteur de servlet proprement dit. À chaque serveur Catalina est associé un unique moteur de servlet, auquel on accède via des connecteurs. Un moteur peut comporter plusieurs sous-éléments Host, chacune représentant un hôte virtuel. Toutes les implémentations par défaut de cet élément supportent les attributs suivants :
  • name : le nom de ce moteur, notamment utilisé dans les fichiers journal ;
  • defaultHost : l'hôte virtuel par défaut vers lequel diriger cette requête.

Exemple 5. Exemple d'élément Engine

 <Engine  name="Catalina"  defaultHost="localhost">

	 <!-- contenu de l'élément Engine -->

 </Engine>

4.6. Élément Host

Cet élément modélise un hôte virtuel. Un hôte virtuel doit être associé à l'adresse IP de ce serveur, via un DNS ou un fichier hosts. Si l'attribut defaultHost du moteur dans lequel se trouve cet hôte est défini, alors au moins un des hôtes doit obligatoirement posséder ce nom. Toutes les implémentations de Host doivent supporter les attributs suivants :
  • name : le nom de cet hôte virtuel ;
  • appBase : l' application base pour cet hôte. Il s'agit du répertoire contenant les applications web pour cet hôte. Il peut s'agir d'un chemin absolu, ou d'un chemin relation au répertoire $CATALINA_BASE. La valeur par défaut de cet attribut est true.
  • autoDeploy : indique à Tomcat s'il doit charger automatiquement les applications web qui sont copiées dans le répertoire appBase. Le cas échéant, Tomcat scrute le contenu de ce répertoire à intervalles de temps réguliers, afin de détecter de nouveaux répertoires, ou de nouveaux fichiers .war.
  • deployOnStartup : indique à Tomcat s'il doit charger les applications web se trouvant dans appBase lors de son démarrage. La valeur par défaut de cet attribut est true.
L'implémentation par défaut supporte en plus les attributs suivants.
  • workDir : répertoire de travail propre à cet hôte. Par défaut, Catalina utilise un sous-répertoire de $CATALINA_BASE/work pour chaque hôte, mais il est possible d'en choisir un autre. On peut accéder à ce répertoire d'une servlet, via l'attribut d'application javax.servlet.context.tempdir.
  • unpackWARs : indique à Catalina qu'il doit exécuter les applications web de cet hôte dans un répertoire de travail avant de les exécuter. La valeur par défaut de cet attribut est true.
  • deployXML : indique à Catalina s'il peut ou non prendre en compte les fichiers /META-INF/context.xml des applications web. La valeur par défaut de cet attribut est true.

Exemple 6. Exemple d'élément Host

 <Host  name="localhost"   appBase="webapps"
       unpackWARs="true"  autoDeploy="true">

	 <!-- contenu de l'élément Host -->

 </Host>

4.7. Élément Context

Enfin, l'élément Context modélise une application web. Cet élément est un peu particulier, car il peut se trouver en plusieurs endroits. Historiquement (Tomcat v4), cet élément se trouvait nécessairement dans le fichier server.xml de Tomcat. Cette façon de faire posait deux problèmes :
  • toute modification d'un contexte pour une unique application web imposait de redémarrer l'ensemble du serveur Tomcat, puisque ce fichier est pris en compte au démarrage de Tomcat ;
  • ce fichier étant la propriété de l'administrateur de Tomcat, il y avait un problème de partage de droits, puisque ce sont les administrateurs des applications web qui connaissent le contenu de ces éléments.
Ce problème a été levé, et il est maintenant possible de placer cet élément dans un fichier context.xml rangé dans le répertoire META-INF de l'application. La prise en compte ou non de ce fichier à cet endroit peut être réglé par l'administrateur de Tomcat (attribut deployXML de l'élément Host). S'il choisit de ne pas prendre en compte ces fichiers, alors Tomcat ira chercher ce fichier ailleurs, dans un endroit contrôlé par l'administrateur. On peut définir autant d'éléments Context que l'on veut dans un hôte virtuel, avec une restriction :
  • chaque élément Context doit être associé à un unique attribut path, qui représente le chemin vers cette application web.
  • au moins un Context doit être associé à un chemin vide. C'est cette application qui servira toutes les requêtes non servies par les autres applications.

4.8. Élément GlobalNamingResources

Cet élément permet de configurer des ressources et des variables d'environnement, qui seront ensuite disponibles pour toutes les applications web gérées par cette instance de Tomcat. La distribution par défaut nous donne l'exemple de la base d'utilisateurs reconnue par cet instance de Tomcat. Voyons tout d'abord un exemple de définition d'une variable d'environnement.

Exemple 7. Exemple de variable d'environnement

 <Environment  name="maxRetry"  type="java.lang.Integer"  value="10"
              override="false"/>

Notons que l'attribut name, qui représente le nom de la variable créée, est relatif au context java:comp/env. Dans notre exemple, le nom JNDI complet de la variable sera donc java:comp/env/maxRetry. Examinons maintenant la ressource définie dans le server.xml par défaut.

Exemple 8. Exemple de Resources : UserDatabase

 <Resource  name="UserDatabase"  auth="Container"
           type="org.apache.catalina.UserDatabase"
           description="User database that can be updated and saved"
           factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
           pathname="conf/tomcat-users.xml" />

Toute ressource doit posséder un nom (attribut name) et un type, sous forme d'une classe Java. Cette ressource UserDatabase sera donc représentée par un objet de type UserDatabase, que Tomcat peut construire grâce à la classe factory MemoryUserDatabaseFactory. Cet objet a besoin du paramètre suivant pour s'initialiser : pathname, qui lui indique dans quel fichier les utilisateurs sont définis. On peut définir des ressources très diverses, les plus fréquentes sont les connexions aux bases de données, disponibles sous forme de DataSource, ou aux serveurs de mail.

Exemple 9. Exemple de Resources : serveur de mail

 <Resource  name="mail/Session"  auth="Container"
           type="javax.mail.Session"
           mail.smtp.host="localhost"/>

Nous verrons dans la suite comment il est possible d'accéder à ces ressources d'une application web.

4.9. Élément Realm

Un Realm est une notion qui appartient à l'environnement de sécurité de Java, défini par JAAS ( Java Authentification and Authroization Service ) pour la partie JSE et JCCA pour la partie JEE. Par définition, un Realm est un ensemble d'utilisateurs qui partagent la même méthode d'authentification. Techniquement pour Tomcat, un Realm est défini par cette méthode d'authentification. Comme il a été dit, un élément Realm est un élément qui peut être inclus dans plusieurs éléments conteneur du fichier conf/server.xml de Tomcat : Engine, Host ou Context. Un élément Realm inclus dans un élément parent est automatiquement hérité dans les éléments enfants. Ainsi, un Realm défini dans un Host (donc au niveau d'un hôte virtuel) sera automatiquement pris en compte par tous les Context (donc les applications web) de ce Host. Un élément Realm permet d'associer des droits d'utilisation aux application web. Un tel élément modélise une base d'utilisateurs et rôles, qu'il est ensuite possible d'utiliser pour restreindre l'utilisation de certaines applications. Tomcat propose plusieurs implémentations de Realm. Nous en avons déjà vu une : org.apache.catalina.realm.MemoryRealm, qui utilise le fichier tomcat-users.xml. Les autres implémentations permettent notamment de lire la liste des utilisateurs et des rôles dans des bases de données, qui elles-mêmes peuvent être administrées par ailleurs. Le choix d'une implémentation particulière se fait en fixant une valeur à l'attribut className de l'élément Realm. Examinons une de ces implémentations : org.apache.catalina.realm.JDBCRealm. Dans cette implémentation, les utilisateurs sont enregistrés dans une table. Tomcat a besoin de plusieurs informations pour y accéder :
  • la chaîne de connexion à la base de données, un nom d'utilisateur et un mot de passe ;
  • le nom de la table, et des différentes colonnes où se trouvent les informations dont il a besoin.
Voici un exemple d'un tel élément.

Exemple 10. Configuration d'un Realm JDBC

 <Realm  className="org.apache.catalina.realm.JDBCRealm"
        driverName="com.mysql.jdbc.Driver"
        connectionURL="jdbc:mysql:/db_user" 
        connectionName="admin_db" 
        connectionPassword="passwd"
        userTable="t_user"  userNameCol="user_name"  userCredCol="passwd"
        userRoleTable="t_role"  roleNameCol="role_name"
/>

On reconnaît sans problème les paramètres de connexion à la base parmi les attributs de cet élément. Viennent ensuite les paramètres de la table contenant les utilisateurs. Tomcat utilise deux colonnes : userNameCol porte les noms des utilisateurs, et userCredCol leurs mots de passe. Notons que par défaut les mots de passe sont stockés en clair, mais qu'il est possible de configurer ce Realm pour qu'ils soient cryptés. Enfin, viennent les paramètres de la table des rôles : userRoleTable porte le nom de cette table et userRoleTable le nom de la colonne qui contient les noms des rôles. Cette table doit aussi comporter une colonne userNameCol, qui réalise la jointure entre la table des utilisateurs et celle des rôles. Il existe également une implémentation de Realm capable de s'adresser à une DataSource directement : org.apache.catalina.realm.DataSourceRealm. La DataSource est obtenue par une requête JNDI dont le nom est donné en paramètre. Voyons un exemple.

Exemple 11. Configuration d'un Realm sur une DataSource

 <Realm  className="org.apache.catalina.realm.DataSourceRealm"
        dataSourceName="jdbc/UserDataSource"
        userTable="t_user"  userNameCol="user_name"  userCredCol="passwd"
        userRoleTable="t_role"  roleNameCol="role_name"
/>

Les attributs permettant de lire les tables d'utilisateurs et de rôles sont les mêmes que pour le Realm JDBC.

4.10. Élément Valve

De même que l'élément Realm, l'élément Valve peut se placer dans les conteneurs Engine, Host et Context. De même que pour le Realm, une valve définie au niveau d'un conteneur s'applique à ses sous-conteneurs. Une valve est un élément utilitaire, qui peut avoir différentes fonctions, qui s'insère dans le processus de traitement d'une requête, et realise un certain traitement. À chaque type de valve est associé un traitement particulier. Un élément Valve comporte toujours un attribut className, qui indique quelle implémentation de Valve est utilisée pour cet élément. Suivent ensuite une liste d'attributs propres à chaque implémentation. Voyons les principales implémentations de Valve :

4.10.1. Valve de journalisation

La valve de journalisation permet d'enregistrer des informations sur chaque requête, au même format que les serveurs web classiques (Apache notamment).

Exemple 12. Valve de journalisation

 <Valve  className="org.apache.catalina.valves.AccessLogValve"
        directory="logs"  prefix="fichier_log"  resolveHosts="false" 
        rotatable="true"  fileDateFormat="yyyy-MM-dd.HH"/>

On crée ici une valve de journalisation, qui enregistre ses informations dans des fichiers dont le préfixe est fichier_log, dans le répertoire $CATALINA_BASE/logs. Ce fichier subira une rotation toutes les heures, ce qui est fixé par la valeur de l'attribut yyyy-MM-dd.HH. L'attribut resolveHost décide si une requête DNS est faite afin d'enregistrer le nom d'hôte du client, ou juste son adresse IP.

4.10.2. Valve de filtrage par adresse IP ou par hôte

Ces valves permettent de refuser l'accès aux appplications web en fonction de l'adresse IP du client, ou en fonction de son nom d'hôte.

Exemple 13. Valve de filtrage par adresse IP

 <Valve  className="org.apache.catalina.valves.RemoteAddrValve"
        allow="192.168.1.*"  deny="192.168.0.*"/>

 <Valve  className="org.apache.catalina.valves.RemoteHostValve"
        allow="*.fr"  deny="*.com"/>

Dans les deux cas, la stratégie d'accès est la même. Si l'attribut allow est présent, alors la requête doit correspondre à sa valeur. S'il n'est pas présent, alors la requête est acceptée, sauf si elle correspond à la valeur de l'attribut deny. Dans tous les cas, une requête qui correspond à la valeur de l'attribut deny est rejetée. Notons enfin que l'attribut deny de RemoteHostValve est décodé en utilisant la expressions régulières Java (package java.util.regex).

4.10.3. Autres valves

Tomcat propose d'autres valves que celles présentées ici :
  • Une valve de débugage : la RequestDumperValve permet d'enregistrer dans un fichier l'intégralité des paramètres d'une requête HTTP. Elle ne doit être utilisée qu'en phase de mise au point d'une application, sous peine de saturer rapidement le disque dur.
  • Des valves de sécurité et d'authentification :
    • SingleSignOn : permet de s'authentifier sur plusieurs applications web d'un même hôte virtuel ;
    • BasicAuthenticator et DigestAuthenticator : permettent de forcer l'authentification HTTP basic ou digest pour l'accès à une application web.
    • FormAuthenticator et SSLAuthenticator : activent l'authentification par formulaire, en mode normal ou SSL.
Java servlet et JSP
Retour au blog Java le soir
Cours & Tutoriaux
Table des matières
Introduction
1. Position de l'API Servlet
2. Présentation
Présentation de Tomcat
1. Un peu d'histoire
2. Organisation des répertoires de Tomcat
2.1. Répertoire bin
2.2. Répertoire conf
2.3. Répertoire lib
2.4. Répertoire log
2.5. Répertoire temp
2.6. Répertoire webapp
2.7. Répertoire work
3. Lancement de Tomcat
3.1. Lancement par défaut
3.2. Accéder à l'administration de Tomcat
3.3. Plusieurs instances de Tomcat
4. Configuration de Tomcat
4.1. Introduction
4.2. Élément Server
4.3. Élément Service
4.4. Élément Connector
4.5. Élément Engine
4.6. Élément Host
4.7. Élément Context
4.8. Élément GlobalNamingResources
4.9. Élément Realm
4.10. Élément Valve
5. Définition et chargement des applications web
5.1. Introduction
5.2. Prise en compte des éléments Context
5.3. Chargement et mise à jour à chaud
6. Utilisation de Tomcat avec Apache
API Servlet
1. Introduction
2. Une première servlet
2.1. Le code
2.2. Création de l'application web
2.3. Déploiement dans Tomcat
3. Concepts, cycle de vie
3.1. Requête
3.2. Réponse
3.3. Session
3.4. Application web
3.5. Contexte d'exécution
3.6. Cycle de vie
3.7. Filtre
4. Présentation générale de l'API
4.1. Introduction
4.2. Interfaces disponibles
5. Notion de servlet
5.1. Interfaces servlet
5.2. Cycle de vie d'une servlet
5.3. Paramètres d'initialisation d'une servlet
6. Notion de requête
6.1. Accès aux paramètres d'une requête
6.2. Accès aux éléments de l'en-tête HTTP
6.3. Accès aux éléments de l'URL
6.4. Accès aux paramètres du client
6.5. Accès aux informations de sécurité
6.6. Accès à la session, au contexte et aux informations d'initialisation
7. Notion de réponse
7.1. Contrôle du buffer de sortie
7.2. Contrôle de la réponse HTTP
8. Notion de session HTTP
9. Redirection ou inclusion d'une ressource
10. Listeners
10.1. Introduction
10.2. Événements de l'API Servlet
10.3. Ajout ou retrait d'un attribut
10.4. Création et destruction d'un contexte
10.5. Notification d'un objet attaché à un contexte
10.6. Déclaration d'un listener dans une application web
11. Connexion à une base
11.1. Introduction
11.2. Connexion manuelle
11.3. Connexion par utilisation de source de données
Filtrage
1. Filtrage de servlets
2. Mise en place d'un filtre
2.1. Écriture d'un filtre
2.2. Déclaration du filtrage
3. Filtrage d'une requête
4. Filtrage d'une réponse
4.1. Fonctionnement de ce filtrage
Java Server Pages
1. Introduction
2. Un premier exemple
2.1. Une première JSP statique
2.2. Une première JSP dynamique
2.3. Fonctionnement interne des JSP
3. JSP scriplet
3.1. Les expressions
3.2. Les déclarations
3.3. Variables prédéfinies
3.4. Scriplet de directives
4. Utilisation de beans
4.1. Introduction
4.2. Déclaration d'un bean existant
4.3. Création d'un nouveau bean
4.4. Utilisation des propriétés d'un bean
5. Inclure un contenu externe dans une JSP
5.1. Introduction
5.2. Inclusion au lancement de l'application
5.3. Inclusion au traitement de la requête
6. Utilisation de bibliothèques de tags
6.1. Introduction
6.2. Bibliothèque core
7. Internationalisation
7.1. Notion de bundle
7.2. Internationalisation de pages JSP
Projet exemple
1. Présentation du projet