un autre petit tutorial en java

Programmation de servlets Java


Les servlets sont des programmes écrits en Java qui permettent de traiter et de répondre à des requètes passées la plupart du temps à un serveur web les abritant. Ils peuvent donc être utilisés pour traiter des données issues d’un formulaire au sein d’une page HTML, pour la génération de pages HTML dynamiques en y incluant par exemples des informations issues de base de données. Ils sont donc probablement une réponse pertinente à la croissante complexité des sites web, notamment ceux de commerce éléctronique.
Ce tutorial, loin d’être exhaustif, a pour objectif de présenter de la manière la plus claire possible les fonctions de bases mises à disposition par l’API Servlet.

 

Plan:

Installation
Architecture de base d’un servlet
Exemple: traitement de formulaires
Maintien de sessions
Cookies
Problèmes de threading
JDBC: Java DataBase Connectivity
Servlets et transformations XSLT avec Xalan-J
Un servlet évolué: Cocoon
Upload de fichiers

1 Installation

Les sections suivants supposent que le JDK de SUN, ainsi que Apache 1.2 et spérieur ont été préalablement installé.

1.1 Installation du Kit de Développement de Servlets : le JSDK

La première étape consiste à télécharger le JSDK2.0 sur le site de SUN (ici), le décompresser puis à copier (cp -R) le répertoire JSDK2.0 dans le répertoire de votre choix (on prendra /usr/lib/ pour la suite de ce tutorial). Il faut alors mettre à jour le path en incluant /usr/lib/JSDK2.0/bin (export PATH=/usr/lib/JSDK2.0/bin:$PATH), ainsi que le classpath en y ajoutant le chemin de l’archive jsdk.jar contenant les classes (export CLASSPATH = /usr/lib/JSDK2.0/lib/jsdk.jar :$CLASSPATH sous bash).
Pour vérifier que tout s’est bien déroulé, on lance l’utilitaire servletrunner qui devrait afficher les lignes suivantes :




olly%>servletrunner
servletrunner starting with settings:
port = 8080
backlog = 50
max handlers = 100
timeout = 5000
servlet dir = ./examples
document dir = ./examples
servlet propfile = ./examples/servlet.properties

servletrunner permet de tester les servlets, c’est à dire qu’il va faire office de mini-serveur, écoutant sur un port spécifique (8080 par défaut). Il est possible de modifier les paramètres par défaut de servletrunner, notamment les flags -d suivi du répertoire contenant les servlets, et -s suivi du fichier de propriétés de la zone à considérer.
 

1.2 Installation du module côté serveur : ApacheJserv

La première étape consiste à télécharger le moteur de servlets d’Apache, ApacheJServ, puis à décompresser l’archive quelque part sur le disque, sous /tmp par exemple. Il y a ensuite deux façons de procéder pour rajouter le module mod_jserv. La première consiste à recompiler complètement Apache après lui avoir ajouté le source de mod_jserv. La seconde nécessite une version d’Apache 1.3.*, avec support des Dynamic Shared Objects (DSO) et permet d’ajouter le module mod_jserv de manière dynamique, c’est à dire sans avoir à recompiler Apache. Pour des raisons de temps, seule la deuxième procédure, plus “moderne”,  est décrite ici.
Comme pour la plupart des packages fournis sous forme de code source, il est nécessaire dans un premier temps d’éxécuter le script de configuration avec configure. configure s’efforce de deviner le maximum de choses, et si l’ensemble des fichiers sont à leur place habituelle, tout se passeras parfaitement. Pour ma part, voici la ligne de commande que j’ai utilisé (avec succès sous SuSE) :

olly%>./configure -with-jsdk=/usr/lib/JSDK2.0/lib/jsdk.jar  -disable-debugging -with-apache-install=/usr

(La directive -with-apache-install=/usr est nécéssaire sous SuSE (mon cas) car configure croit que apxs est sous apache_dir/sbin/, alos qu’il  est en réalité sous /usr/sbin.)
Lors d’une seconde intallation sous Mandrake 7.0, la commande est devenue :

olly%>./configure –with-apxs=/usr/sbin/apxs –prefix=/usr/lib/jserv –with-jdk-home=/usr/lib/jdk1.2.2 –with-JSDK=/usr/lib/JSDK2.0/lib/jsdk.jar –disable-debugging –with-java-platform=2

olly%>make
olly%>make install
 

1.3 Configuration pour l’éxécution de servlets

L’environnement d’Apache JServ est divisé en zones, totalement indépendantes les unes des autres. Cela permet de séparer les servlets selon le possesseur, le mesures de sécurité désirées, ou encore les ressources allouées.  Toutefois, une unique zone suffit dans la plupart des utilisations.
Apache JServ possède un fichier de configuration nommé jserv.conf qui sert à définir son comportement au regard d’Apache. Le fichier de configuration d’Apache /etc/httpd/httpd.conf doit donc contenir une directive Include permettant d’inclure le fichier jserv.conf en son sein.

Exemple de ligne à inclure dans httpd.conf (après avoir copié le fichier jserv.conf à l’endroit indiqué):
Include /etc/httpd/jserv.conf

Le fichier jserv.conf contient à son tour une directive ApJServProperties /chemin/vers/jserv.properties pointant sur le fichier jserv.properties qui contient les propriétés des diférents servlets utilisés. jserv.properties permet entre autres choses de spécifier le nombre de zones souhaitées, le nom donné à chacune, ainsi que leur emplacement sur le disque.
Par exemple, si l’on souhaite deux zones nommées zone_a et zone_b, le fichier jserv.properties devra contenir les lignes suivantes :




# List of servlet zones Apache JServ manages
zone=zone_a, zone_b

Configuration : plusieurs zones. Chaque zone possède un fichier nom_zone.properties propre, dans lequel est entre autres indiqué le répertoire où trouver les servlets (repositories=/chemin/vers/classes).

Les zones disponibles doivent être indiquées dans le fichier jserv.properties. Les lignes zones=zone1, zone2, … et le chemin des fichiers de propriété leur correspondant : zone1.properties=/chemin/vers/zone1.properties, zone2.properties=/chemin/vers/zone2.properties, etc..

Une fois JServ configuré, il est nécessaire de relancer Apache, avec une des commandes suivantes: rcapache restart, apachectl restart ou bien kill -NOHUP `cat var/httpd.pid`.
 

2 Architecture de base d’un servlet

Avant de rentre dans les détails, examinons le code d’un servlet avec fonctionnalités minimale.

2.1 Exemple : Hello World!

Ce premier exemple de servlet effectue une tâche toute simple : il crée une page HTML intitulée “mon premier servlet”, laquelle affiche simplement “Salut tout le monde”.




import javax.servlet.*; //importe le package servlet
import javax.servlet.http.*; //importe servlet.http
import java.io.*; //importe les classes d’entrée-sortie
public class ExempleServlet extends HttpServlet { // ExempleServlet hérite de HttpServlet
    /* surcharge la méthode doGet */
    public void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out;
        response.setContentType(”text/html”);          // then write the data of the response
        out = response.getWriter();
        out.println(”<HTML>
                            <HEAD><TITLE> mon premier servlet </TITLE></HEAD>
                           <BODY><P>Salut tout le monde!</BODY></HTML>”);
        out.close();
    }
}

Ce servlet hérite donc de la classe HttpServlet, et surcharge la méthode doGet, cette dernière étant appelée lorsqu’un client envoie une requète GET au serveur.

Pour éxécuter ce servlet, il suffit de placer le code compilé (ExempleServlet.class) dans l’un des répertoires correspondant aux zones configurées, par exemple ~/example/ puis d’ouvrir avec un browser l’URL http://localhost/example/ExempleServlet.
 

2.2 Contenu du package javax.servlet

Le coeur du package est la classe Servlet de laquelle tout servlet doit obligatoirement hériter. Un servlet n’utilise pas nécéssairement le protocole HTTP , c’est pourquoi il existe une interface HttpServlet héritant de la classe Servlet. Tous les servlets utilisés avec ApacheJserv devront bien sur hériter de l’interface HttpServlet et surcharger certaines de ses méthodes, par exemple les méthodes doGet ou doPost
Le package Servlet contient également deux classes qui permettent l’interaction avec les clients du serveur web, les classes ServletRequest et ServletResponse. La classe ServletRequest fournit des informations concernant la requète parvenue au serveur, notamment les noms et valeurs des paramêtres passés, l’adresse IP du client, ls cookies et donne également accès via un stream aux données encapsulées dans le corps de requètes HTTP, notamment lors de l’envoi de données au serveur via une méthode POST. La classe ServletResponse fournit des méthodes permettant de répondre aux clients, par exemple une méthode permettant de fixer le type MIME de la réponse, ainsi que des streams via lesquels il est possible d’envoyer des données au client. Les classes HttpServletRequest et HttpServletResponse sont des interfaces qui étendent un peu plus les classes ServletRequest et ServletResponse en permettant l’accès aux caractèristiques spécifiques des headers HTTP.
 
 

  • classe HttpServletRequest

