Accueil | Créer un blog | Blog Beauté | Blog Séries 247

un petit annuaire

juste pour faire connaitre mon petit annuaire

un nuveau petit tutorial en java | 19 janvier 2006


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

href="#Architecture de base d'un servlet">Architecture de base d'un servlet

Exemple: traitement de formulaires

Maintien de sessions

Cookies

href="#Problemes de threading">Problèmes de threading

href="#Java DataBase Connectivity">JDBC: Java DataBase Connectivity

href="xalan.html">Servlets et transformations XSLT avec Xalan-J

href="#Cocoon">Un servlet évolué: Cocoon

href="#Upload de fichiers">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 (href="http://java.sun.com/products/servlet/archive.html">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
name=query>
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 à href="http://www.retep.org.uk/postgres/">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 href="http://www.servlets.com/resources/com.oreilly.servlet/index.html">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();
}
}
}

 


 


Publié par unpetitannuaire à 20:39:40 dans un petit annuaire | Commentaires (0) |

un petit tutorial en java | 19 janvier 2006


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 href="http://java.apache.org">java.apache.org and href="http://xml.apache.org">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 href="http://onjava.com/lpt/a/780">"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) {

           color=#33ff33>//should log some message here

        }

    }

}





 

 

The XML data


The XML file we will use was grabbed from the href="http://slashdot.org /slashdot.xml">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) {

           color=#33cc00> //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 - .

Publié par unpetitannuaire à 20:38:56 dans un petit annuaire | Commentaires (0) |

les categories de mon annuaire | 19 janvier 2006

en anglais
en anglais
en angleterre
en angleterre
en aquitaine
en aquitaine
en ardèche
en ardèche
en ardeche
en ardeche
en ardenne
en ardenne
en ardenne
en argentina
en ariège
en ariège
en asie
en asie
en assurance
en assurance
en assurances
en assurances
en asturias
en australia
en auvergne
en auvergne
en aveyron
en aveyron
en barcelona
en bariloche
en beeld
en begeleiding
en belgique
en belgique
en benidorm
en bilbao
en bois
en bois
en bolivia
en bolivie
en bolivie
en bourgogne
en bourgogne
en bourse
en bourse
en bresse
en bresse
en bretagne sud
en bretagne sud
en bretagne
en bretagne
en brie
en brie
en buenos aires
en buenos
en bulgarie
en bulgarie
en buscadores y
en buscadores
en cévennes
en cévennes
en córdoba
en canarias
en cancun
en cangas de
en cangas
en canoa
en cantabria
en caracas
en cas
en cas
en casa
en castellón
en castellano
en castellon
en castilla
en cataluña
en champagne
en champagne
en charente maritime
en charente maritime
en charente
en charente
en charge
en charge
en chile
en chine
en chine
en ciel
en ciel
en ciencias
en coaching
en colombia
en comercio internacional
en comercio
en communicatie
en communication
en communication
en cordoba
en corse
en corse
en costa rica
en costa
en cours
en cours
en creuse
en creuse
en croatie
en croatie
en cuba
en cuir
en cuir
en cultuur
en cusco
en cuzco
en de
en defensa
en derecho
en df
en direct
en direct
en directo
en domein
en door
en dordogne
en dordogne
en dordogne
en drôme provençale
en drôme provençale
en drôme
en drôme
en droit
en droit
en dvd
en ecuador
en een
en egypte
en egypte
en el centro
en el extranjero
en el mundo
en el sur
en el usuario
en el valle
en el
en entreprise
en entreprise
en espaã
en españa
en español
en español
en espa
en espagne
en espagne
en espagne
en espagne
en esta
en estados unidos
en estados
en estambul
en este
en europa
en europe
en europe
en evenementen
en famille
en famille
en flandre
en flandre
en flash
en flash
en flash
en florencia
en folie
en folie
en forêt
en forêt
en format
en format
en forme
en forme
en français
en français
en france et
en france et
en france
en france
en france
en franche
en franche
en francia
en fruit
en fuengirola
en fuenlabrada
en galicia
en gebruikte
en general
en gestion
en gestion
en gezond
en gezondheid
en gironde
en gironde
en grèce
en grèce
en granada
en gros
en gros
en guadalajara
en guadeloupe
en guadeloupe
en guanajuato
en guatemala
en guinea
en haïti
en haïti
en haute
en haute
en het
en histoire
en histoire
en hoe
en ibiza
en ict
en ile de
en ile de
en ile
en ile
en image
en image
en images
en images
en immobilier
en immobilier
en in
en in
en in
en informatie
en informatique
en informatique
en inglés
en inglaterra
en inox
en inox
en internet
en internet
en irlande
en irlande
en is
en italia
en italie
en italie
en je
en kit
en kit
en kunst
en lã
en línea
en la argentina
en la costa
en la habana
en la isla
en la manga
en la red
en la sierra
en la web
en la
en la
en la
en la
en la
en la
en landen
en langue
en langue
en languedoc
en languedoc
en langues
en langues
en lanzarote
en las islas
en las
en laye
en laye
en liemers
en ligne
en ligne
en ligne de
en ligne de
en ligne
en ligne
en ligne
en ligne
en ligne
en lima
en limousin
en limousin
en linea
en linux
en logistiek
en londres
en lorraine
en lorraine
en los
en lozère
en lozère
en luberon
en luberon
en málaga
en médecine
en médecine
en méditerranée
en méditerranée
en méxico
en madera
en madrid
en main
en main
en malaga
en mallorca
en mallorca
en mallorca
en management
en management
en marbella
en marketing
en marketing
en marketing
en martinique
en martinique
en matière de
en matière de
en matière
en matière
en meer
en menorca
en mer
en mer
en met
en mexico
en miami
en milieu
en milieu
en milieu
en montagne
en montagne
en montgolfière
en montgolfière
en morelos
en moto
en naar
en nerja
en niet
en nieuwe
en normandie
en normandie
en nouvelle
en nouvelle
en nuestra
en nueva
en oaxaca
en oeuvre
en oeuvre
en of
en omgeving
en omstreken
en onderhoud
en ontwikkeling
en onze
en op
en or
en or
en organisatie
en organisation
en organisation
en orlando
en oropesa del
en oropesa
en over
en périgord
en périgord
en page
en page
en partners
en pays de
en pays de
en pays
en pays
en perú
en peru
en picardie
en picardie
en picos de
en picos
en pierre
en pierre
en place
en place
en poitou
en poitou
en portugal
en productie
en provence
en provence
en provence
en provence
en puebla
en puerto rico
en puerto
en punta del
en punta
en référencement
en référencement
en région
en région
en république dominicaine
en république dominicaine
en république
en république
en réseau
en réseau
en rassen
en recht
en recrutement
en recrutement
en red
en relaciones internacionales
en relaciones
en rhône
en rhône
en rodenrijs
en roumanie
en roumanie
en royans
en royans
en salamanca
en salta
en salud
en san luis
en san
en santé
en santé
en santiago
en sardaigne
en sardaigne
en savoie
en savoie
en savoir
en savoir
en scène
en scène
en schwei
en schwei
en sciences
en sciences
en segovia
en seine
en seine
en selectie
en sevilla
en sie
en sie
en sinaloa
en softbal
en software
en soie
en soie
en sonora
en suède
en suède
en su
en suisse romande
en suisse romande
en suisse
en suisse
en tanzanie
en tanzanie
en te
en teck
en teck
en temps réel
en temps réel
en temps
en temps
en todo
en touraine
en touraine
en training
en tu
en tuin
en tunisie
en tunisie
en un
en una
en und
en und
en uruguay
en uw
en vacatures
en val
en val
en valencia
en valladolid
en van
en vanoise
en vanoise
en vendée
en vendée
en venecia
en venezuela
en venta en
en venta
en vente
en vente
en verkoop van
en verkoop
en verkopen
en verre
en verre
en vijver
en vila
en villarreal
en visserij
en vivo
en voor
en wat
en web
en webdesign
en website
en welzijn
en werk
en yucatán
en yvelines
en yvelines
en zaragoza
en zijn
en zorg
en zu
en zu
enalotto
enamorados
enanlagen
enanlagen
enbahn
enbahn
enbau
enbau
enbeleuchtung
enbeleuchtung
enberg
enberg
enburg
enburg
encadrement
encadrement
encadrements
encadrements
encamp
encamp
encan
encan
encanto
encartaciones
enceinte
enceinte
enceintes
enceintes
encens
encens
enchère
enchère
enchères
enchères
enchere
enchere
encheres
encheres
enciclopedia libre
enciclopedia
enciclopedia
encierros
encoder
encoder
encoding
encoding
encontrarás
encontrar
encore
encore
encre
encre
encryption
encryption
encuentra
encuentro de
encuentro
encuentros
encuesta
encuestas
encyclopédie
encyclopédie
encyclopedia
encyclopedia
encyclopedia
encyclopedia
encyclopedie
encyclopedie
encyclopedie
end gastronomique
enddarm
enddarm
ende der welt
ende der welt
ende der
ende der
ende des
ende des
enden
enden
ender
ender
enderlein
enderlein
endermologie
endermologie
enders
enders
endersbach
endersbach
endettement
endettement
endienst
endienst
endingen
endingen
endlich
endlich
endocrinología
endocrinologia
endodontie
endodontie
endokrinologie
endokrinologie
endometriose
endometriose
endorf
endorf
endoskopie
endoskopie
endoskopische
endoskopische
endres
endres
endroit
endroit
endstufen
endstufen
enduit
enduit
enduits
enduits
endurance
endurance
endurance
enduro
enduro
enduro
enduro
enduro
enduro
enemy
enemy
energía solar
energía
energías
energetic
energetic
energetica
energetico
energetische
energetische
energia elettrica
energia solare
energia
energia
energie ag
energie ag
energie rinnovabili
energie
energie
energie
energie
energie
energie
energieagentur
energieagentur
energiearbeit
energiearbeit
energieberater
energieberater
energieberatung
energieberatung
energieeffizienz
energieeffizienz
energieeinsparverordnung
energieeinsparverordnung
energiekosten
energiekosten
energiemanagement
energiemanagement
energien
energien
energiepass
energiepass
energies
energies
energiesparen
energiesparen
energietechnik
energietechnik
energieversorgung
energieversorgung
energy
energy
energy
energy
energy
energy
enero de
enero del
enero
enfance
enfance
enfant
enfant
enfants de
enfants de
enfants du
enfants du
enfants et
enfants et
enfants
enfants
enfants
enfants
enfels
enfels
enfer
enfer
enfermedad de alzheimer
enfermedad de
enfermedad
enfermedades
enfermería
enfermera
enfermeras
enfermeria
enfermos
enfest
enfest
enfocarte
enfoque
engadin
engadin
engadin
engadina
engagement
engagement
engagement
engagement
engagierte
engagierte
engel für charlie
engel für charlie
engel für
engel für
engel
engel
engel
engel
engeland
engelberg
engelberg
engelbert
engelbert
engelen
engelhard
engelhard
engelhardt
engelhardt
engelke
engelke
engels
engels
engels
engels
engels
engels
engelse
engelskirchen
engelskirchen
engen
engen
enger
enger
enghien
enghien
engin
engin
engine marketing
engine
engine
engine
engine
engine
engine
engine
engineer
engineer
engineer
engineer
engineer
engineer
engineering ag
engineering ag
engineering gmbh
engineering gmbh
engineering
engineering
engineering
engineering
engineering
engineering
engineering
engines
engines
engines
engins
engins
england
england
england
englisch deutsch
englisch deutsch
englisch
englisch
englische
englische
englischkurs
englischkurs
englischkurse
englischkurse
english in
english language
english language
english to
english to
english translation
english translation
english
english
english
english
english
english
english
englmar
englmar
engrais
engrais
engranajes
enguera
enhain
enhain
enhandel
enhandel
enhorn
enhorn
enige
enigma
enigma
enigma
enigma
enigmas
enigmi
enita
enita
enjeux
enjeux
enjoy
enjoy
enjoy
enjoy
enjoy
enjoy
enkele
enkhuizen
enkirchen
enkirchen
enlüder
enlüder
enlace
enlaces
enluminure
enluminure
enluminures
enluminures
enneagram
ennepe
ennepe
ennepetal
ennepetal
ennest
ennest
ennio
ennstal
ennstal
enogastronomia
enogastronomia
enogastronomia
enogastronomici
enogastronomici
enogastronomici
enologia
enoteca
enoteche
enoteche
enoteche
enpals
enputz
enputz
enquête
enquête
enquête
Publié par unpetitannuaire à 20:38:14 dans un petit annuaire | Commentaires (0) |

Archives

Janvier

DiLuMaMeJeVeSa
1234567
891011121314
15161718192021
22232425262728
293031    

Glossaire

Rechercher

  • RSS
  • RSS
  • Podcast
  • atom 03