mod_jserv
Les utilisateurs de Windows doivent télécharger le programme d’auto-installation sur http://java.apache.org/.
Téléchargez l’archive gzippée à partir de http://java.apache.org/ et décompactez-la dans un endroit approprié -- en ce qui nous concerne, nous l’avons placée dans /usr/src/mod_jserv.
Le fichier README indique :
Apache JServ est un moteur de servlets 100% en pur Java. Il implémente les spécifications de l’API 2.0 des servlets Java de Sun et ajoute la gestion de ces servlets au serveur HTTP Apache.
Pour que cette installation fonctionne, vous devez avoir installé :
Apache 1.3.9 ou une version supérieure.
Mais pas Apache 2, qui ne reconnaît pas mod_jserv.
Un environnement d’exécution (JRE) totalement compatible avec Java 1.1.
Nous avons décidé d’installer le kit de développement (JDK) complet car nous en aurons besoin plus tard pour Tomcat. Pour ce faire, nous avons téléchargé le JDK 1.1.8 à partir du site de FreeBSD ( ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/local-distfiles/nate/JDK1.1/jdk1.1.8_ ELF.V1999-11-9.tar.gz ).
Si vous aimez l’aventure, vous pouvez installer la version 1.2, qui est disponible à partir de la page http://www.freebsd.org/java/dists/12.html. Lorsque vous l’aurez téléchargée, consultez la section « Installation du JDK » pour savoir quoi faire ensuite. Si vous utilisez un système d’exploitation différent de ceux que nous citons, vous devrez trouver le paquetage convenant à ce système.
Le Java Servlet Development Kit (JSDK)
Vous trouverez sur http://java.sun.com/products/servlet/download.html l’éventail des versions disponibles. Comme à chaque fois avec Java règne une certaine confusion : les mots « Java Servlet Development Kit » ou « JDSK » sont difficiles à trouver sur cette page et, lorsqu’ils ont été localisés, ils semblent faire référence aux très anciennes versions plutôt qu’aux nouvelles, qui sont nommées « Java Servlet ». Cependant, nous avons eu le sentiment que les anciennes sont sûrement préférables dans le monde si changeant et si erratique de Java : nous avons donc téléchargé la version 2.0 à partir de la page http://java.sun.com/products/servlet/archive.html. Cette version contient à la fois le code Windows et « Unix (Solaris and others) », agrémenté de cette remarque rassurante : « La version pour Unix est indiquée comme étant pour Solaris mais ne contient aucun code spécifique à Solaris ». Le fichier tar comporte une extension .Z, qui indique qu’elle doit être décompactée à l’aide du programme uncompress d’Unix. Un JDSK est disponible pour FreeBSD : ftp://ftp.FreeBSD.org/pub/FreeBSD/branches/-current/ports/java/jsdk.tar.
Un compilateur Java
Si vous avez téléchargé l’environnement d’exécution au lieu du JDK, vous aurez également besoin d’un compilateur -- soit le javac de Sun (voir le site web déjà cité), soit le compilateur jikes d’IBM, qui est plus rapide ( http://www.alphaworks.ibm.com/tech/jikes ).
Un compilateur C ANSI
Si vous avez téléchargé les sources d’Apache et que vous avez réussi à les compiler, c’est que vous possédez ce compilateur. Il y a cependant un piège caché car mod_jserv n’appréciera pas d’être confié à un programme make trop ancien : vous devez avoir un « GNU make », téléchargeable à partir de ftp://ftp.gnu.org/gnu/make/. Voir la section suivante.
Compilation de gmake
mod_jserv nécessite GNU make, qui est incompatible avec tous les autres make connus. Vous devez donc l’installer et le compiler avant d’aller plus loin. Voici comment nous avons fait.
Comme vous avez sûrement déjà un programme make qui fonctionne parfaitement, vous ne souhaiterez probablement pas que le nouveau se substitue à lui : vous devrez donc le sauvegarder avant de commencer.
Créez, comme d’habitude, un répertoire pour les sources, décompactez-les dans celui-ci et compilez gmake (qui ne s’appelle heureusement pas make ) avec les commandes suivantes :
./configure --program-prefix=g
make
make install
Vous devriez obtenir /usr/local/bin/gmake.
Compilation de JServ
Après avoir installé gmake, placez-vous dans le répertoire des sources de mod_jserv. Avant de commencer, vous devez avoir compilé Apache pour que JServ puisse effectuer ses tests de configuration. Si vous avez suivi le déroulement de ce livre, vous avez déjà dû pratiquer cette opération une ou deux fois mais, dans le cas contraire, c’est maintenant l’occasion de le faire : retournez au chapitre 1.
Vous devez ensuite décider entre une intégration dans l’exécutable Apache (que nous conseillons) ou une préparation d’un DSO. Nous avons suivi la première et configuré mod_jserv de la façon suivante :
MAKE=/usr/local/bin/gmake ./configure --prefix=/usr/local --with-apache-src=
/usr/src/apache/apache_1.3.19 --with-jdk-home=/usr/src/java/jdk1.1.8
--with-JSDK=/usr/src/jsdk/JSDK2.0/lib
Vos chemins seront probablement différents. --prefix précise l’emplacement où vous souhaitez placer les composantes de JServ. Assez bizarrement, elles apparaîtront dans le sous-répertoire etc du répertoire préfixe. Vous pourriez également penser qu’il faut mettre /src à la fin du chemin d’Apache, mais ce n’est pas le cas. Si, pour une raison ou une autre, la compilation échoue, assurez-vous de supprimer le fichier config.cache avant de réessayer. Comme il est presque sûr que cela ne fonctionnera pas du premier coup, mettez les commandes nécessaires dans un script :
rm config.cache
MAKE=/usr/local/bin/gmake ./configure --prefix=/usr/local/bin --with-apache-
src=/usr/src/apache/apache_1.3.19 --with-jdk-home=/usr/src/java/jdk1.1.8
--with-JSDK=/usr/src/jsdk/JSDK2.0/lib > log
Si vous utilisez mod_ssl, ajoutez --enable-EAPI à la liste des options. configure produira de très nombreux messages dans le fichier log tandis que les messages d’erreurs apparaîtront à l’écran. Toute erreur du script est susceptible de produire des messages d’erreurs assez troublants : dans notre première tentative, par exemple, nous avions écrit --with-JDSK au lieu de --with-JSDK, ce qui a produit le message suivant :
checking JSDK ... configure: error: Does not exist:
'/usr/local/JSDK2.0
ce qui était justifié. Il nous a quand même fallu parcourir le fichier configure avant de réaliser que le script n’avait pas réussi à trouver --with-JDSK, ne l’avait pas signalé, puis s’était rendu à l’emplacement par défaut du JSDK.
Lorsque ./configure a effectué toutes ses opérations, il affiche un commentaire avisé sur ce qu’il faut faire ensuite. Le début disparaîtra probablement du haut de l’écran, mais vous pourrez le consulter à la fin du fichier log :
+-STEP 1-------------------------------------------------------------+
|Run 'make; make install' to make a .jar file, compile the C |
|code and copy the appropriate files to the appropriate |
|locations. |
+--------------------------------------------------------------------+
+-STEP 2-------------------------------------------------------------+
|Then cd /usr/src/apache/apache_1.3.19 and run 'make; make install' |
+--------------------------------------------------------------------+
+-STEP 3-------------------------------------------------------------+
|Put this line somewhere in Apache’s httpd.conf file: |
|Include /usr/src/jserv/ApacheJServ-1.1.2/etc/jserv.conf |
| |
|Then start Apache and try visiting the URL: |
|http://my586.my.domain:SERVER_PORT/servlets/Hello |
| |
|If that works then you have successfully setup Apache JServ. |
| |
|If that does not work then you should read the |
|troubleshooting notes referenced below. |
+--------------------------------------------------------------------+
+-Troubleshooting----------------------------------------------------+
|Html documentation is available in the docs directory. |
| |
|Common Errors: |
| Make sure that the log files can be written to by the |
| user your httpd is running as (ie: nobody). If there are |
| errors in your configuration, they will be logged there. |
| |
|Frequently asked questions are answered in the FAQ-O-Matic: |
| |
| http://java.apache.org/faq/ |
+--------------------------------------------------------------------+
Vous poursuiverez l’installation en faisant :
gmake
Puis :
gmake install
Placez-vous maintenant dans /usr/src/apache/apache_1.3.19 (ou le répertoire des sources d’Apache sur votre système) et n’allez pas dans le sous-répertoire src comme nous le faisions auparavant. Faites alors :
./configure --activate-module=src/modules/jserv/libjserv.a
make
make install
Lorsque nous l’avons fait, make a produit quelques messages d’avertissement. Cette fois-ci, les commentaires sont produits sur stderr. Vous pouvez les capturer en faisant :
make install &> log2
Ces commentaires se terminent par :
+-------------------------------------------------------------+
| You now have successfully built and installed the |
| Apache 1.3 HTTP server. To verify that Apache actually |
| works correctly you now should first check the |
| (initially created or preserved) configuration files |
| |
| /usr/local/etc/httpd/httpd.conf |
| |
| and then you should be able to immediately fire up |
| Apache the first time by running: |
| |
| /usr/local/sbin/apachectl start |
| |
|Thanks for using Apache. The Apache Group |
| http://www.apache.org/ |
+-------------------------------------------------------------+
Ce qui n’est pas très utile car :
- Le fichier de configuration est une variante de l’énorme fichier à tout faire d’Apache, que nous considérons comme source de confusion et dépassé.
- Le fichier de configuration ne dit rien sur JServ.
- Chez nous, la commande /usr/local/sbin/apachectl start n’a pas fonctionné car Apache a recherché le fichier de configuration au mauvais endroit.
À notre avis cependant, la compilation de l’exécutable est suffisamment difficile et on ne s’attend pas à ce que l’installation fonctionne aussi bien. Le nouveau fichier httpd se trouve dans .src. Placez-vous dans ce répertoire et vérifiez que tout s’est bien passé en faisant :
./httpd -l
Une référence à mod_jserv.c parmi le lot des « modules compilés » serait une bonne nouvelle. Attention : si vous oubliez le ./, il y a fort à parier que vous lancerez le httpd qui se trouve dans /usr/local/bin et qui ne sait sûrement absolument rien de JServ. Nous avons ensuite copié ce httpd sous le nom /usr/local/sbin/httpd_jserv.
Si vous en êtes là, vous pouvez tester que tout fonctionne en ajoutant cette ligne au fichier de configuration de site.jserv (une simple copie de site.simple ) -- assurez-vous que le chemin convienne à votre cas :
Include /usr/local/bin/etc/jserv.conf
Puis, lancez Apache (avec /usr/local/sbin/httpd_jserv ) et pointez votre navigateur sur http://www.butterthlies.com/servlets/Hello. Vous devriez voir quelque chose comme ça :
Example Apache JServ Servlet
Congratulations, ApacheJServ 1.1.2 is working!
Malheureusement, la Terre ne tourne pas de la même façon pour nous deux. La première tentative de Ben a échoué car le fichier jserv.conf qui lui avait été fourni n’était pas tout à fait correct. La solution a consisté à le copier dans notre propre fichier configuration puis à le modifier de façon appropriée. Le problème se matérialisait par le message suivant :
Syntax error on line 43 of /usr/local/jserv/etc/jserv.conf:
ApJServLogFile: file '/home/ben/www3/NONE/logs/mod_jserv.log' can’t be opened
Nous l’avons corrigé en mettant le chemin adéquat et Apache a bien voulu démarrer. Cependant, toute tentative d’accès à la servlet d’exemple provoquait une erreur interne d’Apache, indiquée par les messages suivants dans le fichier log des erreurs :
java.io.IOException: Directory not writable: //NONE/logs
at org.apache.java.io.LogWriter.<init>(LogWriter.java:287)
at org.apache.java.io.LogWriter.<init>(LogWriter.java:203)
at org.apache.jserv.JServLog.<init>(JServLog.java:92)
at org.apache.jserv.JServ.start(JServ.java:233)
at org.apache.jserv.JServ.main(JServ.java:158)
Nous avons alors constaté que le fichier /usr/local/jserv/etc/jserv.properties contenait la ligne suivante :
log.file=NONE/logs/jserv.log
probablement pour les mêmes raisons que le problème avec jserv.conf. Pour le corriger, nous avons pris notre propre copie du fichier des propriétés (qui est utilisé par la partie Java de JServ) et nous avons modifié le chemin. Pour utiliser ce nouveau fichier de propriétés, nous avons dû changer son emplacement dans notre fichier httpd.conf :
ApJServProperties /usr/local/jserv/etc/jserv.properties
Cela n’a quand même pas résolu nos problèmes. Cette fois-ci, l’erreur apparaissait dans le fichier jserv.log que nous venions de reconfigurer :
[28/04/2001 11:17:48:420 GMT] Error creating classloader for servlet zone root : java.lang.IllegalArgumentException: Repository //NONE/servlets doesn’t exist!
Cette erreur est liée à une zone de servlet, appelée root -- elle est définie par deux directives dans jserv.properties :
zones=root
root.properties=/usr/local/jserv/etc/zone.properties
Le fichier posant problème était donc maintenant zone.properties, que nous avons copié et corrigé après avoir changé son emplacement dans jserv.properties :
repositories=NONE/servlets
Nous avons changé ce chemin pour qu’il pointe vers le répertoire example des sources de JServ, qui contient un exemple de servlet précompilée :
repositories=/home/ben/software/unpacked/ApacheJServ-1.1.2/example
et, finalement, en allant sur http://votre.serveur/servlets/Hello, nous avons obtenu des « congratulations » bien méritées.
Directives de JServ
JServ a ses propres directives Apache, qui sont décrites dans le fichier jserv.conf.
Pour lancer JServ avec Win32, vous devez indiquer à Apache qu’il doit charger le module de communication JServ :
...
LoadModule jserv_module modules/ApacheModuleJServ.dll
...
Avec Unix, si JServ doit s’exécuter comme un objet partagé, indiquez à Apache de charger le module de communication JServ :
LoadModule jserv_module /usr/local/bin/libexec/mod_jserv.so
Il est conseillé d’utiliser la construction suivante pour encapsuler les directives JServ :
<IfModule mod_jserv.c>
ApJservManual
ApJServManual [on/off]
Valeur par défaut : off
Précise si Apache doit lancer ou non JServ ( On=manuel Off=automatique ). C’est assez trompeur car off signifie « lance JServ ». Cependant, comme il s’agit de la valeur par défault, vous pouvez ignorer le problème.
ApJServProperties
ApJServProperties fichier
Valeur par défaut : ./conf/jserv.properties
Indique le nom du fichier de propriétés pour Jserv en mode automatique. En mode manuel, cette directive est ignorée.
Exemple
ApJServProperties /usr/local/bin/etc/jserv.properties
ApJServLogFile
ApJServLogFile fichier
Valeur par défaut : ./logs/mod_jserv.log
Indique le nom du fichier log pour ce module. Le chemin est relatif au ServerRoot d’Apache. Pour éviter des confusions possibles, il est conseillé d’utilisez un chemin absolu. Ce fichier de log est différent de celui indiqué dans le fichier jserv.properties : il s’agit ici des logs de la partie C de JServ.
Avec Unix, le propriétaire du processus de la JVM doit avoir les droits d’écriture sur ce fichier. En d’autres termes, si vous lancez JServ en mode manuel et que Apache s’exécute sous le compte nobody, cet utilisateur doit pouvoir écrire dans ce fichier.
Si cette directive vaut DISABLED, les logs seront redirigés vers le fichier log des erreurs d’Apache.
Exemple
ApJServLogFile /usr/local/var/httpd/log/mod_jserv.log
ApJServLogLevel
ApJServLogLevel debug|info|notice|warn|error|crit|alert|emerg
Valeur par défaut : info (sauf si compilé avec JSERV_DEBUG,
auquel cas la valeur par défaut est debug)
Niveau des logs pour ce module.
Exemple
ApJServLogLevel notice
ApJServDefaultProtocol
ApJServDefaultProtocol nom
Valeur par défaut : ajpv12
Précise le protocole utilisé par cet hôte pour se connecter à JServ. Pour autant que nous le sachions, le protocole par défaut est le seul possible : vous pouvez donc ignorer cette directive. Il en existe une nouvelle version, mais elle ne fonctionne qu’avec mod_jk, que nous présenterons plus loin.
Exemple
ApJServDefaultProtocol ajpv12
ApJServDefaultHost
ApJServDefaultHost nom-hôte
Valeur par défaut : localhost
Précise l’hôte par défaut sur lequel s’exécute JServ.
Exemple
ApJServDefaultHost java.apache.org
ApJServDefaultPort
ApJServDefaultPort numéro-port
Valeur par défaut : dépend du protocole (8007 pour ajpv12)
Indique le port par défaut sur lequel JServ attend les connexions.
Exemple
ApJServDefaultPort 8007
ApJServVMTimeout
ApJServVMTimeout nombre-secondes
Valeur par défaut : 10
Précise la durée octroyée à la JVM pour démarrer, ainsi que la durée d’attente d’un ping vers la JVM pour vérifier qu’elle fonctionne. Les machines lentes ou fortement chargées peuvent avoir intérêt à augmenter cette valeur.
Exemple
ApJServVMTimeout 10
ApJServProtocolParameter
ApJServProtocolParameter protocole paramètre valeur
Valeur par défaut : aucune
Passe le paramètre et la valeur au protocole indiqué.
Actuellement, aucun protocole ne reconnaît cette directive, qui a été introduite pour des protocoles futurs.
ApJServSecretKey
ApJServSecretKey fichier
Valeur par défaut : ./conf/jserv.secret.key
Indique le fichier de la clé secrète de JServ. Le chemin est relatif au répertoire racine d’Apache.
Exemples
ApJServSecretKey /usr/local/bin/etc/jserv.secret.key
ApJServSecretKey DISABLED
ApJServMount
ApJServMount point-montage url-jserv
Valeur par défaut : aucune
Précise le point de montage des zones servlet (voir la documentation pour plus d’informations sur ces zones).
point-montage est le
nom du répertoire Apache dans lequel on souhaite monter url-jserv (qui est de la forme protocole://hôte:port/zone ). Si protocole, hôte
ou port ne sont pas spécifiés, ce
seront les valeurs des directives ApJServDefaultProtocol, ApJServDefaultHost ou ApJServDefaultPort qui seront utilisées. Si zone n’est pas spécifié, le nom de la zone
sera le premier sous-répertoire de la servlet appelée. Voici
quelques exemples :
ApJServMount /servlets /myServlets
Si l’utilisateur demande http://host/servlets/TestServlet, cela invoquera la servlet TestServlet de la zone myServlets sur l’hôte par défaut, via le protocole par défaut et sur le port par défaut.
ApJServMount /servlets ajpv12://localhost:8007
Si l’utilisateur demande http://host/servlets/myServlets/TestServlet, cela invoquera la servlet TestServlet de la zone myServlets.
ApJServMount /servlets ajpv12://jserv.mydomain.com:15643/myServlets
Si l’utilisateur demande http://host/servlets/TestServlet, cela invoquera la servlet TestServlet de la zone myServlets sur l’hôte jserv.mydomain.com, en utilisant le protocole ajpv12 sur le port 15643.
ApJServMountCopy
ApJServMountCopy on/off
Valeur par défaut : on
Précise si <VirtualHost> hérite ou non des points de montage de l’hôte de base.
Cette directive ne sert que lorsque l’on utilise des hôtes virtuels
Exemple
ApJServMountCopy on
ApJServAction
ApJServAction extension uri-servlet
Valeur par défaut : Aucune
Exécute une servlet en passant le nom de fichier avec l’extension indiquée dans la propriété PATH_TRANSLATED de la requête.
Cette directive est utilisée par les outils externes.
Exemples
ApJServAction .jsp /servlets/org.gjt.jsp.JSPServlet
ApJServAction .gsp /servlets/com.bitmechanic.gsp.GspServlet
ApJServAction .jhtml /servlets/org.apache. servlet.ssi.SSI
ApJServAction .xml /servlets/org.apache.cocoon.Cocoon
État de JServ
Activez le status handler de JServ avec l’URL http://nom-serveur/jserv/ (notez la barre de fraction finale !) et modifiez la directive deny pour restreindre l’accès à cette page d’état :
<Location /jserv/>
SetHandler jserv-status
order deny,allow
deny from all
allow from 127.0.0.1
</Location>
Dans un environnement en production, n’oubliez pas de désactiver ou de protéger l’exécution du status handler de JServ car il permet à des utilisateurs inconnus de prendre connaissance d’informations privées sur vos servlets et sur leurs paramètres d’initialisation, comme les mots de passe JDBC ou autres informations importantes. Ce handler ne doit être accessible que par les administrateurs du système.
Écriture d’une servlet
Maintenant que JServ fonctionne, ajoutons-lui une petite servlet, juste pour montrer comment faire. Il existe bien sûr déjà un exemple de servlet dans la distribution de JServ, la servlet Hello que nous avons mentionnée plus haut : son code source se trouvant dans le répertoire example, nous vous invitons à le consulter. Nous voulons écrire quelque chose d’un peu plus intéressant : la servlet Simple affiche les paramètres qui lui sont passés. Comme toujours avec Java, il faut écrire beaucoup de code pour réaliser cette opération :
import java.io.PrintWriter;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpUtils;
public class Simple extends HttpServlet
{
public void doGet(HttpServletRequest requête, HttpServletResponse réponse)
throws ServletException, IOException
{
PrintWriter out;
String qstring = requête.getQueryString();
Hashtable query;
if(qstring == null)
qstring="";
try
{
query = HttpUtils.parseQueryString(qstring);
}
catch(IllegalArgumentException e)
{
query = new Hashtable();
String tmp[] = new String[1];
tmp[0] = qstring;
query.put("requête incorrecte", tmp);
}
réponse.setContentType("text/html");
out=réponse.getWriter();
out.println("<HTML><HEAD><TITLE>Servlet Simple</TITLE></HEAD>");
out.println("<BODY>");
out.println("<H1>Servlet Simple</H1>");
for(Enumeration e = query.keys() ; e.hasMoreElements() ; )
{
String clé = (String)e.nextElement();
String valeurs[] = (String [])query.get(clé);
for(int n=0 ; n < valeurs.length ; ++n)
out.println("<B>" + clé + "[" + n + "]" + "=</B>" + valeurs[n]
+ "<BR>");
}
out.println("</BODY></HTML>");
out.close();
}
}
Pour compiler ce code, on a utilisé la commande suivante :
javac -classpath /home/ben/software/jars/jsdk-2.0.jar:/usr/local/jdk1.1.8/lib/classes.zip Simple.java
C’est-à-dire que nous avons fourni le chemin vers le JSDK et les classes de base du JDK. Tout ce qui reste à faire est d’activer la servlet -- le plus simple est d’ajouter le répertoire de Simple.java à la liste des répertoires de la zone root en modifiant le fichier zone.properties :
repositories=/home/ben/software/unpacked/ApacheJServ-1.1.2/example,/home/ben/work/suppose-apachebook/samples/servlet-simple
Nous avons ajouté le répertoire en le séparant par une virgule de celui qui y était déjà. Pour effectuer nos tests, nous avons été sur http://votre.serveur/servlets/Simple. Nous pouvons également ajouter des paramètres : ils seront alors affichés. Ainsi, http://votre.serveur/servlets/Simple?nom=Ben&nom=Peter&qqchose=autre affichera la page suivante :
Servlet Simple
qqchose[0]=autre
nom[0]=Ben
nom[1]=Peter
Si quelque chose se passe mal avec votre servlet, vous trouverez le message d’erreur et la trace de la pile des appels dans le fichier jserv.log.
Vous pouvez bien sûr créer une zone totalement neuve pour la nouvelle servlet, mais cela nous a semblé un peu disproportionné.