Un objet de cette classe permet d’accéder aux éléments du header HTTP de la requète, tels que les cookies envoyés avec la requète, le type de méthode utilisée, aisni que les noms de paramètres et leur valeur passés avec la requète. La méthode getHeader permet de récupérer tout ou partie du header de la requète HTTP. Par exemple:


String useragent = request.getHeader(\"user-agent\"); 
if (useragent.indexOf(\"Netscape\")) {
   /** instructions éxécutées si le navigateur client est Netscape **/
}



La méthode getParameter retourne une chaîne de caractères contenant la valeur du paramètre passé en argument. Par exemple:



String bookId = request.getParameter(”bookid”);


Cette instruction stocke dans la variable bookId la valeur du paramètre nommé bookid (getParameter renvoie NULL si le paramètre n’existe pas).
Il est également possible d’obtenir une chaine de caractères unique contenant l’ensemble des paramètres et valeurs grâce à la méthode getQueryString, et de la parser soi-même par la suite.
Lors d’une requète POST, on utilisera pour lire les données contenues dans le corps de la requète la méthode getReader, qui renvoie un BufferedReader (cas de données texte)  ou  la méthode getInputStream qui renvoie un ServletInputStream.(données binaires).
 

  • classe HttpServletResponse

La classe HttpServletResponse fournit deux méthodes permettant de renvoyer des données à l’utilisateur : la méthode getWriter, qui renvoie un objet Writer permet de renvoyer des données de type texte, par exemple le contenu d’une page HTML.  La méthode getOutputStream retourne un ServletOutputStream grâce auquel il est possible de faire parvenir des données binaires au client. Dans les deux cas, il est important de fermer le stream après utilisation afin que le serveur sache que la réponse est complète.

    2.2 Cycle de vie d’un servlet

  • Initialisation

Lorsqu’une requète cliente porte sur un servlet non encore en mémoire, celui-ci est dans un premier temps chargé par le classLoader du moteur Jserv, puis sa méthode init() est appelée. C’est dans cette méthode que doivent donc être placée les commandes gourmandes en ressources ou celles prenant du temps (connection aux bases de données, par exemple). Il est important lorsque l’on surcharge la méthode init() de faire appel à la méthode init de la super classe, ce qui a pour effer de sauver la

Exemple de surcharge de la méthode init() :




public class MonServlet extends HttpServlet {
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        try {
            Class.forName(”xxx”);
        }
        catch(java.lang.ClassNotFoundException e) {
            …
        }
    }
    public void doGet(…) {
    …
    }
}

  • Fonctionnement

Après initialisation, le servlet est capable de recevoir une requète de la part d’un client. Lorsqu’une requète lui parvient, il appelle alors la méthode service(), qui reconnait le type de la requète HTTP (GET, POST, …) et la fait parvenir à la méthode conçue pour traiter les requètes de ce même type (doGet(), doPost(), …)

  • Destruction

Un servlet est normalement gardé en mémoire en prévision d’éxécutions futures, cependant pour des raisons diverses, notamment la configuration de Jserv et l’occupation des ressources, le moteur de servlet peut décider de détruire le servlet en appelant sa méthode destroy(). C’est donc ici que le concepteur de servlets doit inclure des instructions permettant par exemple de sauvegarder des données pour de futures sessions.
 

3 Exemple : traitement de formulaires

Les formulaires au sein d’une page HTML permettent l’interaction entre client et serveur web. Un formulaire contient généralement plusieurs éléments ou contrôles, comme par exemple des zones de saisie de texte, des boutons, des listes de choix, qu’il appartient à l’utilisateur de remplir, cliquer ou sélectionner selon ses désirs. Chacun des choix de l’utilisateur est stocké dans une paire NAME/VALUE.
Il existe deux méthodes pour faire parvenir les données de l’utilisateur au serveur. La première, dite méthode GET, transmet les données utilisateurs dans le header de la requète, tandis que la seconde, la méthode PUT, les transmet dans le corps de la requète, permettant de transférer des volumes de données beaucoup plus important.

3.1 Méthode GET

 

<form ACTION=”/servlets/cherche” METHOD=”GET”>
<B>Chercher</B>
<input TYPE=”text” NAME=”query” VALUE=”" SIZE=20>
<B>avec</B>
<select NAME=”type”>
<option VALUE=”Google” SELECTED>Google
<option VALUE=”Altavista”>Altavista
<option VALUE=”Metacrawler”>Metacrawler
<option VALUE=”Dictionnaire”>Dictionnaire
</select> 
<input TYPE=”submit” VALUE=”Now!”>
</form>

Chercher

avec



Pour traiter une requète GET, il est nécessaire de surcharger la méthode doGet. A l’intérieur de cette méthode, la méthode getParameter permet de récupérer la valeur d’un paramètre passé au servlet avec la requète GET. Par exemple:

String bookId = request.getParameter(”bookId”); //permet de récuperer la valeur du paramètre “bookid”. La méthode renvoie null si le paramètre n’existe pas. Il est possible d’utiliser cela pour compacter les pages dynamique en un seul servlet:
 




String bookId = request.getParameter(”bookId”);
if (bookid == null) {

    //affiche le formulaire

} else {

    //traite le formulaire

}




 

3.2 Méthode PUT

La méthode PUT est généralement utilisée pour uploader des fichiers du disque de l’utilisateur vers le serveur. Elle peut par exemple être utilisée pour soumettre des images, ou encore des fichiers contenant des données à analyser par le serveur.

4 Maintien de sessions

HttpSession session = request.getSession(true);

Rien de plus pour l’instant.

5 Cookies

Bien que les classes et méthodes utilsées pour le maintien de session utilisent les cookies sans que l’on ai besoin d’y toucher directement, l’API Servlet comprends la classe javax.servlet.http.Cookie qui permet de manipuler des objets Cookies
 

    5.1 Envoyer un cookie

Pour créer un cookie:




Cookie c = new Cookie(”login”, str_login);
c.setVersion(1);
c.setDomain(”.mon_domaine.com”);
res.addCookie(authCookie);

    5.2 Récupérer un cookie

L’instruction suivante permet de récupèrer l’ensemble des cookies:

Cookie[] cookies = req.getCookies(); 

La classe Cookie possède alors les méthodes suivantes:
public String getName()  pour récupèrer le nom du cookie

public String getDomain() pour récupèrer le domaine

public String getValue() pour récupérer la valeur stockée dans le cookie


6 Problèmes de threading

Un serveur web pouvant servir plusieurs clients de manière concurrente, lorsqu’un servlet est conçu de manière à accèder à une ressource partagée, par exemple une base de données, il est parfois nécéssaire de prévenir l’accès simultané par plusieurs clients à cette même ressource. Afin d’obliger un servlet à ne traiter qu’une seule requète à tout moment, il existe deux possibilités : la première consiste à concevoir le servlet de façon à ce qu’il implémente l’interface SingleThreadModel.

Un exemple d’un tel servlet est le suivant :




public class ReceiptServlet extends HttpServlet implements SingleThreadModel {
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        …
    }

    …
}


Le serveur s’assure alors que la méthode service n’est pas appelée plus d’une seule fois simultanément.
Un moteur de base de données comporte bien souvent des systèmes de verrouillage d’accès et n’est donc pas un bon exemple. Prenons plutot l’exemple d’un fichier texte contenant un nombre plusieurs clients pourraient vouloir modifier simultanément

La deuxième possibilité est de synchroniser l’accès à la ressource.

7 Java DataBase Connectivity

Il serait difficile de parler de l’API Servlet sans également mentionner l’API JDBC. En effet, ce dernier permet à tout servlet d’accèder de manière directe à pratiquement n’importe quelle base de donnée externe, pourvu que celle ci possède un driver JDBC. Dans cet article, nous utilisons la base de données PostgreSQL, dont le driver JDBC est disponible à cette adresse. Il faut avant de commencer s’assurer que le chemin du driver JDBC est présent dans le $CLASSPATH. (au besoin faire un olly>export CLASSPATH=$CLASSPATH:/usr/lib/pgsql/jdbc6.5-1.2.jarou bien insérer la ligne wrapper.classpath=/usr/lib/pgsql/jdbc6.5-1.2.jardans le fichier jserv.properties)

Pour faire fonctionner l’example fourni, il est nécéssaire d’avoir une base de données (ici nommée test), et d’y insérer une table avec quelques données. Pour cela, il suffit de créer un fichier texte tout simple nommé par exemple jdbc.sql contenant les quelques commandes SQL suivantes :




create table stories (story_title varchar(100), story_url varchar(100), story_date date);
insert into stories values (’NASA Proposes Launch Solar Sail Vehicle For 2010′, ‘http://slashdot.org/article.pl?sid=00/05/15/058238′, ‘2000-05-15′);
insert into stories values (’Linuxcare Responds To Tim O\’Reilly’s Article’, ‘http://slashdot.org/article.pl?sid=00/05/15/0254252′, ‘2000-05-15′);
insert into stories values (’New Internet VCR Service’, ‘http://slashdot.org/article.pl?sid=00/05/14/2048217′, ‘2000-05-15′);



 

Ensuite la commande  olly>psql test< jdbc.sql permet d’éxécuter ces commandes (et donc de créer la table et d’y insérer les trois enregistrements).

    7.1 Connection à une base de donnée

Dans le monde JDBC, une base de données est représentée par une URL, par exemple jdbc:postgresql://host:port/base. En ce qui concerne le driver JDBC pour PostgreSQL, host est par défaut égal à localhost et port à 5432


import java.sql.*;
public class jdbctest {
   public static void main(String args[])
   {
        String url = “jdbc:postgresql:test”;
        Connection con;
        Statement stmt;
	
        try
        {
           Class.forName(”postgresql.Driver”);
        }
        catch(java.lang.ClassNotFoundException e)
        {
           System.err.print(”ClassNotFoundException: “); System.err.println(e.getMessage());
        }

	
        try
        {
           con = DriverManager.getConnection(url, “olly”, “”);
           stmt = con.createStatement(); 

	
            ResultSet rs = stmt.executeQuery(”select * from stories”);
           while (rs.next())
           {
               String s = rs.getString(”story_title”);
               System.out.println(s);
           }
           stmt.close();
           con.close();

	
        }
       catch (SQLException ex)
       {
           System.err.println(”SQLException: ” + ex.getMessage());
       }
   }
}


	

Stockage d’objet Java dans une base PostgreSQL

Postgresql est une base de données d’un genre un peu particulier : elle possède par rapport à une base relationnelle traditionnelle des extensions objets, qui lui permettent par exemple de stocker une table dans un champs d’une autre table.

Il est donc tout à fait possible en Java de stocker un objet dans un stream, si la classe de l’objet implémente l’interface java.io.Serializable. Cette caractèristique rend alors possible le stockage d’ objets Java dans une base Postgresql, au moyen des LargeObject. Cependant, Postgresql est un moteur de base de données d’un genre un peu particulier : il possède par rapport à une base relationnelle traditionnelle des extensions objets, qui lui permettent par exemple de stocker une table dans un champs d’une autre table. La classe postgresql.util.Serialize du driver JDBC se sert de cette caractèristique pour fournir un moyen de stocker un objet Java en tant que table.
 

8 Un servlet évolué: Cocoon

Cocoon permet de transformer des données XML grâce a des feuilles de style XSL de façon à obtenir non seulement du HTML pour les navigateurs classiques, mais également du WML pour les browser WAP contenus dans certains téléphones mobiles, ou encore du PDF . Il permet donc d’ouvrir les sites web inter ou intranet à un nombre considérable de clients, sans que soient nécessaires les refontes de chaque document pour le rendre compatible avec les systèmes de navigation spécifiques à chaque client. 
 

    Installation de Cocoon

La première chose a faire consiste à télécharger Cocoon, à partir du site http://xml.apache.org, puis à le compiler (comme à l’habitude, ./configure, make, make install)
Il est ensuite nécessaire de rendre les classes Cocoon visibles par le moteur de servlets : il faut pour cela ajouter des wrapper.classpath vers tous les .jar requis par Cocoon dans le fichier jserv.properties
cocoon.jar :
xerces.jar : parseur XML
xalan.jar : moteur de transformation XSLT
fop.jar : formating
par exemple:
wrapper.classpath=/usr/local/java/lib/cocoon.jar

Il faut ensuite choisir la zone servlet dans laquelle Cocoon doit résider, zone dans cette exemple. Il faut donc passer le fichier cocoon.properties en parametre au fichier zone.properties, en y ajoutant la ligne suivante:
servlet.org.apache.cocoon.Cocoon.initArgs=properties=[path-to-cocoon]/conf/cocoon.properties

Il faut également dire à Apache d’associer tous fichier xml avec Cocoon. Pour cela, il faut ajouter:




Action cocoon /servlet/org.apache.cocoon.Cocoon
AddHandler cocoon xml



dans le fichier jserv.conf. (/servlet/ est le point de montage de la zone servlet a laquelle appartient Cocoon)
Nous sommes alors prêts pour créer notre premier document XML, ainsi que sa feuille de style.
Plusieurs cas de figures : le fichier XML existe, il faut simplement lui adjoindre une feuille XSL. Deuxième cas, l’information est stockée dans une base de données, par exemple postgreSQL, et il va être nécessaire d’extraire dans un premier temps cette information, pour la mettre au format XML, puis lui appliquer une transformation XSL.

Cas 1: Le fichier XML existe deja
Le fichier XML est le suivant, et nous voulons afficher ses infos dans un document HTML, sous forme de table.




<?xml version=”1.0″ encoding=”UTF-8″?>
<stories>
    <story>
        <story_title>NASA Proposes Launch Solar Sail Vehicle For 2010</story_title>
        <story_url> http://slashdot.org/article.pl?sid=00/05/15/058238</story_url>
        <story_date>2000-05-15</story_date>
    </story>

    <story>
        <story_title>Linuxcare Responds To Tim O&apos;Reilly&apos;s Article</story_title>
        <story_url>http://slashdot.org/article.pl?sid=00/05/15/0254252</story_url>
        <story_date>2000-05-15</story_date>
    </story>

    <story>
        <story_title>New Internet VCR Service</story_title>
        <story_url>http://slashdot.org/article.pl?sid=00/05/14/2048217</story_url>
        <story_date>2000-05-15</story_date>
    </story>
</stories>


La feuille de style que l’on doit appliquer pour obtenir le résultat souhaité est très simple:




<?xml version=”1.0″?>
<xsl:stylesheet xmlns:xsl=”http://www.w3.org/1999/XSL/Transform” version=”1.0″>
<xsl:template match=”/”>
<html>
<body>
<xsl:apply-templates select=”stories”/>
</body>
</html>
</xsl:template>

<xsl:template match=”stories”>
<table>
<xsl:apply-templates select=”story”/>
</table>
</xsl:template>

<xsl:template match=”story”>
 <tr><td><a href=”{story_url}”><xsl:value-of select=”story_title”/></a></td><td><xsl:value-of select=”story_date”/></td></tr>
</xsl:template>

</xsl:stylesheet>


Cette feuille de style est stockée dans le fichier stories.xsl. Pour signifier à Cocoon qu’il doit appliquer cette feuille au document XML ci-dessus, il faut rajouter une ligne à ce dernier, dans son entête,  juste après le tag de version.




<?xml version=”1.0″?>
<?xml-stylesheet href=”stories.xsl” type=”text/xsl”?>
<?cocoon-process type=”xslt”?>

<stories>
.
.




En pointant votre browser sur l’url de stories.xml, on obtient le code HTML suivant:
 




<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0//EN”
                      “http://www.w3.org/TR/REC-html40/strict.dtd”>
<html><body><table><tr><td><a
      href=”http://slashdot.org/article.pl?sid=00/05/15/058238″>NASA Proposes Launch Solar Sail Vehicle For 2010</a></td><td>2000-05-15</td></tr><tr><td><a
      href=”http://slashdot.org/article.pl?sid=00/05/15/0254252″>Linuxcare Responds To Tim O’Reilly’s Article</a></td><td>2000-05-15</td></tr><tr><td><a href=”http://slashdot.org/article.pl?sid=00/05/14/2048217″>New Internet VCR Service</a></td><td>2000-05-15</td></tr></table></body></html>

<!– This page was served in 748 milliseconds by Cocoon 1.7 –>




 
 

Cas 2 : l’information est stockée dans une base de données
 

Il faut passer par ce que l’on appelle un SQLProcessor. XSQL, fourni par Oracle, est un exemple de produit transformant un résultat d’une requète SQL en XML. Pour pouvoir utiliser SQLProcessor, il faut s’assurer qu’une ligne du type processor.type.sql = org.apache.cocoon.processor.sql.SQLProcessor est présente dans le fichier cocoon.properties.

Cet exemple éxécute une requète SQL sur une base PostGreSQL grâce à JDBC (il faut donc lui fournir les coordonnées du driver, ainsi que des infos utilisateurs, tq login et password) puis récupère les résultats et les formatte en XML. Il s’agit simplement de remplacer le bloc <query> … </query> par le résultat, puis de lui appliquer la feuille de style normale.




<?xml version=”1.0″?>
<?xml-stylesheet href=”stories.xsl” type=”text/xsl”?>
<?cocoon-process type=”sql”?>
<?cocoon-process type=”xslt”?>

<page>

 <connectiondefs>
  <connection name=”test_connection”>
   <driver>postgresql.Driver</driver>
   <dburl>jdbc:postgresql:test</dburl>
   <username>olly</username>
   <password></password>
  </connection>
 </connectiondefs>

 <query connection=”test_connection” doc-element=”stories” row-element=”story”>
  select story_title, story_url, story_date from stories
 </query>

</page>


Les attributs doc-element et row-element permettent de spécifier respectivement le nom que va prendre l’ensemble des résultats (ResultSet), et les lignes (rows). S’ils ne sont pas spécifié, ces noms seront ROWSET et ROW.
 

9 Upload de fichiers

Pour “uploader” un fichier grace à un servlet Java, il faut utiliser le package com.oreilly.servlet disponible à cette adresse. Imaginons que l’on ai le formulaire suivant:

<form  enctype=\"multipart/form-data\" action=\"action\" method=\"post\"><br>
<textarea name=\"indata\" cols=\"70\" rows=\"10\"></textarea><br>
<input type=\"file\" name=\"infile\"><br>
<input type=\"submit\" name=\"submit\" value=\"Continue\"><br>
</form><br>

Ce formulaire contient deux champs, un champ de type texte (textarea), et un champ de type “file”. Supposons maintenant que l’on veuille sauver les données du formulaire (fichier ou texte) dans le fichier /tmp/dataXX-YY. La méthode doPost() permettant de réaliser cela est la suivante :

 import java.io.*;
 import javax.servlet.*;
 import javax.servlet.http.*;
 import java.util.Date;
 import com.oreilly.servlet.multipart.*;
	
 .
 .
	
 public void doPost (HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {
	
        /** récupère la date courante **/
        Date d = new Date();
	
	/** forge une chaine de caractère contenant la date **/
        String timestamp = new String(d.getMinutes() + \"-\" + d.getSeconds());
	
	/** crée un nouveau multipart parser, la taille des objets parsés étant de 10 MB au maximum **/
        MultipartParser mp = new MultipartParser(request, 10*1024*1024); // 10MB
        Part part;
	
	/** itére tous les parties **/
        while ((part = mp.readNextPart()) != null) {
	    /** s'il s'agit du fichier **/
            if (part.getName().equals(\"infile\")) {
	
	        /** recupere les données sous la forme d'un FilePart **/
                FilePart filePart = (FilePart) part;
                String fileName = filePart.getFileName();
	
		/** recopie dans un nouveau fichier **/
                if (fileName != null) {
                    long size = filePart.writeTo(new File(\"/tmp/data\" + timestamp));
                    break;
                }
	
	    /** s'il s'agit de la zone de texte **/
            } else if (part.getName().equals(\"indata\")) {
	
	        /** recupere les données sous la forme d'un objet ParamPart **/
                ParamPart paramPart = (ParamPart) part;
	
		/** récupere la valeur du champ \"indata\" **/
                String indata = paramPart.getStringValue();
	
		/** pour écrire dans un fichier **/
                PrintWriter fos = new PrintWriter(new FileWriter(\"/tmp/data\" + timestamp));
		fos.print(indata);
	
                fos.close();
            }
        }
}

 

 

un petit tutorial en java

Using the Xalan XSLT engine within a java servlet

Introduction

Separation of style from content allows for the same data to be presented in different ways and is the clear answer to the multiplication of connected devices (Palm, Pocket PC, Interactive TV) that can access networked ressources using their own language (WML, WebClipping, HTML, XHTML, cHTML, etc..).
In this article, we show how to produce HTML and WML content from an XML data source, and the appropriate XSLT stylesheets. The XSLT transformation is done using the Xalan transformation engine, an open-source java project hosted by the Apache foundation. The Xalan engine is called from a java servlet, running in the Tomcat servlet engine.
 

Requirements

In this article, I will assume that you have installed the Tomcat servlet engine, and the Xalan XSLT engine. Both are available from java.apache.org and xml.apache.org. I also assume that xalan.jar, xerces.jar (the XML parser bundled with Xalan) and the servlet classes are present in your classpath. If not, try something like:

XALAN_HOME=/path/to/xalan.jar
XERCES_HOME=/path/to/xerces.jar
export CLASSPATH=$CLASSPATH:$XALAN_HOME:$XERCES_HOME
 
 

Creating a new web application within Tomcat

Although you could install your java classes in an existing web application (the one called “examples”, for instance), it is probably better to create a new web application.  This is nicely explained in “Deploying web applications to Tomcat” by James Goodwill.
Assuming $TOMCAT_HOME is the path to the Tomcat directory, first change directory to webapps (the root of all web applications) and create the following directories:

/xslt
/xslt/WEB-INF
/xslt/WEB-INF/classes

To do so, type the following commands:
> cd $TOMCAT_HOME/webapps
> mkdir xslt
> cd xslt
> mkdir WEB-INF
> cd WEB-INF
> mkdir classes
> cd classes

The /xslt/WEB-INF/classes directory is the place where you will store all the servlets classes described below.

Once the directories are created, you should install a servlet context, by editing the file $TOMCAT_HOME/conf/server.xml, and adding the following lines:

<Context path=”/xslt” docBase=”webapps/xslt” debug=”0″ reloadable=”true” >
</Context>

path=”/xslt” tells Tomcat that all requests starting with /onjava belong to the onjava web application.
docBase=”webapps/xslt” tells the servlet container that the web application is located on webapps/xslt”
 

Once you have done these operations, you need to restart Tomcat.
 

Xalan-J : a Java XSLT engine

We use Xalan as our XSLT engine. While we embed Xalan within our servlet, Xalan-J can also be used in a command line way to perform XSLT transformation and produce static output files. For example, imagine you want to produce a static HTML file called slashdot.html from a XML file called slashdot.xml.
You just need to type the following line:
> java org.apache.xalan.xslt.Process -in slashdot.xml -xsl slashdot.xsl -out slashdot.html

If you want the output to be displayed on the screen, simply omit the -out flag and argument.

The XSLT processor class

Xalan-J implements the TrAX (Transformation API for XML) interface. From the Xalan documentation: “A TRaX TransformerFactory is an object that processes transformation instructions, and produces Templates (in the technical terminology). A Templates object provides a Transformer, which transforms one or more Sources into one or more Results. To use the TRaX interface, you create a TransformerFactory, which may directly provide a Transformers, or which can provide Templates from a variety of Sources. The Templates object is a processed or compiled representation of the transformation instructions, and provides a Transformer. The Transformer processes a Source according to the instructions found in the Templates, and produces a Result“.
In the code below, the XSLT processor class contains a method that takes as input a XML source, a XSL source, a servlet request (it is not used here) and a servlet response, and it returns the output of the transformation to the servlet output stream.




import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

import org.xml.sax.SAXException;

import javax.xml.transform.*;
import javax.xml.transform.stream.*;

public class XalanXslProcessorBean {

    TransformerFactory tFactory;

    //the constructor simply gets a new TransformerFactory instance
    public XalanXslProcessorBean() {
        tFactory = TransformerFactory.newInstance();
    }

    //this method takes as input a XML source, a XSL source, and returns the output of the transformation to the servlet output stream
    public void process(StreamSource xmlSource,
                                  StreamSource xslSource,
                                  HttpServletRequest request,
                                  HttpServletResponse response)
             throws ServletException, IOException, SAXException {
        try {
            Templates templates = tFactory.newTemplates(xslSource);
            Transformer transformer = templates.newTransformer();
             transformer.transform(xmlSource, new StreamResult(response.getOutputStream()));
        }
        catch (Exception e) {
           //should log some message here
        }
    }
}




 
 

The XML data

The XML file we will use was grabbed from the slashdot.org site, and contains the slashdot news in XML form. It needs to be saved to your disk (and called slashdot.xml for example).




<?xml version=”1.0″?><backslash xmlns:backslash=”http://slashdot.org/backslash.dtd”>

 <story>
  <title>NASA Proposes Launch Solar Sail Vehicle For 2010</title>
  <url>http://slashdot.org/article.pl?sid=00/05/15/058238</url>
  <time>2000-05-15 07:54:15</time>
  <author>timothy</author>
  <department>ralph-nader-will-have-to-hire-a-chase-car</department>
  <topic>space</topic>
  <comments>99</comments>
  <section>articles</section>
  <image>topicspace.gif</image>
 </story>

 <story>
  <title>Linuxcare Responds To Tim O’Reilly’s Article</title>
  <url>http://slashdot.org/article.pl?sid=00/05/15/0254252</url>
  <time>2000-05-15 02:57:07</time>
  <author>timothy</author>
  <department>consider-source-horses-mouth-grain-of-salt</department>
  <topic>linuxbiz</topic>
  <comments>142</comments>
  <section>articles</section>
  <image>topiclinuxbiz.gif</image>
 </story>

 <story>
  <title>New Internet VCR Service</title>
  <url>http://slashdot.org/article.pl?sid=00/05/14/2048217</url>
  <time>2000-05-14 20:51:57</time>
  <author>timothy</author>
  <department>this-is-cool-but-can-they-do-that?</department>
  <topic>news</topic>
  <comments>189</comments>
  <section>articles</section>
  <image>topicnews.gif</image>
 </story>

 <story>
  <title>Google Releases WAP Search Tool</title>
  <url>http://slashdot.org/article.pl?sid=00/05/14/1240252</url>
  <time>2000-05-14 17:49:11</time>
  <author>emmett</author>
  <department>wireless</department>
  <topic>internet</topic>
  <comments>141</comments>
  <section>articles</section>
  <image>topicinternet.jpg</image>
 </story>

 <story>
  <title>No More Unreal Ports For Linux?</title>
  <url>http://slashdot.org/article.pl?sid=00/05/14/1439224</url>
  <time>2000-05-14 16:32:11</time>
  <author>timothy</author>
  <department>one-web-one-program-happy-mothers-day</department>
  <topic>games</topic>
  <comments>250</comments>
  <section>articles</section>
  <image>topicgames.jpg</image>
 </story>

 <story>
  <title>Pioneer Introduces 1st DVD Recorder (In Japan)</title>
  <url>http://slashdot.org/article.pl?sid=00/05/14/152210</url>
  <time>2000-05-14 15:50:48</time>
  <author>CmdrTaco</author>
  <department>steam-rising-from-the-riaas-forehead</department>
  <topic>tv</topic>
  <comments>98</comments>
  <section>articles</section>
  <image>topictv.jpg</image>
 </story>

 <story>
  <title>QuakeForge And QuakeWorld Forever Merge</title>
  <url>http://slashdot.org/article.pl?sid=00/05/14/1447248</url>
  <time>2000-05-14 15:07:27</time>
  <author>CmdrTaco</author>
  <department>and-then-there-was-one</department>
  <topic>quake</topic>
  <comments>57</comments>
  <section>articles</section>
  <image>topicquake.gif</image>
 </story>

 <story>
  <title>What Happens When Open Source And Work Collide?</title>
  <url>http://slashdot.org/article.pl?sid=00/05/09/016208</url>
  <time>2000-05-14 14:04:07</time>
  <author>Cliff</author>
  <department>sticky-situations</department>
  <topic>programming</topic>
  <comments>170</comments>
  <section>askslashdot</section>
  <image>topicprogramming.gif</image>
 </story>

 <story>
  <title>Black Holes Don’t Exist???</title>
  <url>http://slashdot.org/article.pl?sid=00/05/14/1339252</url>
  <time>2000-05-14 13:39:24</time>
  <author>Roblimo</author>
  <department>pop-science-can-be-fun</department>
  <topic>science</topic>
  <comments>162</comments>
  <section>articles</section>
  <image>topicscience.gif</image>
 </story>

 <story>
  <title>Los Alamos Lab: We’re OK, You’re OK</title>
  <url>http://slashdot.org/article.pl?sid=00/05/14/0143228</url>
  <time>2000-05-14 04:44:44</time>
  <author>timothy</author>
  <department>sir-please-step-*away*-from-the-plutonium-bin</department>
  <topic>news</topic>
  <comments>278</comments>
  <section>articles</section>
  <image>topicnews.gif</image>
 </story>

</backslash>




 

The XSLT stylesheet

An XSL stylesheet basically consists of a set of templates. Each template “matches” some set of elements in the original XML data and then describes the contribution that the matched element makes to the final output.
An XSLT template is defined by a xsl:template tag, whose “match” parameter determines where this template applies. For example <xsl:template match=”/”> … </xsl:template> applies to the root element of the XML document, while <xsl:template match=”backslash/story”> matches every story element that has backslash as father. Templates are generally applied recursively, i.e. a template calls another templates using the xsl:apply-templates tag.
<xsl:value-of> inserts the value of an expression to the final output. Note that {element} can also be used to insert the value of element.

Here is the HTML stylesheet (named slashdot.xsl) we will use:




<?xml version=”1.0″?>
<xsl:stylesheet xmlns:xsl=”http://www.w3.org/1999/XSL/Transform” version=”1.0″>

<xsl:template match=”/”>
<html>
<body>
<xsl:apply-templates select=”backslash/story”/>
</body>
</html>
</xsl:template>

<xsl:template match=”backslash/story”>
  <li><a href=”{url}”><xsl:value-of select=”title”/></a></li>
</xsl:template>

</xsl:stylesheet>


Outputting HTML with a servlet

This java code implements a basic servlet, which uses the XalanXslProcessorBean class defined above. It sets the Content-Type portion of the HTTP header to text/html, creates two StreamSources objects from both the xml and the xsl files, and perform the transformation




import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

import javax.xml.transform.stream.*;

public class XslProcessorServlet extends HttpServlet {

    XalanXslProcessorBean processor;

    public void init(ServletConfig config) {
        processor = new XalanXslProcessorBean();
    }

    public void doGet (HttpServletRequest request,
                                HttpServletResponse response)
             throws ServletException, IOException {

        //sets the Content-Type portion of the HTTP header to text/html
        response.setContentType(”text/html”);
        try {
            processor.process(new StreamSource(”slashdot.xml”), new StreamSource(”slashdot.xsl”), request, response);
        }
        catch (Exception e) {

        }
    }
}


Since slashdot.xml is often updated,  you may prefer to fetch it directly from the slashdot.org site:  you then need to change the processor.process(…) line to: processor.process(new StreamSource(new InputStreamReader((new URL(”http://slashdot.org/slashdot.xml”)).openStream())), new StreamSource(”slashdot.xsl”), request, response);
Then restart your servlet container if needed, and reload the page.
 

Outputting HTML and WML with a servlet

Suppose that you want to make your content available to both HTML and WML navigators. Basically, you just need a XSLT stylesheet that can transform XML to HTML, and another one that can transform XML to WML (Wireless Meta Language). You then need to implement a mechanism that can use the appropriate stylesheet, depending on the navigator information contained in the HTTP request header.

Here is the WML stylesheet. Note the xsl:output tag, which is the only way to produce the <!DOCTYPE wml PUBLIC “-//WAPFORUM//DTD WML 1.1//EN” “http://www.wapforum.org/DTD/wml_1.1.xml”> string in the WML output.




<?xml version=”1.0″?>
<xsl:stylesheet xmlns:xsl=”http://www.w3.org/1999/XSL/Transform” version=”1.0″>
<xsl:output method=”xml”
                  doctype-public=”-//WAPFORUM//DTD WML 1.1//EN”
                  media-type=”text/vnd.wap.wml”
                  doctype-system=”http://www.wapforum.org/DTD/wml_1.1.xml”
                  encoding=”ISO-8859-1″/>

<xsl:template match=”/”>
<wml>

    <template>
        <do type=”prev” name=”Previous” label=”Back”>
            <prev/>
        </do>
    </template>

    <card id=”card1″ title=”Slashdot news”>
        <p>
            <xsl:apply-templates select=”backslash/story”/>
        </p>
    </card>

</wml>
</xsl:template>
 

<xsl:template match=”backslash/story”>
  <a href=”{url}”><xsl:value-of select=”title”/></a><br/>
</xsl:template>

</xsl:stylesheet>


Note that the following servlet code now contains some code to fetch the user agent from the HTTP header, and uses the WML stylesheet when the user agent string contains the word (Nokia). Obviously, this only works with a Nokia phone or with some Nokia emulator.




import java.io.*;
import java.net.*;
import javax.servlet.*;
import javax.servlet.http.*;

import javax.xml.transform.stream.*;

public class XslProcessorServlet extends HttpServlet {

    XalanXslProcessorBean processor;

    public void init(ServletConfig config) {
        processor = new XalanXslProcessorBean();
    }

    public void doGet (HttpServletRequest request,
                                HttpServletResponse response)
        throws ServletException, IOException {

        //fetch the user agent part of the HTTP header
        String useragent = request.getHeader(”user-agent”);

        //if the user agent contains the string “Nokia”, then use the WML stylesheet, otherwise use the HTML one
        StreamSource xslsource;
        if (useragent.indexOf(”Nokia”) >= 0) {
            //send the correct Content-Type
            response.setContentType(”text/vnd.wap.wml”);
            xslsource = new StreamSource(”slashdot_wml.xsl”);
        } else {
            response.setContentType(”text/html”);
            xslsource = new StreamSource(”slashdot_html.xsl”);
        }

        try {
            processor.process(new StreamSource(”slashdot.xml”), xslsource, request, response);
        }
        catch (Exception e) {

        }
    }
}


blogspirit
xanga
g-blog
blog-city
blogsome
blogg
msn
oldiblog
blogeasy
joueb
alfablog
avatale
blogstudio
blog.ca
blog.com
bloghi.com
ebloggy.com
blogigo
blogsharing
blogsource
blogspot
bloxster
cool-blog

ALV Ringtone NBA Petites annonces - sonneries - annonces immobilieres - sonneries Alicia keys
Echange de liens - page 1 - page 2 - page 3 - page 4 - page 5 - page 6 - page 7 - page 8 - page 9 - page 10 - le top ten | les nouveaux sites - . Le forum - .

les categoeirs de mon petit annuaire

escuelas
escultismo
escultor
escultura
esculturas
escursioni in
escursioni
escursionismo
esdoorn
esedra
esempi
esencia
esencias
esens
esens
esercito
esercizi
eserver
esgrima
eshop
eshop
esigenze
eslava
eslohe
eslohe
eslovaquia
eslovenia
esmas
esmeralda
esordienti
esoterie
esoterik
esoterik
esoterismo
esoterismo
esotici
espèce
espèce
espèces
espèces
espérance
espérance
espéranto
espéranto
espíritu
espaã
españa
españa en
españa y portugal
españa y
españa
españa
españa
españa
españa
español
español de
español del
español en españa
español en
español
español
español
español
español
española de
española
españolas
españoles
espace
espace
espace
espace
espaces verts
espaces verts
espaces
espaces
espacial
espacio web
espacio
espacios
espada
espadas
espagne
espagne
espagne
espagne
espagne
espagne
espagnol en espagne
espagnol en espagne
espagnol en
espagnol en
espagnol
espagnol
espagnol
espagnol
espagnol
espagnole
espagnole
espagnole
espagnole
espalda
espana
espanol
espanol
espanol
espanola
espanso
espanyol
especial de
especial
especiales
especialidad
especialidades
especialista en
especialista
especialistas en
especialistas
especializada en
especializada
especializadas
especializado en
especializado
especies
espectáculo
espectáculos
espectaculo
espectaculos
espectro
espejo
espejos
espeleo
espeleología
espeleologia
espelette
espelette
espelkamp
espelkamp
esperanto
esperanto
esperanto
esperanto
esperanto
esperanto
esperanto
esperanto
esperanza
esperia
esperienza
esperienze
esperti
espesor
espinosa
espion
espion
espionnage
espionnage
espiral
espiritismo
espiritu
espiritual
espirituales
espiritualidad
esplanade
esplosi
espoir
espoir
espondilitis anquilosante
espondilitis
esportazione
esposito
espositori
esposizione
esposizioni
espresso
espresso
espresso
espresso
espresso
espresso
espressomaschine
espressomaschine
espressomaschinen
espressomaschinen
esprit
esprit
esprit
esprit
esquí
esquel
esquemas
esqui
esquina
esquivel
esquizofrenia
esquizofrenia
essai
essai
essais
essais
essaouira
essaouira
essay
essay
essays
essays
essec
essec
essegi
essen
essen
essen e
essen e
essen und trinken
essen und trinken
essen und
essen und
essen
essen
essen
essence
essence
essener
essener
essentie
essentiel
essentiel
essentielle
essentielle
essentielles
essentielles
essenz
essenz
essenzen
essenzen
essenziali
esser
esser
essere
essiccatoi
essig
essig
esslingen am neckar
esslingen am neckar
esslingen am
esslingen am
esslingen e
esslingen e
esslingen
esslingen
esslinger
esslinger
essonne
essonne
essonnes
essonnes
essstörung
essstörung
essstörungen
essstörungen
están
estándares
estética
est de
est de
est le
est le
est un
est un
est une
est une
esta página
establece el
establece
establecimiento
establishment
establishment
estación de
estación
estacion
estacionamiento
estaciones de
estaciones
estadística
estadísticas
estadisticas
estado de méxico
estado de sinaloa
estado de
estado
estados unidos
estados
estambul
estamos
estampa
estampado
estampe
estampe
estampes
estampes
estancia
estancias
estar
estartit
estas
estatal de
estatal
estate agency
estate
estate
estate
estate
estate
estate
estate
estates
estates
estates
estatuto
este punta
este sitio
esteban
estella
estense
estensi
estepona
esterel
esterel
esteri
esterna
esterne
esterni
esterno
estero
estero
estetica
estetica
estetiche
estetiche
estetiche
estetici
estetico
esthétique
esthétique
esther
esther
esthetique
esthetique
estilo
estilos
estimation
estimation
estimo
estintori
estiva
estival
estival
estivale
estivale
estivales
estivales
estive
estivi
estivo
estivo
estivo
estland
estland
estnisch
estnisch
estonia
estonia
estonia
estonie
estonie
estores
estos
estrés
estrada
estratégica
estratégico
estrategia
estrategias de
estrategias
estrategica
estrazione
estrazioni
estrella de
estrella
estrellas
estremo
estreno
estrenos
estrich
estrich
estriche
estriche
estrie
estrie
estructura
estructurado
estructural
estructuras de
estructuras
estrusi
estrusione
estrusori
estuaire
estuaire
estuches
estudiante
estudiantes de
estudiantes
estudiantil
estudiar en australia
estudiar en
estudiar
estudio de diseño
estudio de
estudio jurídico
estudio
estudios contables
estudios de
estudios en
estudios
estupefacientes
et à la
et à la
et accessoires
et accessoires
et artisans
et artisans
et associés
et associés
et astuces
et astuces
et au
et au
et autres
et autres
et aux
et aux
et blanc
et blanc
et cadeaux
et cadeaux
et chambres
et chambres
et chat
et chat
et cher
et cher
et communication
et communication
et culture
et culture
et d’
et d’
et d’histoire
et d’histoire
et d’industrie
et d’industrie
et décoration
et décoration
et développement
et développement
et dans le
et dans le
et dans
et dans
et de gestion
et de gestion
et de l
et de l
et de la
et de la
et de secours
et de secours
et de services
et de services
et de
et de
et de
et de
et de
et de
et des techniques
et des techniques
et des
et des
et du
et du
et dvd
et dvd
et en europe
et en europe
et en
et en
et environnement
et environnement
et fabrication
et fabrication
et fils
et fils
et formation
et formation
et garonne
et garonne
et gestion de
et gestion de
et gestion
et gestion
et guides de
et guides de
et guides
et guides
et hébergement
et hébergement
et informatique
et informatique
et international
et international
et internet
et internet
et jardins
et jardins
et jean
et jean
et jouets
et jouets
et légumes
et légumes
et la
et la
et le
et le
et les
et les
et lesbien
et lesbien
et libertés
et libertés
et location
et location
et loir
et loir
et loire
et loire
et loisirs
et loisirs
et métiers
et métiers
et management
et management
et marketing
et marketing
et marne
et marne
et miquelon
et miquelon
et modèles
et modèles
et modernes
et modernes
et musée
et musée
et musique
et musique
et nouvelles technologies
et nouvelles technologies
et nouvelles
et nouvelles
et objets
et objets
et plus
et plus
et politique
et politique
et pour
et pour
et produits
et produits
et professionnels
et professionnels
et réalisation de
et réalisation de
et réalisation
et réalisation
et référencement
et référencement
et réseaux
et réseaux
et recrutement
et recrutement
et sa région
et sa région
et sa
et sa
et saint
et saint
et services
et services
et ses
et ses
et société
et société
et sociales
et sociales
et son
et son
et table
et table
et technique
et technique
et techniques
et techniques
et terroirs
et terroirs
et un
et un
et une
et une
et vente de
et vente de
et vente
et vente
et vie
et vie
et vilaine
et vilaine
et vous
et vous
etablissement
etablissement
etablissements
etablissements
etage
etage
etagen
etagen
etagenbett
etagenbett
etagenbetten
etagenbetten
etain
etain
etalon
etalon
etampes
etampes
etang
etang
etapas
etats de
etats de
etats
etats
etching
etching
eterna
eterna
eterno
ethan
ethernet
ethernet
ethernet
ethernet
ethernet
ethics
ethics
ethiek
ethik
ethik
ethiopie
ethiopie
ethique
ethique
ethische
ethische
ethnique
ethnique
ethno
ethno
ethno
ethno
ethnologie
ethnologie
etica
etica
etichettatrici
etichette
etico
etienne de
etienne de
etienne
etienne
etienne
etienne
etiket
etikett
etikett
etikette
etikette
etiketten
etiketten
etiketten
etikettendrucker
etikettendrucker
etikettieren
etikettieren
etiopía
etiopia
etiqueta
etiquetas
etiquette
etiquette
etiquettes
etiquettes
etnias
etnica
etnici
etnico
etnografico
etnomarketing
etoile
etoile
etoiles
etoiles
etoscha
etoscha
etosha
etosha
etoys
etoys
etrangères
etrangères
etranger
etranger
etretat
etretat
etruria
etrusca
etruschi
etrusco
etsen
ettal
ettal
ettaler
ettaler
etten
ettlingen
ettlingen
ettore
etude et
etude et
etude
etude
etudes
etudes
etudiant
etudiant
etudiants
etudiants
etudier
etudier
etuis
etuis
etwas andere
etwas andere
etwas
etwas
etxea
eu neuwagen
eu neuwagen
euganei
eugen
eugen
eugendorf
eugendorf
eugenia
eugenio
eugenio
eukanuba
eukanuba
eulalie
eulalie
eulen
eulen
eulenspiegel
eulenspiegel
eupen
eupen
eupen
eupen
eurasier
eurasier
eure et loir
eure et loir
eure et
eure et
euregio
euregio
euregio
eureka
eureka
eureka
euritmie
euro 2
eurodisney
eurodisney
euroeyes
euroeyes
euroline
euroline
eurolines
eurolines
euromünzen
euromünzen
euromunten
europã
europã
europã
europã
europäisch
europäisch
europäische
europäische
europäischen union
europäischen union
europäischen
europäischen
europäischer
europäischer
europäisches
europäisches
européen de
européen de
européen des
européen des
européen
européen
européenne
européenne
européennes
européennes
européens
européens
europ
europ
europ
europ
europa
europa
europa
europa
europa
europa
europa
europa
europa
europaletten
europaletten
europapark
europapark
europas grö
europas grö
europas
europas
europaschule
europaschule
europaweit
europaweit
europcar
europcar
europe
europe
europe
europe
europe
europe
europe
europe
europe
europea de
europea
europea
europea
europea
european
european
european
european
european
european
european
europeas
europee
europeen
europeen
europeenne
europeenne
europees
europei
europeo de
europeo
europeo
europeos
europese grondwet
europese regeringen
europese unie
europese
euros
euros
euros
eurospeedway
eurospeedway
eurostar
eurostar
eurovision song contest
eurovision song contest
eurovision song
eurovision song
eurovision
eurovision
euroweb internet gmbh
euroweb internet gmbh
euroweb internet
euroweb internet
euroweb
euroweb
eurythmie
eurythmie
euskadi
euskadi
euskadi
euskal herria
euskal
euskal
euskal
euskara
euskera
euskirchen
euskirchen
eustache
eustache
eutanasia
eutanasia
euthanasie
euthanasie
euthanasie
eutin
eutin
evaluación de
evaluación
evaluatie
evaluation
evaluation
evaluation
evaluation
evaluierung
evaluierung
evang
evang
evangelica
evangelie
evangelio
evangelion
evangelion
evangelion
evangelion
evangelion
evangelisatie
evangelisation
evangelisation
evangelisch
evangelisch
evangelisch
evangelische allianz
evangelische allianz
evangelische gemeinde
evangelische gemeinde
evangelische jugend
evangelische jugend
evangelische kirche
evangelische kirche
evangelische kirchengemeinde
evangelische kirchengemeinde
evangelische
evangelische
evangelische
evangelischen kirche
evangelischen kirche
evangelischen
evangelischen
evangelischer
evangelischer
evangelisches
evangelisches
evangelium
evangelium
evangile
evangile
evasion
evasion
eveil
eveil
evelyn
evelyn
evenemang
evenemang
evenement
evenement
evenement
evenementen
evenementenbureau
evenementenburo
evenementiel
evenementiel
evenementielle
evenementielle
evenements
evenements
event
event
event
event
event
event
eventagentur
eventagentur
eventi e
eventi
eventkalender
eventkalender
eventmanagement
eventmanagement
eventmarketing
eventmarketing
evento
evento
eventorganisation
eventorganisation
eventos sociales
eventos
events
events
events
events
events
events
events
eventservice
eventservice
evenwicht
evere
everest
everest
everglades
everglades
everlast
everlast
everquest
everquest
everquest
everquest
evers
evers
evers
every
evian
evian
evita
evitar
evola
evolución
evolutie
evolution
evolution
evolution
evolution
evolution
evolution
evolution
evolutiva
evoluzione
evrard
evrard
evreux
evreux
ewald
ewald
ewan mcgregor
ewige
ewige
ewigkeit und ein
ewigkeit und ein
ewigkeit und
ewigkeit und
ewigkeit
ewigkeit
exámenes
exact globe
exact
exactas
examen
examen
examen
examen
examen
examen
examenes
examens
examens
examens
excalibur
excalibur
excel
excel
excel
excel
excel
excel
excel
excelencia
excellence
excellence
excellence
excellence
excellent
excellent
excellent
excelsior
excelsior
excelsior
excelsior
excelsior
excelsior
exchange server
exchange server
exchange
exchange
exchange
exchange
exchange
exchange
exchange
excimer
excimer
excite
exclusief
exclusieve
exclusif
exclusif
exclusion
exclusion
exclusiv
exclusiv
exclusivas
exclusive
exclusive
exclusive
exclusive
exclusive
exclusive
exclusive
exclusivos
excursie
excursies
excursion
excursion
excursion
excursion
excursion
excursion
excursiones
excursions
excursions
excursions
excursions
excursions
executive search
executive search
executive search
executive search
executive search
executive
executive
executive
executive
executive
executive
executive
exemple
exemple
exemples
exemples
exenta n
exenta
exercice
exercice
exercices de
exercices de
exercices
exercices
exercises
exercises
exerzitien
exerzitien
exhaust
exhaust
exhibition
exhibition
exhibition
exhibition
exhibition
exhibition
exhibitions
exhibitions
exhibitions
exhibitions
exhibitions
exigence
exigence
exilio
existe
existenz
existenz
existenz
existenzgründer
existenzgründer
existenzgründung
existenzgründung
existiert
existiert
exito
exklusiv
exklusiv
exklusive
exklusive
exkursion
exkursion
exkursionen
exkursionen
exodus
exoten
exoten
exotic
exotic
exotic
exotic
exotique
exotique
exotiques
exotiques
exotische
exotische
expédition
expédition
expéditions
expéditions
expérience
expérience
expériences
expériences
expansion
expansion
expansion
expansion
expat
expat
expat
expat
expatriés
expatriés
expatriate
expatriate
expatriates
expatriates
expatriation
expatriation
expedición
expediciones
expediente x
expediente
expedientes
expeditie
expedities
expedition
expedition
expeditionen
expeditionen
expeditions
expeditions
expeditions
expeditions
expedito
experience
experience
experience
experience
experience
experiencia de
experiencia
experiencias
experiment
experiment
experimental
experimental
experimental
experimental
experimental
experimentell
experimentell
experimenten
expert comptable
expert comptable
expert
expert
expert
expert
expert
expert
experte
experte
experten
experten
expertise comptable
expertise comptable
expertise
expertise
expertise
expertise
expertise
expertises
expertises
experto
expertos en
expertos
experts comptables
experts comptables
experts
experts
experts
experts
experts
exploitant
exploitatie
exploitation de
exploitation de
exploitation forestière
exploitation forestière
exploitation
exploitation
exploración
explorateurs
explorateurs
exploration
exploration
explorer
explorer
explorer
explorer
explorer
explorer
explorer
explorers
explosion
explosion
explosionsschutz
explosionsschutz
expo 2
expo 2
exponate
exponate
export
export
export
export
export
export
export
exportación
exportacion de
exportacion
exportaciones
exportadores
exportar
expos
expos
expos
exposición
exposicion
exposiciones
expositie
exposities
exposition de
exposition de
exposition
exposition
exposition
exposition
expositions
expositions
expositores
expres
expresión
expresionismo
express by holiday
express by holiday
express by
express by
express
express
express
express
express
express
express
expresse
expression
expression
expression
expression
expressionismus
expressionismus
expressions
expressions
expresso
expresso
exquise
exquise
extérieur
extérieur
extérieurs
extérieurs
extender
extender
extensible
extensible
extension
extension
extension
extension
extensions
extensions
extensions
exter
exter
exterieur
exterieur
exterior
exteriores
extern
externa
externalisation
externalisation
externe
externe
externe
externe
externe
externer
externer
extertal
extertal
extintores
extrême
extrême
extra apotheek
extra vergine di
extra vergine
extra virgin
extra
extra
extra
extra
extra
extra
extra
extraction
extrait
extrait
extraits de
extraits de
extraits
extraits
extrakt
extrakt
extranet
extranet
extranet
extranet
extranet
extranet
extranjera
extranjero
extranjeros
extraordinaires
extraordinaires
extraterrestre
extravergine d’oliva
extravergine di oliva
extravergine di
extravergine
extrem
extrem
extrema
extremadura
extreme rage
extreme rage
extreme
extreme
extreme
extreme
extreme
extreme
extremo
extruder
extruder
extrusion
extrusion
extrusion
extrusion
extrusion
exupéry
exupéry
exzenterschneckenpumpen
exzenterschneckenpumpen
eyaculación
eyaculacion precoz
eyaculacion
eyeglass
eyeglass
eyeglasses
eyeglasses
eyeglasses
eyeglasses
eyewear
eyewear
eyewear
eyewear
eyrolles
eyrolles
eyzies
eyzies
ezsoftware
ezsoftware
fábrica
fábulas
fácil
fátima
fächer
fächer
fähigkeiten
fähigkeiten
fähre
fähre
fähren
fähren
fälle
fälle
färben
färben
fässer
fässer
fèves
fèves
fédéral de
fédéral de
fédéral
fédéral
fédérale
fédérale
fédération anarchiste
fédération anarchiste
fédération de
fédération de
fédération des
fédération des
fédération française de
fédération française de
fédération française
fédération française
fédération nationale
fédération nationale
fédération québécoise
fédération québécoise
fédération
fédération
félin
félin
féline
féline
félins
félins
félix
féminin
féminin
féminine
féminine
féminisme
féminisme
féministe
féministe
février
février
fête de
fête de
fête des
fête des
fêtes de
fêtes de
fêtes
fêtes
física y
física
fórmula 1
fórmula
fósiles
föderation
föderation
föhr
föhr
förde
förde
förder
förder
förderanlage
förderanlage
förderanlagen
förderanlagen
förderbänder
förderbänder
förderband
förderband
förderer
förderer
förderkreis
förderkreis
fördermittel
fördermittel
förderprogramme
förderprogramme
fördersysteme
fördersysteme
fördertechnik gmbh
fördertechnik gmbh
fördertechnik
fördertechnik
förderung der
förderung der
förderung von
förderung von
förderung
förderung
förderverein
förderverein
förster
förster
fútbol
fútbol
füchse
füchse
fühler
fühler
fühmann
fühmann
führen
führen
führende
führende
führer
führer
führerschein
führerschein
führerscheine
führerscheine
führerscheinentzug
führerscheinentzug
führt
führt
führung
führung
führungen
führungen
führungs
führungs
führungskräfte
führungskräfte
führungstraining
führungstraining
füller
füller
füllhalter
füllhalter
füllung
füllung
füllungen
füllungen
fünfte
fünfte
für ärzte
für ärzte
für österreich
für österreich
für 2
für 2
für alle
für alle
für allgemeinmedizin
für allgemeinmedizin
für alte
für alte
für anfänger
für anfänger
für angewandte
für angewandte
für arbeit
für arbeit
für arbeitsmedizin
für arbeitsmedizin
für arbeitsrecht
für arbeitsrecht
für arbeitsschutz und
für arbeitsschutz und
für arbeitsschutz
für arbeitsschutz
für augenheilkunde
für augenheilkunde
für autoren
für autoren
für bauwesen
für bauwesen
für beamte
für beamte
für behinderte menschen
für behinderte menschen
für behinderte
für behinderte
für berlin
für berlin
für betroffene
für betroffene
für bildung
für bildung
für blinde und
für blinde und
für blinde
für blinde
für charlie
für charlie
für chirurgie
für chirurgie
für damen
für damen
für das
für das
für den frieden
für den frieden
für den mittelstand
für den mittelstand
für den
für den
für deutschland
für deutschland
für die seele
für die seele
für die
für die
für digitale
für digitale
für e
für e
für ein lama
für ein lama
für ein
für ein
für eine
für eine
für einen
für einen
für eltern
für eltern
für ergotherapie
für ergotherapie
für ernährung
für ernährung
für erwachsene
für erwachsene
für erwachsenenbildung
für erwachsenenbildung
für führungskräfte
für führungskräfte
für familien
für familien
für familienrecht
für familienrecht
für firmen
für firmen
für fotografie
für fotografie
für frauen
für frauen
für frieden
für frieden
für gefahrstoffe
für gefahrstoffe
für geschichte
für geschichte
für gestaltung
für gestaltung
für gesundheit
für gesundheit
für haus
für haus
für hund
für hund
für hunde
für hunde
für ihr
für ihr
für ihre gesundheit
für ihre gesundheit
für ihre homepage
für ihre homepage
für ihre
für ihre
für ihren
für ihren
für immobilien
für immobilien
für industrie
für industrie
für innere
für innere
für internationale
für internationale
für internet
für internet
für jeden
für jeden
für junge
für junge
für katzen
für katzen
für kinder e
für kinder e
für kinder und
für kinder und
für kinder
für kinder
für kino
für kino
für klarinette
für klarinette
für klassische homöopathie
für klassische homöopathie
für klassische
für klassische
für kleine
für kleine
für kmu
für kmu
für kommunikation
für kommunikation
für kultur und
für kultur und
für kultur
für kultur
für kunst und
für kunst und
für kunst
für kunst
für kunstgeschichte
für kunstgeschichte
für lesben
für lesben
für linkshänder
für linkshänder
für linux
für linux
für literatur
für literatur
für mädchen
für mädchen
für männer
für männer
für münchen
für münchen
für marketing
für marketing
für medizin
für medizin
für medizinische
für medizinische
für menschen mit
für menschen mit
für menschen
für menschen
für menschenrechte
für menschenrechte
für musik
für musik
für musiker
für musiker
für nachhaltige entwicklung
für nachhaltige entwicklung
für nachhaltige
für nachhaltige
für naturheilkunde
für naturheilkunde
für neue medien
für neue medien
für neue
für neue
für neurochirurgie
für neurochirurgie
für neurologie
für neurologie
für orthopädie
für orthopädie
für outlook
für outlook
für pferde
für pferde
für physiotherapie
für physiotherapie
für plastische
für plastische
für psychiatrie und
für psychiatrie und
für psychiatrie
für psychiatrie
für psychotherapie
für psychotherapie
für reisen
für reisen
für rheinland
für rheinland
für rollstuhlfahrer
für rollstuhlfahrer
für schwule
für schwule
für senioren
für senioren
für sie
für sie
für singles
für singles
für soziale
für soziale
für sport
für sport
für sportmedizin
für sportmedizin
für studenten
für studenten
für suchmaschinen
für suchmaschinen
für systemische
für systemische
für tai
für tai
für technische
für technische
für tiere
für tiere
für tierrechte
für tierrechte
für umwelt und
für umwelt und
für umwelt
für umwelt
für unternehmen
für unternehmen
für urlaub
für urlaub
für verfassungsschutz
für verfassungsschutz
für webdesign
für webdesign
für webmaster
für webmaster
für werbung und
für werbung und
für werbung
für werbung
für windows
für windows
für wirtschaft
für wirtschaft
für wissensweitergabe
für wissensweitergabe
für zahn
für zahn
fürst
fürst
fürstenberg
fürstenberg
fürstenfeld
blogspirit
xanga
g-blog
blog-city
blogsome
blogg
msn
oldiblog
blogeasy
joueb
alfablog
avatale
blogstudio
blog.ca
blog.com
bloghi.com
ebloggy.com
blogigo
blogsharing
blogsource
blogspot
bloxster
cool-blog

juste pour faire connaitre mon petit annuaire….

j’ai crée un petit annuaire sur le web… n’hésitez pas à le visiter…