java in a framework - William Rey
Transcription
java in a framework - William Rey
1 JAVA IN A FRAMEWORK William Rey (26 novembre 2010) Table des matières 1 Introduction 5 1.1 À qui s’adresse ce livre ? . . . . . . . . . . . . . . . . . . . . . . . . 6 1.2 À qui s’adresse ce livre ? . . . . . . . . . . . . . . . . . . . . . . . . 7 1.3 Comment s’organise ce livre ? . . . . . . . . . . . . . . . . . . . . . 7 1.4 Pourquoi J2EE-like ? . . . . . . . . . . . . . . . . . . . . . . . . . . 8 1.5 Le prix à payer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 1.6 L’hébergement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 1.6.1 NFrance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 1.6.2 Gandi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 1.6.3 1.7 2 3 Iliad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 Règles typographiques . . . . . . . . . . . . . . . . . . . . . . . . . 10 1.7.1 Renvois . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 1.7.2 Liens vers Internet . . . . . . . . . . . . . . . . . . . . . . . 10 1.7.3 Tables & figures . . . . . . . . . . . . . . . . . . . . . . . . 10 Créer sa première application 11 2.1 Les pré-requis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.2 Télécharger le JDK . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.3 Télécharger Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.4 Créer un projet minimaliste . . . . . . . . . . . . . . . . . . . . . . . 13 2.5 Comment se présente une application WEB ? . . . . . . . . . . . . . 18 2.5.1 Le répertoire WEB-INF . . . . . . . . . . . . . . . . . . . . 18 2.6 Le fichier /WEB-INF/web.xml . . . . . . . . . . . . . . . . . . . . . 19 2.7 Hello World ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 2.7.1 Le serveur (ou conteneur) WEB . . . . . . . . . . . . . . . . 21 2.7.2 La classe principale . . . . . . . . . . . . . . . . . . . . . . . 22 2.7.3 Le lanceur . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 2.7.4 Hello world ! . . . . . . . . . . . . . . . . . . . . . . . . . . 26 Les choses sérieuses 28 3.1 28 Un peu d’interactivité . . . . . . . . . . . . . . . . . . . . . . . . . . 2 TABLE DES MATIÈRES 4 5 6 7 3.2 Sitemesh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 3.3 Définition d’un fichier xwork.xml . . . . . . . . . . . . . . . . . . 32 3.3.1 32 34 4.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 4.2 Références externes . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 4.3 L’action de login . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 Spring 36 5.1 36 Les Plain Old Java Objects . . . . . . . . . . . . . . . . . . . . . . . FreeMarker 38 6.1 Syntaxe de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 6.2 Création de formulaires . . . . . . . . . . . . . . . . . . . . . . . . . 38 Hibernate 7.2 7.3 9 Créer un raccourci pour les getters/setters . . . . . . . . . . . Les actions 7.1 8 3 39 Les bases de données . . . . . . . . . . . . . . . . . . . . . . . . . . 39 7.1.1 MySQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 7.1.2 PostgreSQL . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 7.1.3 Derby . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 7.1.4 HSQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 7.1.5 Oracle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 7.1.6 Sybase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 7.1.7 Microsoft SQL-Server . . . . . . . . . . . . . . . . . . . . . 42 La gestion des transactions . . . . . . . . . . . . . . . . . . . . . . . 42 7.2.1 La session . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 Quelques astuces . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 7.3.1 42 Les sessions détachées . . . . . . . . . . . . . . . . . . . . . Sécurité d’un site WEB 44 8.1 Différences entre une application WEB et une application bureautique 44 8.1.1 Accès direct . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 8.1.2 Historique . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 8.2 Saisie manuelle de l’URL . . . . . . . . . . . . . . . . . . . . . . . . 45 8.3 Variables contenant du code . . . . . . . . . . . . . . . . . . . . . . 45 8.4 Court-circuit des requêtes SQL . . . . . . . . . . . . . . . . . . . . . 45 8.5 Affichage des variables . . . . . . . . . . . . . . . . . . . . . . . . . 46 Saisir des données 47 9.1 Sécuriser la saisie . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 9.2 Fonctionnement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 TABLE DES MATIÈRES 4 9.2.1 Déclarer le versionning . . . . . . . . . . . . . . . . . . . . . 48 9.2.2 Saisie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 9.2.3 Protection des données . . . . . . . . . . . . . . . . . . . . . 50 9.2.4 Clonage de l’objet . . . . . . . . . . . . . . . . . . . . . . . 50 10 displaytag 54 10.1 Téléchargement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 10.2 Ajouter displaytag dans Struts . . . . . . . . . . . . . . . . . . . . . 54 11 Générer des images 56 11.1 Créer une interface . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 11.1.1 Le renderer . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 11.1.2 Utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 12 Logiciels 60 12.1 Microsoft EXCEL . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 12.2 Graphiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.3 Planificateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 60 12.4 SSH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 12.5 RLogin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 13 Le client lourd 62 14 Annexes 63 14.1 Les des logiciels téléchargés . . . . . . . . . . . . . . . . . . . . . . 63 Chapitre 1 Introduction Le développement de sites WEB a pris de plus en plus d’importance dans le monde informatique (aussi bien au niveau individuel qu’au niveau de l’entreprise). Il existe différents moyens de créer un site : tout dépend de sa finalité. Depuis quelques années, la création de simples pages WEB a disparu. De plus en plus sont apparus des langages permettant à des sites WEB de prendre vie, le plus souvent cette vie provient de la présence d’une base de données, plus récemment des capacités interactives de certaines pages. Ainsi, les sites WEB, avant tout informatifs, sont devenus au fil des années des applications complètes et souvent complexes. Bien entendu, des outils ont fait leur apparition. Nombre d’entre eux ont disparu mais, comme toujours, un petit nombre a su s’imposer. On peut considérer aujourd’hui trois familles (souvent assimilés à des langages) : PHP, .NET et JAVA. Les solutions en PHP présentent plusieurs avantages sérieux : – la simplicité ; – ses nombreuses capacités ; – le prix de l’hébergement ; – un langage adapté (et créé) pour le WEB ; – disponibilité (il est souvent inutile d’arrêter le serveur lors des mises à jour) ; – faible utilisation CPU ; – la rapidité de développement. Allié avec le serveur Apache & la base de données MySQL, PHP se révèle un langage puissant pour développer des sites WEB. Cependant, la langage PHP peut présenter des limites dans des environnements professionnels qui imposent des normes strictes en matière de sécurité ou, le plus souvent, de compatibilité avec le système d’information existant. C’est pourquoi des solutions élaborées à partir de JAVA ou .NET on leur place dans la mise en place d’Intranet (site WEB institutionnel uniquement accessible à partir de l’intérieur de l’entreprise) ou d’Extranet (site institutionnel accessible de l’extérieur tel que la consultation de vos comptes bancaires). Même si ce livre est consacré au développement en Java EE, il est intéressant de choisir la bonne solution technique. Entre .NET et JAVA, on fera surtout attention à l’environnement du système d’information. Si celui-ci est fortement lié à l’environnement Microsoft (au moins au niveau des serveurs), il sera peut-être plus judicieux de 5 CHAPITRE 1. INTRODUCTION 6 sélectionner la solution propriétaire (celle de Microsoft). Il est aussi intéressant de s’interroger sur l’utilisation d’une technologie WEB. Dans certains cas, le développement d’une solution propriétaire avec un client lourd (c’est à dire une application déployée sur chaque ordinateur) peut être une solution plus raisonnable. À la fin de ce livre, au chapitre 13, vous pourrez apprécier la possibilité d’offrir des interfaces utilisateurs (GUI) différentes avec un minimum de programmation supplémentaire. Développer en JAVA une application WEB peut se faire de plusieurs façons. Dans ce livre, nous abordons l’utilisation d’un framework permettant de standardiser (un peu) le code de l’application entre les différents développeurs. Il existe plusieurs frameworks de développement, nous avons choisi d’aborder uniquement le trio formé par Spring, Struts 2 et FreeMarker. Auquels peuvent s’ajouter de nombreux autres solutions comme Hibernate que nous aborderons de façon assez complète dans les chapitres de ce livre. De même, nous aborderons le développement d’une application WEB avec un simple conteneur WEB (tel que Tomcat), indépendemment de tout serveur d’application (tel que JBoss ou WebShere). Une fois l’application en fonction, vous verrez ce que le passage à un serveur d’application peut vous apporter et la simplicité pour le faire. 1.1 À qui s’adresse ce livre ? Il s’adresse à tout ceux qui connaissent déjà le langage JAVA de base (collections, sockets, threads, I/O, etc.) et désireux de créer un site WEB ou plus exactement des applications WEB facilement interfaçables avec leur base de données. Le trio Spring, Struts 2, FreeMarker permet de créer des solutions basées sur une conception multi-couches ou n-tier. Dans notre case, il s’agit d’un modèle 3-tier comprenant : 1. le GUI : c’est typiquement le traitement des informations circulant entre le navigateur et les premières couches de votre application : la vue (view) et le contrôleur (controller). 2. le business : la couche métier ou si on préfère le modèle dans le sens MVC (Model-View-Controller). C’est cette couche qui gére réellement toutes les règles métiers. 3. les données : typiquement la base de donnés et l’accés à celle-ci qui est assuré par les DAO (Data Access Objects) via des interfaces, des injections de code et le mapping objet des tables (nous verrons cela en détail dans le chapitre consacré à Hibernate, page 39. Au delà, la structure rigide des développements permet de garantir une certaine facilité de maintenance contrairement aux sites développés à partir d’outils qui mélangent accées aux données et affichage. CHAPITRE 1. INTRODUCTION 1.2 7 À qui s’adresse ce livre ? Ce tutoriel s’adresse avant tout aux techniciens, ou plus exactement aux programmeurs qui doivent développer une application WEB sous JAVA. Pour cela, les connaissances suivantes sont pré-requises : – JAVA : vous devez connaître la programmation en JAVA et tout particulièrement les nouveautés syntaxiques de la version 5 (à savoir les boucles de type «foreach» qui remplacent efficacement l’utilisation d’un objet Iterator ainsi que les templates). Une bonne connaissance des collections (List, Map, Set et leur implémentation sous forme de classes) est nécessaire. De même, la connaissance des annotations (uniquement leur utilisation) est nécessaire. – WEB : le protocole HTTP est considéré comme connu au moins superficiellement (nous ne rentrerons pas dans les détails, en revanche, on parlera fréquemment de requêtes et de sessions). – HTML : le langage HTML de description de page que nous utiliserons est relativement simple. Une connaissances des balises classiques (<head>, <title>, <body>, <img>, <b>) est suffisante. – CSS (Cascading Style Sheet) : la connaissance de la syntaxe des cascading style sheet est un plus mais nous fournirons tous les fichiers nécessaires. Ces fichiers se limite à gérer la mise en page des pages WEB. – SQL (Structured Query Language) : la connaissance de SQL est nécessaire dans le sens où vous devrez créer des requêtes et éventuellement créer votre base de données. Cependant, l’utilisation d’Hibernate utilisant son propre langage de requêtes (HQL : Hibernate Query Language), aucune connaissance approfondie n’est nécessaire. Les connaissances nécessaires peuvent paraître importantes mais cet ouvrage n’est en aucun cas un cours de programmation : il s’adresse avant tout à des personnes ayant une compétence suffisante dans les langages de programmation. En ce qui concerne JAVA, je ne peux que vous conseiller les tutoriels proposés par la société Sun Microsystems elle-même sur son site WEB (http://java.sun.com/). Il sont complets et vous permettront de comprendre rapidement les enjeux de la nouvelle syntaxe introduite dans la version 5 du compilateur. 1.3 Comment s’organise ce livre ? Ce livre présente une solution pour gérer sa médiathèque à travers une interface WEB : le projet KOMPIL7. La création d’un site de référencement musical permet d’expliquer pas à pas la construction d’une application WEB dynamique. L’intérêt d’une application telle que celle proposée est de permettre de répondre à tous les besoins à travers un exemple fonctionnel. CHAPITRE 1. INTRODUCTION 1.4 8 Pourquoi J2EE-like ? JEE (ou J2EE) est une norme et un ensemble d’outils et de normes. Cette norme nécessite deux briques principales : un conteneur Web (tel que Tomcat pour ne citer que le plus connu) et un serveur d’application (WebLogic, JBoss, etc...) Le serveur d’application concentre plusieurs technologies extrêmement intéressantes telles que : – JDNI (Java Directory Naming Interface) : un système permettant de repérer des services tels que l’accès à la base de données et d’autres informations qui permettent de ne pas exposer les données de connexion (tels que le nom de la base de donnée, le mot de passe, etc.) Cette technologie permet de créer des configurations de tests et des configurations de production sans rien toucher au logiciel final. – JTA (Java Transaction API) : une API permettant de synchroniser plusieurs serveurs (généralement un serveur de base de données et un serveur de messages tels que MQSeries) et de gérer les transactions de façon transparente (uniquement à travers des déclarations en XML). – JPA (Java Persistence API) : une API de persistance standard qui permet de déclarer sous forme de classe les entités de la base de données. L’utilisation du framework Spring permet de se passer d’un serveur J2EE. Nous allons voir comment. 1.5 Le prix à payer Quelques efforts et un peu de sueur. La création d’un site WEB via les outils MVC n’est pas excessivement facile et requiert un certain niveau en programmation. En revanche, tous les logiciels utilisés sont gratuits. Dans tous les cas, que vous travailliez sous Windows, U NIX (cela inclut bien évidemment Linux) ou M AC OS, vous pourrez effectuer vos développements et tester les résultats grâce à une technologie entièrement JAVA 1 . C’est la garantie de pouvoir faire tourner votre application partout et, éventuellement, en cluster. 1.6 L’hébergement Une fois votre application terminée, il faut la rendre disponible. À moins qu’il ne s’agisse d’une application d’entreprise hébergée par votre équipe informatique, il faudra la mettre sur la toile. Pour cela, il vous faut trouver un hébergeur. Les hébergeurs classiques proposent pour la plupart des hébergements pour LAMP (PHP, MySQL et Apache). Ce qui ne correspond pas à nos besoins. Jusqu’à récemment, il fallait opter pour un hébergement dédié. Mais, à présent, grâce à la virtualisation des serveurs sous Linux, il est possible de trouver des hébergements permettant d’abriter des serveurs de type J2EE 2 pour un prix relativement 1. Dans certains cas, certaines briques logicielles comme Eclipse utilisent des routines natives, il en va de même si vous optez pour une solution utilisant le serveur HTTP Apache. 2. ou simplement des conteneurs WEB tels que Tomcat ; en effet, nous verrons dans ce livre que la création d’un site WEB en JAVA ne nécessite pas nécessairement d’avoir recours à un serveur d’application tel que WebSphere, JBoss ou JOnAS. CHAPITRE 1. INTRODUCTION 9 correct. Ci-dessous, trois offres qui permettent l’installation d’une application serveur écrite en JAVA. La liste est loin d’être exhaustive puisque de plus en plus d’hébergeurs (en France comme à l’étranger) propose la location des machines pré-configurées soit partagées (ou mutalisées, si vous préférez), soit dédiées. Les offres ci-dessous sont donc purement indicatives, ne concerne que des hébergeurs français et n’engage pas l’auteur de ce livre. L’intérêt est de donner une idée du prix de l’hébergement d’un site en JAVA (à partir d’environ 15 e par mois). 1.6.1 NFrance Située à Toulouse, cette société offre la location de serveurs UNIX grâce à la technologie de virtualisation qui permet d’acquérir tout ou partie de la puissance d’une machine (tant en terme de CPU qu’en terme d’espace disque). Leur offre s’articule autour des solutions VDS (il s’agit d’un terme commercial, la technologie sous-jacente est la virtualisation proposée par http://linux-vserver.org/). Elle propose également des hébergements dédiés aux sites sous JAVA avec un serveur TOMCAT. Il s’agit d’une solution spécifique, toujours basées sur leur solutions VDS. Pour moins de 80 eH.T. par mois, vous pouvez accéder à un hébergement comprenant 80 Go de disque dur, 1 serveur SMTP, mySQL, etc. Leur site web : http://www.nfrance.com/ 1.6.2 Gandi Gandi propose également des solutions de location CPU et disque dur. À partir d’environ 15 eH.T. par mois, vous pouvez héberger un site conçu en JAVA. L’intérêt de leur offre est sans doute l’achat de CPU et de disque dur à la demande et sur des périodes plus ou moins longues. Leur site web : http://www.gandi.net/ 1.6.3 Iliad Iliad (via sa filière Dedibox) propose des machines sous Linux à partir de 30 eH.T. par mois. Cette solution donne droit à un microprocesseur Celeron, 2 Go de mémoire vive et 160 Go de disque dur. C’est une solution digne d’intérêt pour des applications JAVA qui peuvent rapidement consommer beaucoup de mémoire et attirante par la capacité du disque dur proposé. Cependant, il s’agit d’une simple machine hébergée sans sauvegarde. Il est de votre responsabilité de sauvegarder vos données d’une manière ou d’une autre (généralement sur votre machine locale). De plus, une machine de type Celeron n’est pas une bête de compétition. CHAPITRE 1. INTRODUCTION 1.7 10 Règles typographiques Les règles typographiques employées dans ce livre sont standards. 1.7.1 Renvois Les renvois permettent de référencer une section, un chapitre ou une figure dans ce livre. Ainsi, une référence à cette section sera notée : voir section 1.7.1. Le numéro de page n’est généralement pas indiqué. 1.7.2 Liens vers Internet Fréquemment, nous vous renverrons vers les documentations originales, vers des logiciels ou vers des librairies. Pour cela, nous vous donnerons l’adresse de la page WEB à taper dans votre navigateur. Cette adresse commencera toujours par http: ou ftp:. En revanche, la fonte utilisée reste identique à celle du texte. Par exemple : http://www.google.fr/ vous renverra sur la page d’accueil du moteur de recherche Google. 1.7.3 Tables & figures Les illustrations sont insérées sous forme flottante, ainsi les copies d’écrans et les autres éléments graphiques peuvent se trouver dans les pages suivantes et même parfois sur une page dédiée. Chapitre 2 Créer sa première application 2.1 Les pré-requis Pour créer votre application, vous devez installer sur votre machine le minimum vital pour développer. Vous devez tout d’abord installer une version récente du SDK de JAVA ainsi qu’un conteneur WEB (ici, il s’agira de Jetty mais vous pouvez également utiliser Tomcat) et bien entendu l’outil de développement Eclipse. Tous ces logiciels proviennent du monde libre et sont téléchargeables sur Internet. Il est également nécessaire de télécharger différentes librairies formant la base de votre application. Merci de vous référencer au tableau 14.1 pour la liste des composants et la version utilisée dans ce tutoriel (bien entendu, vous pouvez télécharger des versions plus récentes). Sous Windows, nous utiliserons le répertoire C:\tools pour y installer tous nos outils ainsi que notre environnement de développement. Sous unix, on privilégiera le répertoire ~/tools. Ce répertoire sera référencé par la variable $ROOT. Sous Windows, la variable s’écrit %ROOT% si celle-ci a été déclarée dans un fichier batch (ayant l’extension .bat ou .cmd). Dans tous les cas, évitez absolument d’avoir des répertoires contenant des espaces. En effet, l’utilisation d’espaces dans le nom des répertoires (habitude fréquemment observée sous Windows) pose des problèmes de nommage des fichiers lors du passage des paramètres en ligne de commande. Nous vous conseillons de stocker vos téléchargements dans le répertoire $ROOT/download. Il sera noté $DOWNLOADS. 2.2 Télécharger le JDK Le site officiel de JAVA est à l’adresse http://java.sun.com/. Vous y trouverez un menu pour télécharger la dernière version de JAVA. Pour ce tutoriel, vous devez utiliser 11 CHAPITRE 2. CRÉER SA PREMIÈRE APPLICATION 12 la version 5 1 ou supérieure (les versions 1.4 et inférieures ne sont pas compatible avec le développement MVC). Vous devez impérativement charger une version contenant le SDK (pas uniquement la version runtime souvent appelée JRE pour Java Runtime Environment). Une fois le SDK installé, vous allez pouvoir installer l’outil de développement. Le répertoire d’installation préconisé pour le SDK est $ROOT/jdk5. Nous le noterons $JAVA_HOME. Le répertoire $JAVA_HOME a un sens puisqu’il est utilisé nativement pour repérer le répertoire de base de l’installation de JAVA. 2.3 Télécharger Eclipse Eclipse est une IDE (Integrated Development Environment) qui permet de programmer rapidement en JAVA. Cet outil est hébergé à l’adresse http://www.eclipse.org/. Vous pouvez télécharger Eclipse SDK version 3.4 ou supérieur. La figure 2.1 vous montre le site WEB (suceptible de changer). Il faut impérativement télécharger la version permettant la création de sites JEE. Cela permet de simplifier considérablement les soucis de configuration lors de la création du projet. La page de téléchargement est capable de déterminer quel système d’exploitation vous utilisez (Windows, L INUX ou M AC OS). Le téléchargement peut être assez long (> 150 Mo). F IGURE 2.1 – Site de téléchargement Une fois le fichier téléchargé, vous obtenez un fichier .zip (tout au moins sous Windows). Vous devez donc le décompresser dans un répertoire (je vous conseille 1. Les versions de JAVA étaient numérotées 1.1 jusqu’à 1.4 ; ensuite Sun a laissé tombé le 1.x en nommant ces dernières versions JAVA 5 et JAVA 6 CHAPITRE 2. CRÉER SA PREMIÈRE APPLICATION 13 $ROOT/eclipse). Pour ce faire, vous devez un utilitaire de décompression compatible ZIP. Sous Windows(XP ou supérieur), la compression ZIP est directement prise en charge magré cela, de nombreux utiliateurs utilisent WinZIP, 7ZIP ou d’autres programmes équivalent. Une fois le fichier décompressé, Eclipse est prêt à être utilisé. Il suffit de créer un raccourci sur l’exécutable (et le placer sur le bureau pour ceux qui travaillent sous Windows). Une fois installé et l’icône copiée sur le bureau, double cliquez dessus pour démarrer Eclipse. Celui-ci est généralement un peu long à démarrer à cause du chargement de ses informations internes (plug-ins). Une fois démarré, vous pouvez le configurer un peu (nous verrons cela plus tard). 2.4 Créer un projet minimaliste Pour cela, ouvrez Eclipse, puis créez votre nouveau projet comme l’indique la figure 2.2. Il s’agit bien d’un nouveau projet que vous stockerez dans l’espace de travail par défaut de Eclipse ($workspace_loc). Dans Eclipse, le répertoire de travail (le «workspace») est une notion très importante : il détermine la racine de votre environnement de travail JAVA. Bien que certaines ressources puissent être déclarées à l’extérieur du workspace (comme par exemple le code source des librairies utilisées par votre application ou leur documentation), il est préférable d’utiliser le workspace comme répertoire de travail. F IGURE 2.2 – Créer un nouveau projet (1ere partie) CHAPITRE 2. CRÉER SA PREMIÈRE APPLICATION 14 Le deuxième écran de création (figure 2.3) permet de spécifier le nom du projet. Ici, nous avons choisi le nom « Kompil7 » en hommage à un ancien programme écrit en 1991 fonctionnant sous MS/DOS. Le «Project contents» permet de spécifier un répertoire en dehors du workspace ce que je déconseille. Le répertoire où seront stockés les fichiers du projet sera donc $workspace_loc/kompil7. Notez l’importance de préciser le nom du projet en lettres minuscules afin d’éviter les problèmes de casse (minuscule/majuscule) pour les utilisateurs L INUX. Le «Target Runtime» est laissé vide. En effet, même si on peut créer des cibles en terme d’installation (typiquement installer son développement sur Tomcat) ce qui peut simplifier la mise en place du projet, nous avons préféré conserver la méthode manuelle pour entrer dans le détail des opérations nécessaires au bon fonctionnement d’une application WEB. La version du modèle Web dynamique peut être conservé en 2.4 (cela n’a pas d’impact majeur sur nos développements). F IGURE 2.3 – Créer un nouveau projet (2e partie) Il est temps de configurer le «Web Module». Laissez les informations déterminées par Eclipse (voir section 2.4). Pour information, les données décrivant les pages WEB (le code HTML et CSS) seront stockés dans le répertoire “WebContent” tandis que le code source JAVA sera stocké dans le répertoire src. Cette séparation entre les classes JAVA et les pages est importante : en effet, on CHAPITRE 2. CRÉER SA PREMIÈRE APPLICATION 15 F IGURE 2.4 – Définition des répertoires peut considérer que la partie «présentation» est stockée uniquement dans la partie WebContent tandis que les « composants métier » sont dans la partie src (ainsi que l’accés aux données de la base et la partie controller). Dans la partie gauche de l’écran (voir figure 2.5) apparaît les différentes parties de notre projet. La perspective hJava EEi 2 permet de visualiser l’ensemble des informations utiles à votre projet. – Deployment descriptor : Kompil7 – cette partie décrit le contenu du fichier web.xml de votre projet. C’est ce fichier (que nous verrons en détail section 2.6) qui explicite votre projet au conteneur WEB. – Java Resources : src – contient le code JAVA de votre application : les packages et toutes le code source des classes. La partie « hLibrariesi » permet de stocker les librairies (fichiers .jar) utiles à votre application. Elle est divisée en trois sous-catégories : – EAR Libraries – les libraries utilisées par le serveur d’application (dans notre cas, il n’y en aura aucune). – JRE System Library – la librairie système (c’est à dire JRE 1.5 : le Java Runtime Environment de JAVA 5.0) ; cette librairie est directement gérée par Eclipse. – Web App Libraries – c’est dans cette section que l’on ajoutera toutes les librairies (.jar) nécessaires à votre application (entre autres : Spring, Struts, Hibernate, etc.) ; comme vous le découvrirez rapidement, cette partie peut 2. La perspective est une notion clé du logiciel Eclipse. Chaque perspective permet d’afficher les informations pertinentes avec des « vues » différentes adaptées au travail en cours : développement JAVA classique, développement WEB, débuggage de l’application, etc. CHAPITRE 2. CRÉER SA PREMIÈRE APPLICATION 16 F IGURE 2.5 – Détail d’un projet WEB vide contenir énormément de librairies du fait que la création d’une application WEB est avant tout une démarche « assembliste » 3 . – build – la partie construite de l’application. Eclipse y ajoutera tout les classes de votre application. De notre côté, nous y ajouterons les librairies nécessaires au conteneur WEB. – WebContent – la partie web de l’application contenant également un répertoire WEB-INF indispensable à une application WEB (nous en verrons les détails dans le chapitre suivant). En revanche, le répertoire META-INF utile pour décrire une application JAVA et, éventuellement, la classe contenant la méthode main n’a pas réellement de justification dans une application JAVA 4 . – JavaScript Support – cette partie peut-être ignorée pour l’instant. Il est important de vérifier la partie «Java Compiler». Votre version de SDK JAVA doit être 5 ou supérieure. À partir la figure 2.5, faites un clic droit de souris sur le nom du projet, et sélectionnez hPropertiesi. Vous devez voir une fenêtre ressemblant à celle de la figure 2.6. Il est important de vérifier la compatibilité de votre compilateur JAVA. Une version 1.5 ou supérieure est nécessaire. En fait, les numérotations des versions du JDK sont brusquement passées de 1.4 à 5.0 ! Malgré cela, les versions continuent à apparaître comme 1.5 ou 1.6 dans certaines parties d’Eclipse. 3. En opposition à la programmation pure qui consiste à écrire un maximum de code à partir d’un ensemble minimum de librairies 4. à moins d’embarquer un conteneur WEB afin d’avoir une application JAVA totalement indépendante et pouvant être lancée sur un poste client à l’instar d’une application de type client, nous aborderons le sujet avec l’utilisation de Jetty comme conteneur WEB. CHAPITRE 2. CRÉER SA PREMIÈRE APPLICATION F IGURE 2.6 – Propriétés de compilation 17 CHAPITRE 2. CRÉER SA PREMIÈRE APPLICATION 2.5 18 Comment se présente une application WEB ? Une application WEB a des contraintes d’organisation. Par définition, une application WEB est stocké dans un fichier archive dont l’extension est .war (pour Web ARchive 5 ou, éventuellement, .ear (pour Entreprise ARchive dans le cas d’une application liée à un serveur d’application J2EE comme JBoss, WebSphere, etc.). Dans ce fichier d’archive, on retrouvera les répertoires suivants : – la racine : elle va contenir toutes les pages WEB de votre application (.html, .jsp, .ftp, etc.) ainsi que les feuilles de styles et touts les fichiers images. Bien entendu, des sous-répertoires peuvent être créé afin de faciliter le rangement et l’accès aux données. Par définition, tous ces fichiers sont accessible via une URL. – META-INF est un répertoire réservé pour stocker des informations relatives à votre artchive. Il est facultatif. – WEB-INF ce répertoire est indispensable et doit être écrit en majuscules impérativement (le langage JAVA est sensible à la casse). Il contient des données vitales pour votre application est il est « protégé »(c’est à dire que les fichiers ne sont pas accessibles à l’utilisateur). 2.5.1 Le répertoire WEB-INF Sun Microsystems a indiqué plusieurs règles pour créer des applications WEB. L’une d’entre elle (et la principale) définit l’existence d’un répertoire WEB-INF à la racine du fichier .war. Pour information, le fichier .war est un fichier compressé comprenant tous les fichiers de votre application (c’est à dire les classes compilées ainsi que les autres fichiers). Un fichier .war est en tout point identique à un fichier .jar (Java ARchive) mais, par définition, son utilisation est réservée aux applications WEB. Le répertoire WEB-INF est extrêmement standardisé, il doit comporter un fichier web.xml qui va définir votre application et qui va être interprété par le conteneur WEB 6 (c’est à dire, la plupart du temps, Tomcat). Dans ce répertoire /WEB-INF, vous trouverez également le sous-répertoire lib destiné à stocker les librairies utilisées par l’application (elles sont généralement assez nombreuses). Là encore, le nom lib est imposé. Les librairies se trouvant dans le répertoire /WEB-INF/lib seront automatiquement disponibles (il n’est pas utile, contrairement à une application JAVA classiques d’intégrer toutes les librariries dans le CLASSPATH). Un deuxième sous-répertoire imposé est classes qui va contenir toutes les classes JAVA de votre application (extension .class). Ce répertoire /WEB-INF/ classes est sous-divisé en sous-répertoires correspondants aux paquets (packages) JAVA. Ce répertoire est alimenté par la compilation de votre code source et par les fichiers ressources se trouvant dans la partie Java Resources : src de votre environnement de travail. 5. C’est le même principe d’appelation que pour les fichiers JAR (Java ARchive). 6. en anglais, le terme employé est web container. CHAPITRE 2. CRÉER SA PREMIÈRE APPLICATION 2.6 19 Le fichier /WEB-INF/web.xml Le fichier web.xml est stocké dans le répertoire /WEB-INF impérativement. C’est ce fichier qui sera recherché par le conteneur WEB qui démarre votre application. Il s’agit d’un fichier XML dont la structure a été dictée par Sun Microsystems. La figure 2.9 vous montre la structure d’un fichier web.xml vide (il a déjà été créé par Eclipse). Les figures 2.7 et 2.8 permettent d’avoir une vision pure (le format source du fichier) ou une vision en arbre (ce qui est la vision normale d’un fichier XML puisque celui-ci décrit avant tout des structures hiérarchiques). F IGURE 2.7 – Fichier web.xml dans Eclipse (source) Un fichier web.xml vide ressemble à peu prés à celui de la figure 2.9. C’est ce fichier que nous allons enrichir (en même temps que le répertoire contenant les librairies afin de donner à l’application différentes fonctionnalité (en particulier son framework MVC). C’est en effet dans ce fichier que vous allez définir les servlet à utiliser et comment les utiliser (la version 2.4 des applications WEB préfèrent parler de filtres et de listeners 7 ). On y voit également la liste des fichiers à utiliser par défaut dans les URL indiquant des répertoires (nous verrons cela plus loin). Notez que l’ordre est très important dans un fichier web.xml. En effet, le nonrespect de la DTD (Document Type Definition) va empêcher votre application de démarrer. 2.7 Hello World ! La première application est toujours celle qui affiche « Hello World ! ». Tel un nouveau né sortant de son œuf. Qu’à cela ne tienne, nous allons créer la première des 7. le terme français d’écouteur n’est pas très beau, j’ai préféré gardé dans ce livre le terme anglais) CHAPITRE 2. CRÉER SA PREMIÈRE APPLICATION F IGURE 2.8 – Fichier web.xml dans Eclipse (conception) 1 6 <?xml version="1.0" encoding="UTF-8"?> <web-app id="Kompil7" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>Kompil7</display-name> </web-app> F IGURE 2.9 – Fichier web.xml vide 20 CHAPITRE 2. CRÉER SA PREMIÈRE APPLICATION 21 applications. 2.7.1 Le serveur (ou conteneur) WEB Pour cela, il nous manque tout d’abord le conteneur. C’est l’élément principal : celui qui va piloter l’application. Le conteneur WEB est chargé de prendre en charge les requêtes HTTP ainsi que l’envoi de la réponse au client. Il se charge de gérer le protocole HTTP et se contente de déléguer le travail d’analyse et d’affichage à des servlets. Ce sont des classes qui prennent en compte la requête. Certains servlets peuvent être empilés pour effectuer une gestion complète de la requête de l’utilisateur 8 . Il existe plusieurs conteneurs mais ils répondent aux mêmes exigences : celles fixées par Sun Microsystems. Vous pouvez donc très bien utiliser un conteneur différent entre les environnements de tests et celui de production. Ainsi, nous vous proposons d’utiliser Jetty comme conteneur pour le développement de notre application. Celuici est léger et a été packagé dans des libraries JAVA ce qui nous permet de tester notre application WEB comme une application JAVA standard. Plus tard, pour la mise en production, nous envisagerons d’utiliser Tomcat. Vous verrez que votre développement ne nécessite aucune modification. Le téléchargement de Jetty peut se faire sur le site de l’application (http://www.mortbay.org/jetty/). Une fois le fichier jetty-6.1.11.zip téléchargé, ouvrez-le. Vous y trouverez 3 fichiers indispensables dans le répertoire jetty-6.1.11/lib : jetty-6.1.11.jar, jetty-util-6.1.11.jar et servlet-api-2.5-6.1.11.jar (comme vous pouvez le voir dans la figure 2.10). Normalement, vous devriez pouvoir glisser et déplacer (avec la souris) ces 3 fichiers vers Eclipse dans le répertoire build. Si ce n’est pas possible, copier les trois fichiers dans le répertoire /kompil7/build dans le workspace d’Eclipse (${workspace_loc}) ; dans ce cas, il faudra rafraîchir le workspace (clic droit sur le projet, puis choisir hRefreshi (la touche F5 peut également être utilisée). F IGURE 2.10 – Librairies indispensables 8. C’est notamment le cas, comme vous le verrez plus loin, du servlet Sitemesh qui vient en fin de chaîne pour « décorer »la page WEB générée. CHAPITRE 2. CRÉER SA PREMIÈRE APPLICATION 22 On y est presque... Il nous faut maintenant expliquer à Eclipse que ces trois librairies doivent être prises en compte. Rien de plus facile, pour cela, choisissez dans le menu hProject > Propertiesi. La figure 2.11 vous montre comment intégrer ces 3 libraries dans le chemin d’exécution d’Eclipse (le CLASSPATH de JAVA). Cette inclusion est nécessaire mais elle ne doit pas se faire dans le répertoire /WEB-INF/lib car ces librairies appartiennent au conteneur et non à l’application elle-même. En effet, Dans le cas de Tomcat (par exemple), il est inutile d’intégrer ces librairies, c’est pourquoi, il faut considérer ces libraries comme «Librairies» et non comme «Web App Libraries». F IGURE 2.11 – Inclusion des librairies 2.7.2 La classe principale Puisque maintenant le conteneur Jetty est maintenant disponible, il faut écrire la classe principale (c’est à dire une classe qui contient une méthode main). C’est le principe de Jetty. Plutôt que d’avoir un service (c’est le cas avec Tomcat), on aura une simple application JAVA ce qui va alléger le lancement de votre application WEB et évitera dans certains cas l’arrêt et la relance du serveur. Nous allons créer pour cela le paquet « jetty » qui va contenir la classe nécessaire au démarrage de votre application WEB. Bien entendu, nous aurions pu choisir d’utiliser un fichier XML plutôt qu’une classe JAVA mais la présence d’une classe n’est pas une mauvaise idée car cela va éventuellement nous permettre de lancer efficacement notre CHAPITRE 2. CRÉER SA PREMIÈRE APPLICATION 23 application. Le fichier Run.java doit étre créé. Celui-ci va contenir le démarreur de votre application. Celui va être assez simple. Pour créer une classe dans Eclipse, rien de plus simple, choisissez hFile > New > Other...i puis dans la liste, hJava > Classi. Cliquez sur le bouton hNext >i. la figure 2.12 vous montre les caractéristiques de la classe JAVA à créer. F IGURE 2.12 – Classe Run Une fois créée, il suffit d’ajouter les imports nécessaires (Eclipse s’en occupera tout seul si vous demandez la completion du nom des classes lors de la saisie). La figure 2.13 vous montre les imports à ajouter. Attention, ces classes sont spécifiques au serveur Jetty 6 (la compatibilité avec Jetty version 7 n’est pas garantie). import org.mortbay.jetty.Server; import org.mortbay.jetty.webapp.WebAppContext; F IGURE 2.13 – Import des classes du conteneur Encore un petit effort, la méthode main de la classe jetty.Run doit ressembler à la figure 2.14. Aux lignes 2 & 3, on définit un serveur qui écoutera sur le port 8041 (à priori n’importe quel port d’écoute disponible fait l’affaire, y compris le port 80 qui est le port d’écoute par défaut des serveurs WEB). CHAPITRE 2. CRÉER SA PREMIÈRE APPLICATION 24 public static void main(String[] args) throws Exception { int listeningPort = 8041; Server server = new Server( listeningPort ); 3 WebAppContext webApp = new WebAppContext(); webApp.setWar( "./WebContent" ); webApp.setExtraClasspath("./build/classes/"); webApp.setContextPath("/kompil7"); 8 server.addHandler(webApp); server.start(); } F IGURE 2.14 – Méthode main() de la classe Run Une fois le serveur créé, il faut créer un contexte pour l’application WEB (en fait, un conteneur peut héberger plusieurs applications WEB, dans notre exemple, on se contentera d’une seule application). Ce sont les lignes 5 à 8 qui définissent l’application WEB : – setWar va définir le répertoire de base de votre application : celle où se trouve les pages WEB du site et plus exactement le nom du répertoire contenant WEB-INF. Étant donné les répertories créés par Eclipse, il s’agit du répertoire |WebContent| se trouvant dans le workspace. – setExtraClasspath permet d’ajouter un chemin supplémentaire (un seul possible). Cette option est indispensable car Eclipse n’ajoute pas nos classes dans WEB-INF/classes mais dans build/classes. Notez le “/” final obligatoire. – setContextPath permet de fixer le contexte d’exécution de votre application. Par défaut, il s’agit de “/” (le répertoire de base de votre serveur) mais vous pouvez modifier cela avec cette méthode. Ainsi, notre serveur sera à l’adresse http://localhost:8041/kompil7/ 2.7.3 Le lanceur Une fois le conteneur en place et le fichier de lancement en place, il suffit de créer un lanceur (c’est à dire un appel à la classe principale, caractérisée par la méthode main). La figure 2.15 vous montre les différents paramètres mais, par définition, la création d’un nouvelle configuration de déboguage via le menu hRun > Debug Configurations...i est totalement automatique. Pour cela, vous devez simplement cliquer sur la classe Run.java dans le Project Exporer. Une fois le lanceur créé, vous pouvez le lancer directement en cliquant sur le bouton hDebugi. Si tout ce passe bien, quelques messages d’erreurs (c’est à dire affichés en rouge) doivent apparaître dans la console comme le montre la figure 2.14. Notez que le début de la ligne n’est pas significatif (il s’agit de la date et de l’heure). Les différents messages indiquent : 1. les logs sont envoyés vers la sortie standard (stderr) ; 2. la version du conteneur Jetty (6.1.11) ; 3. que le support des pages JSP n’est pas actif (nous verrons cela au chapitre suivant) ; 4. que le serveur a bien démarré en écoute sur le port 8041. CHAPITRE 2. CRÉER SA PREMIÈRE APPLICATION 25 F IGURE 2.15 – Créer le lanceur 2008-09-15 2008-09-15 2008-09-15 2008-09-15 23:58:39.483::INFO: 23:58:40.686::INFO: 23:58:40.249::INFO: 23:58:40.624::INFO: Logging to STDERR via org.mortbay.log.StdErrLog jetty-6.1.11 NO JSP Support for /kompil7, did not find org.a Started [email protected]:8041 F IGURE 2.16 – Messages du serveur Jetty CHAPITRE 2. CRÉER SA PREMIÈRE APPLICATION 26 Sur ces bonnes nouvelles, il suffit de tester si tout fonctionne bien en tentant dans un navigateur quelconque de se connecter à l’URL http://localhost:8041/kompil7/ 9 À ce moment là, devrait s’afficher la liste des répertoires existants à savoir : META-INF/ et WEB-INF/ ainsi que leur caractéristiques (taille et date de dernière mise à jour). En effet, si aucun fichier par défaut n’existe, Jetty va se comporter comme le serveur Apache (et la quasi-totalité des serveurs WEB) en affichant la liste des fichiers du répertoire. 2.7.4 3 Hello world ! <head> <title>Homepage</title> </head> <body> <h1>Hello World!</h1> </body> F IGURE 2.17 – Le fichier index.html Qu’à cela ne tienne, nous y sommes presque. Il suffit de créer un fichier HTML index.html dans le répertoire WebContent. Pour cela, nous allons rester très sobre comme le montre la figure 2.17. Si tout c’est bien passé, la partie Project Explorer d’Eclipse doit ressembler à la figure 2.18. Pour vérifier que tout se passe bien et que le fichier index.html est pris en compte, rafraîchissez la page WEB dans votre navigateur et le message « Hello World ! » doit s’afficher (en gros caractères). Nous avons donc réussi (remarquez au passage que nous n’avons pas redémarré le serveur et que la prise en compte de notre page WEB a été immédiate). Fier de ce premier succés, nous allons aborder à présent les choses sérieuses en améliorant notre application. Les fichiers qui composent ce chapitre sont disponibles à l’adresse http://wrey.free. fr/articles/j2ee/files/kompil7-chap2.zip sous la forme d’un fichier ZIP. 9. Votre machine est toujours nommée localhost, c’est une règle. Vous pourriez très bien utiliser l’IP 127.0.0.1 ou votre adresse IP 192.168.x.y si vous être sur un réseau local derrière un routeur ce qui typiquement le cas des personnes ayant une boîte ADSL. CHAPITRE 2. CRÉER SA PREMIÈRE APPLICATION F IGURE 2.18 – Explorateur du projet pour Hello World ! 27 Chapitre 3 Les choses sérieuses 3.1 Un peu d’interactivité Jusque là, nous avons créé une application qui ne distingue guère d’un site WEB fait avec des pages WEB statiques. Cela signifie que nous avons dépensé beaucoup d’énergie pour pas grand chose. Donc, nous allons rendre notre fichier de bienvenue un peu plus interactif. Pour cela, nous allons renommer le fichier /index.html en /index.jsp (pour renommer un fichier, allez dans l’explorateur d’Eclipse, vous sélectionnez le fichier et vous tapez sur la touche F2 qui est le raccourci normal pour renommer le fichier). Une fois cette opération effectuée, nous allons recharger la page http://localhost:8041/kompil7/. Sur la console (dans Eclipse), vous devriez obtenir une erreur 500 : JSP support not configured avec comme URI : /kompil7/index.jsp. Tout cela parce que le support des pages JSP n’est pas installé. Dans Jetty, le support des pages JSP est assurée par les librairies Apache (celle contenant la classe org.apache.jasper). Vous devez récupérer dans l’archive de Jetty (précédemment téléchargée) les fichiers permettant le support des Java Server Pages également connues sous le nom de JSP). Les fichiers se trouvent dans le répertoire jetty-6.1.11/lib/jsp-2.1. Ces librairies doivent être copiées dans le répertoire /build de Eclipse. Ensuite, il faudra encore une fois déclarer ces librairies comme utilisables par le projet. Il n’est pas possible de les intégrer directement dans le répertoire /WEB-INF/lib car elles ne font pas partie du projet mais font partie intégrante des librairies nécessaires à Jetty. Comme le montre la fig. 3.1, il s’agit ensuite d’ajouter ces librairies dans le CLASSPATH de l’application Jetty. Pour cela, le serveur doir être arrêté. Puis redémarré une fois les librairies prises en compte. Cette fois-ci, les messages affichées lors du démarrage de l’application n’affichent plus d’avertissement quant à la prise en charge des pages JSP. Pour vérifier que tout fonctionne, rechargez la page via l’URL http://localhost: 8041/kompil7 : tout devrait fonctionner. Maintenant, nous allons ajouter de l’interactivité en permettant à la page d’afficher un contenu dynamique. Cela va se faire très simplement en modifiant le fichier /index.jsp comme le montre la figure 3.2. 28 CHAPITRE 3. LES CHOSES SÉRIEUSES F IGURE 3.1 – Ajout des libraries JSP 4 <head> <title>Homepage</title> </head> <body> <h1>Hello world!</h1> Time is <%= new java.util.Date() %> </body> F IGURE 3.2 – Le fichier hello en JSP 29 CHAPITRE 3. LES CHOSES SÉRIEUSES 30 La ligne 6 est ajoutée au fichier d’origine. Les notations <% et %> permettent d’intégrer du code JAVA dans la page WEB donnant une grande interactivité. Le signe égal permet de dpécifier l’affichage d’une information (comme le ferait System.println en JAVA). La création d’un objet de type Date permet d’obtenir très facilement une information qui change fréquemment (toute les secondes) dans un premier exmple vite mis en œuvre. Notez la nécessité de qualifier dans son intégralité le nom de la classe si on veut qu’elle soit reconnue. Il existe également l’alternative de faire appel à des « imports » comme dans le langage JAVA classique. Pour cela, on utilise des invocations telles que <%@page import="java.util.*" %>. Quelques notes personnelles : JSP (Java Server Pages) est le langage officiel pour les sites WEB. Tout conteneur WEB doit impérativement être capable d’interpréter le code JSP (en fait, la page JSP est compilée une première fois et à chaque modification puis exécutée comme du code JAVA classique). On notera qu’en tant que « langage officiel », il est inutile de déclarer une quelconque option dans le fichier web.xml. Dans ce livre, nous n’utiliserons à priori pas le JSP pour construire nos pages mais un autre langage plus proche du langage de script : FreeMarker. Pour interpréter du code FreeMarker, il est d’ailleurs inutile d’avoir le support JSP (comme nous allons le voir très bientôt). 3.2 Sitemesh Bien entendu, notre page reste un peu triste. C’est normal : pas de page de style (les fabuleaux CSS pour Cascading Style Sheets permettant de séparer le contenu de la présentation), pas de menu. C’est vraiment vide. La première solution pour améliorer la page serait de créer deux fichiers d’en-tête à inclure avant et aprés le texte de la page : c’est la méthode généralement utilisée dans des applications PHP où l’on va retrouver un code proche de celui présenté à la fig. 3.3. 3 <? include "../header.php" ?> <h1>Hello World!</h1> <? include "../footer.php" ?> F IGURE 3.3 – Un fichier PHP basique Dans l’exemple de la fig. 3.3, on voit la simplicité de la technique : créer un en-tête (header) et un pied de page (footer) ce qui permet de créer le haut et le bas de la page. Le header va contenir la partie <head> du code HTML ainsi que le menu et les parties généralement présentes sur la partie haute ou sur le côté gauche de la page. Tanque que le footer va permettre l’affichage du bas de la page. Ce genre de fonctionnement présente cependant quelques inconvénients : – le code doit être inséré dans toutes les pages du site ; – le code à insérer est relatif à la page dans la hiérarchie du site (si vous déplacez la page dans un autre répertoire d’un niveau différent, vous devrez corriger le chemin d’inclusion). CHAPITRE 3. LES CHOSES SÉRIEUSES 31 – le header et le footer peuvent être accessibles de l’extérieur (risque faible car si l’extension reste .php, le code sera exécuté et non affiché en clair). – il est parfois nécessaire de passer des paramètres au header (typiquement le titre de la page). En JAVA, il est possible d’utiliser une autre technique : un filtre qui va gérer cela lui-même. Ce filtre s’appelle SiteMesh. Ce logiciel est en fait une simple librairie qu’il conviendra d’ajouter (comme toutes celles qui vont suivre) dans le répertoire de libraries /WEB-INF/lib afin qu’il soit pris en compte par le conteneur WEB. SiteMesh est téléchargeable à l’adresse http://www.opensymphony.com/sitemesh/ download.action. La version 2.3 ou supérieure conviendra parfaitement. Veuillez télécharger le fichier sitemesh-2.3.jar et le copier dans le répertoire /WEB-INF/ lib pour qu’il soit correctement pris en compte. Une fois la librairie ajoutée, il convient d’y faire référence en ajoutant le code suivant dans le fichier /WEB-INF/web.xml comme le montre la fig.3.4. En effet, il est nécessaire de déclarer le nouveau filtre de manière explicite. Le tag <filter> permet de donner le filtre SiteMesh (à savoir la classe et un nom logique utilisé dans le reste du fichier web.xml). Une fois cette définition donnée, il faut également préciser sur quelles pages le filtre SiteMesh sera appliqué. Comme c’est souvent le cas, on appliquera le filtre sur l’intégralité des pages WEB (en précisant /* comme paramètre du tag <url-pattern>. 2 7 <filter> <filter-name>sitemesh</filter-name> <filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class> </filter> <filter-mapping> <filter-name>sitemesh</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> F IGURE 3.4 – Le filtre SiteMesh Ce n’est pas terminé, pour pouvoir profiter de SiteMesh, il faut également déclarer le décorateur à utiliser (le terme decorator est le terme anglais appliqué à la solution SiteMesh ). Pour cela, nous créons un fichier nommé /WEB-INF/decorator.xml (le nom est le nom par défaut pour l’application SiteMesh, si ce fichier n’existe pas vous rencontrerez de nombreuses erreurs lors du démarrage de votre application). La fig. 3.5 vous montre un fichier /WEB-INF/decorators.xml minimaliste. Celui-ci comporte uniquement le filtre des fichiers qui vont être « decorés » (il s’agit d’une redondance avec le fichier web.xml qui s’explique par le fait qu’ici on détermine quel décorateur sera appliqué tandis que le fichier web.xml indique sur quelles requêtes doivent s’appliquer le filtre SiteMesh ). Le décorateur par défaut se nomme “main” agira sur toutes les pages et sera défini dans /decorator/main.jsp. Struts 2 est la partie la plus intéressante de votre application car c’est ce logiciel qui va effectuer les traitements fonctionnels, ceux de votre application. Grâce à l’utilisation conjointe de Spring, le code à écrire se révèle très simple. De plus, l’utilisation des fichiers de configuration écrits en XML permettent de limiter les lignes de code en CHAPITRE 3. LES CHOSES SÉRIEUSES 2 32 <?xml version="1.0" encoding="ISO-8859-1" ?> <decorators defaultdir="/decorators"> <decorator name="main" page="decorator/main.jsp"> <pattern>/*</pattern> </decorator> </decorators> F IGURE 3.5 – un fichier decorators.xml minimaliste configurant les tâches les plus courantes. Très souvent, Struts 2 est en contact étroit avec XWork. Comme les deux sont intimement liés, nous parlerons de Struts 2 y compris dans le cas de XWork. De fait, c’est XWork qui effectue tout le travail : gestion des actions, des intercepteurs et des validateurs. Pour s’en convaincre, il suffit d’aller dans le code de xwork.jar. 3.3 Définition d’un fichier xwork.xml Un fichier xwork.xml contient la configuration nécessaire pour chacune des fonctions de votre site (en fait, on y définit le fonctionnement de certaines pages et leur fonctions et comment elles doivent être visualisées). La figure 3.6 montre un fichier minimal pour le fichier xwork.xml. On y trouve une référence à la DTD (actuellement en version 1.1.1) suivi de l’inclusion d’un fichier nommé webwork-default.xml. <?xml version="1.0" encoding="ISO-8859-1"?> 4 9 <!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.1.1//EN" "http://www.opensymphony.com/xwork/xwork-1.1.1.dtd"> <xwork> <include file="webwork-default.xml" /> </xwork> F IGURE 3.6 – Fichier xwork.xml minimal. Le fichier webwork-default.xml définit des intercepteurs ainsi que des modèles de base pour la visualisation des pages. Il est nécessaire de l’inclure pour chaque application utilisant Struts 2. Le fichier webwork-default.xml est contenu à la racine de la librairie webwork-2.2.2.jar. 3.3.1 Créer un raccourci pour les getters/setters Sous Eclipse, il est possible de créer automatiquement le getter et le setter d’une variable. Pour cela, vous devez, par défaut, effectuer un clic droit sur votre souris puis choisir l’option « Source > Generate Getters & Setters... », c’est assez fastidieux. Il CHAPITRE 3. LES CHOSES SÉRIEUSES 33 est intéressant de créer un raccourci. En effet la création des getters et setters est une tâche répétitive lors du développement et vous gagnerez un temps fou en ayant cette fonctionalité directement disponible. F IGURE 3.7 – Raccourcis claviers Pour créer ce raccourci sous Eclipse, c’est assez simple : dans le menu principal, sélectionnez Window / Preferences..., la boite de préférences apparaît, sélectionnez dans le menu de gauche General / Appearance / Keys, vous devez voir une fenêtre ressemblant à la fig. 3.7. il suffit de remplir les zones comme indiqué et la touche de raccourci ALT + “G” vous permettra de créer getters et setters automatiquement. Il existe 5 niveaux d’abstraction dans les sites WEB à base de la technologie J2EE : – la page WEB qui affiche le contenu grâce à un langage tel que JSP ou Freemarker ; – le controller qui permet d’analyser les entrées de l’utilisateur ; – les services qui sont en fait le cœur du système. – les DAO (pour Data Access Object) qui sont les objets qui permettent d’accéder aux données de la base ; – le repository (c’est à dire la base de données elle-même). 34 Chapitre 4 Les actions 4.1 Introduction Dans un contexte MVC (modèle vue/contrôleur), les actions jouent le rôle du contrôleur. La vue, elle, sera rendue (c’est-à-dire affichée à l’écran). Par définition, les actions sont définis dans le fichier xwork.xml qui doit se trouver à la racine de votre CLASSPATH. Nous vous conseillons de le mettre dans ${WORKSPACE}/src/java. 4.2 Références externes Il est possible de passer des « références externes ». On s’attends donc à pouvoir passer des beans déclarés au niveau de Springavec une certaine facilité. En ce qui concernent les objets beans ayant un setter au niveau de l’action Struts 2 et ayant le même nom que le bean lui-même, il n’y a pas de problème et il est inutile d’utiliser les références externes. Par exemple, si vous avez un bean dénommé myBean, vous pouvez écrire le code suivant (fig. 4.1) et utiliser directement votre bean sans pour autant utiliser les références externes. 1 private MyBean myBean public void setMyBean( MyBean myBean ){ this.myBean = myBean; } 6 public MyBean getMyBean(){ return this.myBean; } F IGURE 4.1 – Exemple d’auto-wiring Spring. En revanche, si votre objet ne porte pas le même nom, vous avez devoir faire appel aux références externes. Alors que l’utilisation de Spring à l’intérieur de Struts 2 est 35 CHAPITRE 4. LES ACTIONS 36 extrêmement simple, l’utilisation des références externes demande un codage supplémentaire au niveau du package XWork . Pour cela, vous devez déclarer la classe com.opensymphony.xwork. spring.SpringExternalReferenceResolver comme « externalReferenceResolver ». Ceci doit être fait au niveau package. On pourrait croire que cela suffit, mais vous avez oublié l’essentiel : l’intercepteur. Dans ce même package, vous devez définir l’intercepteur qui va gérer les références externes. Créer donc un « reference-resolver » qui fait référence à la calsse com.opensymphony.xwork.interceptor. ExternalReferencesInterceptor. La fig. 4.2 vous montre où ajouter l’intercepteur dans la pile des intercepteurs. 1 <interceptor-stack name="myDefaultWebStack"> <interceptor-ref name="completeStack"/> <interceptor-ref name="reference-resolver"/> </interceptor-stack> F IGURE 4.2 – Ajout d’un intercepteur dans la pile 4.3 L’action de login Généralement, tous les sites WEB proposent une partie « privée » permettant la modification de certains paramètres personnels ou simplement d’accéder à des fonctions personnalisées. Chapitre 5 Spring Spring est un Inversion Of Control (IoC) qui travaille en parfaite harmonie avec Struts 2. Spring permet plusieurs choses en autres : – la gestion des « beans », c’est à dire la possibilité d’utiliser des objets JAVA à travers votre applicatif ; – la possibilité de donner de setter (c’est à dire d’appeler une méthode setXXX) dans vos objets (cela permet, par exemple, de récupérer la connexion à une base de données sans avoir à créer la connexion soi-même) ; – vous offrir différents objets permettant d’accéder et de traiter facilement des informations stockées en base de données. Ceci est la liste principale de ses capacités, mais vous pourrez vous apercevoir de sa puissance au fur et à mesure que vous découvrirez la puissance du J2EE-like. Spring reste le plus souvent invisible puisque son travail consiste essentiellement à appeler les méthodes setXXX de vos objets JAVA standards (vos POJOs). Une chose à savoir : Spring ne correspond à aucune norme, en fait, c’est une sorte de pieuvre géante capable de s’adapter à énormément de produits (Hibernate, Struts 2, etc.) : il ne propose qu’un manière particulière d’accéder à l’information ou aux services proposés par ces autres logiciels. Il permet également de simplifier l’écriture de vos services si ceux-ci sont des beans. 5.1 Les Plain Old Java Objects Cette expression désigne des objets JAVA standards. À priori, n’importe quelle classe JAVA donne lieu à l’instanciation de ces objets POJOs. Dans une architecture J2EE pure, il existe des EJB (Entreprise Java Bean). Ceux-ci ont la particularité d’être des objets plutôt complexes puisqu’ils ont la particularité de posséder une partie cliente (exécutée dans votre application ou dans un conteneur de JSP 1 ) et une partie serveur qui tourne sur un serveru d’application 2 ). Cette conception complexe oblige à créer deux objets dont l’un est une coquille vide (la partie cliente) et l’autre la partie métier (plus connue sous sa dénomination 1. tel que TOMCAT, Jetty, etc. 2. tel que BEA WebLogic, JBOSS, etc. 37 CHAPITRE 5. SPRING anglaise businness). 38 Chapitre 6 FreeMarker FreeMarker est un langage orienté WEB permettant de créer des scripts à l’intérieur de pages. Il peut utiliser facilement des objets JAVA et peut se révéler très puissant. Celui-ci change des habitudes si on le compare à des langages comme PHP ou JAVA. Ces derniers ayant une balise ouvrante et acceptant du code de type séquentiel, c’est-à-dire de vrais programmes. A contrario, FreeMarker est plus limité car il offre un nombre limité d’instruction et se contente de macros pour améliorer son langage. Il peut également utiliser des objets JAVA pour les opérations orientés métier. Vous pouvez trouver la documentation FreeMarker en ligne à l’adresse http://www. freemarker.org/docs/index.html. Celle-ci est en anglais et très bien faite. Néanmoins, ce chapitre va vous montrer quelques aspect de ce langage. 6.1 Syntaxe de base FreeMarker utilise une syntaxe de type balise XML. Il existe deux types de balises : les balises internes, par exemple : <#foreach ...></#foreach> ou <#assign var1="toto" /> et les balises utilisateur (macros, fonctions ou extensions JAVA) notés <@toto /> ou <@toto></@toto>. Bien entendu, l’affichage des variables s’effectue comme dans les scripts Unix ou PHP en écrivant ${variable}. 6.2 Création de formulaires Ceci est une fonctionalité Struts 2 automatiquement accessible dans FreeMarker grâce aux librairies de tags. Vous pourrez trouver une définition complète des tags de formulaires à l’adresse : http://wiki.opensymphony.com/display/WW/Form+Tags. À COMPLÉTER... 39 Chapitre 7 Hibernate Avec Hibernate, il est possible de s’affranchir de plusieurs inconvénients liés aux bases de données : – la structure relationnelle qui oblige quelques manipulations au niveau du code JAVA ; – la gestion des transactions ; – la non-compatibilité des bases de données 1 . Hibernate présente également quelques défauts qui peuvent être surmontés assez facilement. En particulier, cet outil n’est pas conçu pour gérer de grands resultSet. En effet, l’outil étant principalement destiné à la gestion de blocs relativement compact d’objets, la manipulation d’un nombre important de lignes requiert quelques précautions (voir section 7.3.1) 7.1 Les bases de données Cette section va vous décrire les différentes bases de données que vous pouvez utiliser avec Hibernate. Ce ne sont pas les seules bases de données utilisables puisque Hibernate propose le support (via l’interface Dialect) de plusieurs autres bases de données. L’idée est simplement de montrer l’intérêt de chacune d’entre elles. 7.1.1 MySQL La plus connue et certainement la plus répandue. Cette base de données et « la » base de données de référence du monde WEB. Elle présente des avantages incontestables. Simple d’installation, pas de maintenance particulière, multi-plateforme (fonctionne aussi bien sous Windowsque U NIX), rapide, etc. Son point fort est d’avoir su s’adapter. En effet, la petite base de données est devenue une référence en ajoutant au fil des années des fonctionnalités indispensables : transactions, clés étrangères, clustering. 1. Bien que définies au niveau de la norme ANSI SQL-92, les bases de données contiennent des spécificités telles que les colonnes auto-incrémentales (MySQL, Sybase,...) qui rivalisent avec les séquences (Oracle,...) 40 CHAPITRE 7. HIBERNATE 41 Se connecter Les URLs de connexion aux bases de données restent assez classique. Pour MySQL, on utilisera une référence telle que : jdbc:mysql://localhost:3306/kompil7 où localhost est le nom du serveur, 3306 le port d’écoute (celui par défaut lors d’une installation classique) et kompil7 la base de données. Cela ne suffit pas. Je ne sais pas pourquoi mais les développeurs de MySQL ont créés quelques petites surprises au programmeur WEB. En effet, en plus de cette URL, il est nécessaire de passer quelques propriétés supplémentaires : – autoReconnect=true afin de se reconnecter automatiquement. En effet, au bout d’un certain temps le serveur déconnecte systématiquement un client resté connecté trop longtemps sans inactivité. – useUnicode=yes d’un part et characterEncoding=UTF-8 d’autre part. Ces deux propriétés sont nécessaires pour pleinement bénéficier des caractères sépciaux en particulier le signe e. autoReconnect=true Ce paramètre n’est pas surprenant. Plusieurs autres serveurs de bases de données déconnecte les clients qui sont restés trop longtemps inactifs (typiquement huit heures). Du coup, le client qui se voit déconnecté doit impérativement se reconnecter physiquement. Dans un environnement où les connections SQL sont mutualisées (connection pool), cela peut poser quelques problèmes pour peu que le site est peu d’activité durant une certaine période. Les mêmes connections seront réutilisées tandis que d’autres pourront ne jamais être mises à contribution alors qu’elles sont ouvertes et physiquement connectées au serveur. Mais cela ne fonctionne pas forcément très bien, c’est pourquoi, il est nécessaire lors de l’utilisation d’un pool de connection tel que org.apache.commons. dbcp.BasicDataSource (proposé par la fondation Apache), d’utiliser un test de connexion assez régulièrement. Pour cela, on utilise le code XML ci-dessous à l’intérieur de la déclaration du DataSource : <property name="testWhileIdle" value="true"/> <property name="timeBetweenEvictionRunsMillis" value="10000"/> <property name="validationQuery" value="select 1"/> useUnicode=yes Cela peut paraître bizarre, mais ce paramètre indique à la partie cliente de travailler en Unicode. Avec JAVA, on aurait pû penser que ce paramètre était par défaut. Que nenni. Comme quoi même les logiciels ouverts peuvent nous surprendre. characterEncoding=UTF-8 L’encodage des caractères. Avec UTF-8, tous les caractères peuvent être codés (de l’anglais au chinois). 7.1.2 PostgreSQL PostgreSQL est une base de données concurrente de MySQL. Elle présente à peu près les mêmes caractéristiques. À priori, moins facile à administrer que MySQL, elle CHAPITRE 7. HIBERNATE 42 est tout de même bien représentée dans le monde U NIX. L’installation native de PostgreSQL sous Windows n’est possible que depuis peu (auparavant, l’installation devait s’effectuer avec l’outil CygWin). Tandis que MySQL propose différents moteurs de stockage (MyISAM, InnoDB, etc.), PostgreSQL propose un seul type de stockage (comme la plupart des bases de données). En revanche, la précision des colonnes de type TIMESTAMP est de l’ordre de la milliseconde (ce qui permet de gérer des colonnes estampillées @Version de manière plus fiable). 7.1.3 Derby Produit IBM, il a été légué à la fondation Apache. C’est donc un produit libre. Sa principale caractéristique est d’être écrit en JAVA (tout comme HSQL). L’intérêt de Derby est la persistence des données sur le disque dur et non la prise en charge en mémoire comme le fait HSQL. 7.1.4 HSQL Tout comme Derby, il s’agit d’une base de données développée nativement en JAVA et qui s’interface donc facilement avec votre code JAVA. HSQL est surtout privilégiée comme base de données «légère». Les données sont stockées en mémoire et les transactions ne sont pas bien gérées. De plus, elle ne possède pas des mécanismes de log qui permettent la récupération de la base dans son dernier état stable. HSQL est surtout utilisée pour le maquettage des applications ainsi que pour servir de moteur dans les exemples et les tutoriels. Elle est également extrêmement utile en tant que base de données en lecture seule où les données peuvent être facilement stockées dans un fichier (CD-ROM de démonstration, etc.) Je déconseillerais l’usage de HSQL dans un environnement de production pour un site WEB. En revanche, les atouts de HSQL en font une base de données rêvée pour certaines applications légères. 7.1.5 Oracle Base de données leader du marché. Elle est souvent utilisée dans les grandes entreprises. En revanche, son prix d’acquisition est dissuasif pour une application personnelle ou une PME. 7.1.6 Sybase Sybase est une base de données solide et robuste. Tout comme Oracle, il s’agit d’un code propriétaire et une licence est nécessaire. Aussi surprenant que cela puisse paraître, Sybase ASE nécessite quelques paramétrage lors de la connexion. En effet, pour profiter des performances offertes par les PreparedStatements (accélération des requêtes par la pré-compilation au niveau CHAPITRE 7. HIBERNATE 43 serveur), il est nécessaire de préciser DYNAMIC_PREPARE=true dans les paramètres de connexion JDBC (voir la documentation JConnect) 7.1.7 Microsoft SQL-Server Microsft SQL Server (MSSQLServer en abrégé) est la base de données de référence sur les plateformes Microsoft. Certainement parce qu’elle a été assez largement déployée sur les plateformes professionnelles (le noyeau NT 4). Son succès est sans doute en partie dû au fait qu’il s’agit d’un noyeau Sybase. En effet, il s’agit du même code que celui utilisé par Sybase sur ses propres bases de données. Bien entendu, avec les années, le code a légèrement dérivé entre les deux produits mais on retrouve encore les mêmes commandes que pour les produits Sybase (en particulier Sybase Adaptive Server Entreprise). 7.2 La gestion des transactions Si une base de données doit répondre à un cahier des charges précis, la gestion des transactions est sans doute le point le plus important. Avec l’utilisation des sessions Hibernate et de Spring, on peut gérer les transactions de différentes manières : soit programmatiquement (un peu comme on le fait avec une connexion JDBC classique) ou déclarativement, c’est à dire dans un fichier XML décrivant la façon dont les transactions sont gérées ou mieux avec les annotations. Pour cela, on trouve différentes documentations sur divers sites Internet sans pour autant avoir une grande clarté dans les explications. En effet, cela ressemble plus à des recettes de cuisine, et on est parfois surpris du fonctionnement des sessions et transactions. Cette section est destinée à vous éclaircir sur le sujet. 7.2.1 La session Tout d’abord, il faut savoir que Hibernate gère des sessions à partir d’un SessionFactory. Cette usine à sessions va nous permettre de récupérer une session existante ou nouvelle (avec connexion à la base de données) afin de pouvoir exécuter nos requêtes SQL. La syntaxe est relativement simple et peut être déclarée dans le fichier applicationContext.xml. 7.3 7.3.1 Quelques astuces Les sessions détachées L’un des inconvénients majeurs de l’outil est sa propension à stocker en mémoire toutes les données récupérées à partir de la base de données. Ceci est assez normal puisque Hibernate est un outil de persistence. Néanmoins, il est parfois nécessaire de manipuler des volumes importants de données. CHAPITRE 7. HIBERNATE 44 Dans ce cas, deux solutions sont envisageables : l’une d’elles est d’utiliser directement les requêtes SQL via JDBC. C’est assez facile : il suffit de récupérer la connection JDBC liée au DataSource. L’autre solution est de demander à Hibernate d’utiliser une « session détachée ». Une session détachée court-circuite les traitements de persistence mais continue à assurer le travail de mapping et permet d’écrire la requête grâce au langage HQL. À travers ce principe, on reste indépendant de l’implémentation de la base de données et on obtient sensiblement les mêmes performances qu’avec une requête SQL normale traitée via JDBC. L’exmple figure 7.1 montre comment créer une session détachées (StatelessSession). Les objets n’étant pas stockés en mémoire pour une persistence ultérieure, vous pouvez les consulter un par un. Ceci peut être utile pour fabriquer des statistiques par exemple. 1 6 // Create a Stateless session StatelessSession session = getHibernateTemplate().getSessionFactory().openStatelessSession(); // Create the transaction (BEGIN TRAN) Transaction tx = session.beginTransaction(); // Create the request (select * from k7 order by IK7) Criteria criteria = session.createCriteria( K7.class ); criteria.addOrder( Order.asc("id") ); 11 // Browse as a ResultSet ScrollableResults cursor = criteria2.scroll(); while( cursor.next() ){ K7 k7 = (K7)cursor.get(0); 16 // Do the work } tx.commit(); session.close(); F IGURE 7.1 – Session détachée Bien entendu, dans certains cas, il faut mieux que les traitements soient assurés via des procédures stockées. Pour cela, on se contentera d’un appel de procédure stockée via Hibernate. Pour cela, une syntaxe particulière doit être utilisée et une requête nommée doit être créée. Je vous conseille de vous référer à la documentation d’Hibernate à la section Using stored procedures for querying. Chapitre 8 Sécurité d’un site WEB Ce chapitre s’adresse aux développeurs de sites WEB, il entre dans les détails des règles à suivre pour sécuriser votre site. Il n’est pas particulièrement orienté J2EE bien que nous aborderons quelques notions spécifiques. 8.1 Différences entre une application WEB et une application bureautique Il existe d’emblée une différence entre les applications bureautiques telles qu’un traitement de texte ou une gestion de stock via une interface spécifique et une application fonctionnant sur le WEB. Dans une application bureautique, c’est l’application qui dirige l’utilisateur tandis que l’application WEB est dirigée par l’utilisateur. En effet, dans une application WEB, tout se passe dans un navigateur en général simpliste (par définition), dont le rôle est limité à l’affichage de pages reçues par le serveur. 8.1.1 Accès direct Dans une application bureautique, vous partez toujours du même écran (généralement celui vous demandant de vous connecter à l’application en entrant votre identifiant et votre mot de passe). Dans une application WEB, vous pouvez vous connecter à n’importe quelle page grâce à son URL. Ce qui signifie que vous pouvez tenter d’accéder à des informations alors que vous n’êtes pas encore identifié. Dans l’architecture Struts 2, le problème est facilement résolu grâce au modèle MVC (voir section 4.3). 8.1.2 Historique Dans une application bureautique, on peut facilement créer un scénario de saisie. Dans une application WEB, l’utilisation de la touche de retour arrière vous permet de consulter la dernière page vue sans pour autant en informer le serveur. Plus grave, dans une saisie, vous pouvez très bien créer une nouvelle page WEB (généralement en appuyant sur CTRL+N) qui possède la même clé de session ; et vous 45 CHAPITRE 8. SÉCURITÉ D’UN SITE WEB 46 pouvez travailler aussi bien dans le premier navigateur dans le second qui seront totalement désynchronisés. Du coup, vous risquez d’affoler le serveur car la séquence de saisie est totalement illogique. 8.2 Saisie manuelle de l’URL La sécurité doit être testé lorsque la page est demandée. Contrairement à une application bureautique où l’accés à un écran est facilement interdit en supprimant l’acés au menu, un site WEB est très différent. En effet, imaginez un utilisateur ayant des droits particulier (administrateur par exemple) ayant accès à une page particulière. Il copie l’adresse de la page et la transmet par courrier électronique à un collègue. Celui-ci est déjà connecté à l’application et copie l’URL fournie : si aucune vérification d’accés au contenu de la page n’est affectué, il pourra accéder à l’information. 8.3 Variables contenant du code À COMPLÉTER... 8.4 Court-circuit des requêtes SQL La faille la plus connue consiste à entrer illégalement dans un site WEB. Pour cela, il suffit d’un peu d’astuce. Généralement, un formulaire de saisie se présente comme suit : 5 <FORM> <INPUT TYPE="text" NAME="login"> <INPUT TYPE="password" NAME="password"> <INPUT TYPE="submit" VALUE="LOG IN"> </FORM> On récupère alors deux variables : password et login. Certains (mauvais) programmeurs créent alors une requête comme celle-ci pour récupérer l’utilisateur : String sql = "SELECT USER_ID FROM USER_TABLE" + " WHERE LOGIN = ’" + login + "’" + " AND PASSWORD = ’" + password +"’"; Tout ce passe bien jusqu’au jour où l’utilisateur tape ’ OR 1 = 1 -- comme mot de passe. Dans ce cas la requête devient : 2 SELECT USER_ID FROM USER_TABLE WHERE LOGIN = ’scott’ AND PASSWORD = ’’ OR 1 = 1 --’ Et plus aucun mot de passe n’est nécessaire pour accéder à la ressource, tout ce passe comme si l’utilisateur avait réellement entré un mot de passe mais la clause « OR 1=1 » ajoutée permet d’outrepasser toute tentative d’authentification. Cette erreur, classique en PHP et dans d’autres langage, peut être évitée en utilisant des requêtes SQL tu type dynamique comme par exemple : CHAPITRE 8. SÉCURITÉ D’UN SITE WEB 2 47 String sql = "SELECT USER_ID FROM USER_TABLE" + " WHERE LOGIN = ?" + " AND PASSWORD = ?"; Ensuite un PreparedStatement est créé. On lui affectera le login et le mot de passe qui seront utilisés en toute sécurité. Avec Hibernate, ce type d’injection de variable est un cas classique. 8.5 Affichage des variables Une erreur fréquente consiste à afficher sur le site des données non reformattées (telles qu’elles sont reçues à travers le navigateur). Ainsi, imaginez l’URL : http:/localhost/printname.action?name=William. Et vous affichez la variable name telle quelle. Le mot “William” apparaîtra. Que va-t-il se passer si l’utilisateur remplace le nom par du code Javascript ? Celui-ci va être exécuté ! C’est le principe de base d’injection de code dans un site WEB. Chapitre 9 Saisir des données 9.1 Sécuriser la saisie Afin de garantir une saisie sécurisée, vous devriez impérativement n’autoriser que les saisies effectuées à l’intérieur d’une session où l’utilisateur est connu (voir 4.3 page 35). Il est envisageable qu’un utilisateur tente de « pirater » la connexion en effectuant des mises à jour aléatoires mais en tout état de cause, vous pouvez tracer ces tentatives frauduleuses et isoler la personne. De plus, avec la méthode exposée plus bas (qui se base sur l’utilisation de Hibernate), vous empêchez la mise à jour de données inaccessibles à l’utilisateur. Le principal problème auquel le développeur d’un site WEB peut se trouver confronté, c’est la duplication de fenêtre ! En effet, il suffit de créer une nouvelle fenêtre dans un navigateur WEB (que ce soit Internet Explorer ou un autre) pour que votre session soit scindée en deux et que votre serveur soit « perdu ». En effet, la connexion HTTP n’étant pas une connexion continue, seul le cookie transporté entre le navigateur et le serveur permet de conserver la liaison. Dans le cas d’un cookie dupliqué sur une fenêtre de saisie, vous pouvez être confronté à une double modification : la première venant de la fenêtre dupliquée, la seconde de la session originale. Dans la plupart des langages, ces deux modifications sont destructrices c’est-àdire que la dernière validation remplace les données de la saisie précédentes. On peut effectivement considérer ce phénomène comme naturel et de la responsabilité de l’utilisateur. Un deuxième cas de figure peut se présenter : deux utilisateurs veulent modifier la même donnée (l’un va modifier l’adresse d’un client, l’autre son numéro de téléphone). Dans ce cas de figure, le premier utilisateur modifie les données du client, le second modifie le client en se basant sur les données d’origines qui ont changées ! Hibernate résoud facilement ce problème en autorisant la création d’une colonne en base de donnée permettant de connaître le statut de la données (sa version). Ainsi, les mises à jour ne s’effectuent en base qui si on tente de modifier la données d’origine (c’est-à-dire que personne n’a fait de mise à jour entre temps). Pour cela, Hibernate peut utiliser deux politiques : soit se baser sur un numéro de version (un entier incrémenté à chaque modification – c’est la méthode conseillée par Hibernate), soit un 48 CHAPITRE 9. SAISIR DES DONNÉES 49 timestamp (l’heure de dernière modification de la donnée, souvent précise à la milliseconde). Bien que Hibernate préfère utiliser le numéro de version, la technique se basant sur le « timestamp » est préférérable sur la plupart des environnements. En effet, contrairement à un numéro de version, le timestamp est automatiquement mis à jour par la base de données lors des requêtes SQL de mise à jour. Cela présente l’avantage de modifier le timestamp si la mise à jour est effectuée à l’extérieur d’Hibernate (par une requête directe en base de données ou un logiciel tiers). L’autre avantage est d’être beaucoup plus imprévisible qu’un numéro de version. Le seul bémol reste la précision du timestamp lorsque celui-ci a une précision inférieure ou égale à la seconde (c’est le cas de MySQL ). Dans ce cas de figure, les mises à jours « quasi-simultanées » risquent de ne pas être distingable. Dans le cas de MS-SQLServer ou de Sybase ASE, la précision est de l’ordre de la milliseconde théoriquement suffisante pour se prémunir d’une mise à jour concurrencielle mal gérée. Dans les bases de données où le type TIMESTAMP est précis à la seconde seulement, il est possible de créer une « dummy transaction » afin d’effectuer la mise la jour puis d’attendre une seconde avant de valider la modification mais cette technique augmente les risques de deadlocks tout en réduisant considérablement les capacités de la base de données. 9.2 9.2.1 Fonctionnement Déclarer le versionning Pour cela, vous devez créer une colonne spécifique dans la table concernée par les mises à jour et ajouter une propriété (avec getter et setter) dans l’objet JAVA associé (voir fig. 9.1). Si vous n’utilisez pas les annotations de JAVA 5, vous devez déclarer la version directement dans le fichier XML de configuration de votre entité (voir 9.2). Une fois ces déclarations effectuée, la gestion du versionning est automatiquement déléguée à Hibernate. À partir de ce moment là, vous pouvez gérer de façon transparente ce qu’on appelle couramment les « transactions longues », à savoir des transactions dont la durée dépasse queleques millisecondes telle que la saisie de l’utilisateur. Aucun verrou n’est maintenu sur la base et lorsque Hibernate voudra mettre à jour la base de données, il ajoutera à sa clause de mise à jour un test sur la valeur de la colonne LAST_UPDATE_DT (colonne dédiée au timestamp). Si celle-ci n’a pas changée, la mise à jour s’effectue. Dans le cas contraire, une exception est remontée à l’application. 9.2.2 Saisie Typiquement, la mise à jour de l’information passe par le stockage de l’objet dans une variable de session. En effet, une fois l’objet à mettre à jour récupérée dans l’application, il est intéressant d’en conserver un exemplaire afin qu’il soit mis à jour par la saisie de l’utilisateur. Nous allons prendre l’exemple d’un musicien (Musician) pour illustrer une ac- CHAPITRE 9. SAISIR DES DONNÉES 2 import import import import javax.persistence.Entity; javax.persistence.Table; javax.persistence.Version; javax.persistence.Column; [...] 7 @Entity @Table(name="MY_CLASS") public class MyClass implements Serializable { private Timestamp lastUpdate; 12 [...] 17 @Version @Column(name="LAST_UPDATE_DT") public Timestamp getLastUpdate() { return lastUpdate; } 22 public void setLastUpdate(Timestamp lastUpdate) { this.lastUpdate = lastUpdate; } } F IGURE 9.1 – Déclaration du versionning 5 10 <hibernate-mapping> <class name="MyClass" table="MY_CLASS"> [...] <version name="lastUpdate" column="LAST_UPDATE_DT" type="timestamp"/> [...] </class> </hibernate-mapping> F IGURE 9.2 – Déclaration du versionning 50 CHAPITRE 9. SAISIR DES DONNÉES 51 tion standard permettant la saisie (création et modification) et la suppression d’un musicien dans la base de données. Le code (fig. 9.3) est suffisant pour la gestion complète de la saisie (en modification). Bien entendu, on ne dévoile que la partie visible du iceberg, Struts 2 se charge de toute la futilité liée à la mise à jour. Comment ça marche ? La première chose à faire est ... À COMPLÉTER... 9.2.3 Protection des données Le principal inconvénient est l’exposition de l’objet musician à Struts. En effet, une fois que Struts obtient une référence à une instance de Musician, il peut aussi bien lire ces propriétés que les modifier. Ainsi, dans FreeMarker, vous pourrez facilement accéder aux propriétés tel que le nom du musicien en utilisant l’instrospection : ${musician.name} ce qui va vous permettre d’afficher le nom du musicien. Malheureusement, le passage de musician.name=John+Lennon dans l’URL sera analysé par Struts qui tentera d’effectuer la commande JAVA suivante : getMusician().setName( "John Lennon" ) 1 C’est ce qu’on veut mais uniquement pour les propriétés qui doivent être mises à jour. Ainsi, si l’URL contient musician.id=6 alors que l’identifiant de l’enregistrement était 8, on va mettre à jour l’enregistrement 6 et non l’enregistrement 8 auquel on s’attendait ! Dans un déroulement normal, cette situation est impossible cependant nous sommes dans le monde du WEB avec des URLs pouvant être facilement falsifiées par l’internaute (d’autant plus facilement que les informations du formulaire sont passées au format GET plutôt que POST). Il est donc extrêmement risqué d’exposer l’instance musician. C’est pourquoi, la méthode getMusician() effectue un clonage de la donnée. Ainsi, si un utilisateur essaie de falsifier les données auquelles il n’a pas accès (comme l’identifiant), il le fera sur un clone ! Du coup, l’utilisation du clone interdit l’usage de notation telle que celle de la figure 9.4. Du coup, il est nécessaire pour chaque propriété modifiable de déclarer deux méthodes afin de lire et modifier la donnée (voir 9.5). Il s’agit d’un setter et d’un getter redirigé vers l’objet stocké dans la session. En revanche, dans le cas où les propriétés de l’objet sont uniquement destinées à être lue, on peut utiliser l’introspection offerte par Struts (puisque nous travaillons sur une copie de l’objet). 9.2.4 Clonage de l’objet Bien entendu, on peut déclarer les entités (telle que le class Musician) comme Cloneable et définir la méthode clone() mais cela n’est pas nécessaire. En effet, toutes les entités étant déclarées comme implémentant l’interface java.io. Serializable, il suffit d’utiliser le clonage par sérialisation/desérialisation. Cette technique est assez connue et présente une vitesse d’exécution proche de celle du clonage. Il suffit d’enregistrer l’objet dans un flux (java.io.OutputStream) 1. N’oublions pas que l’espace est transformé en “+” dans une URL. CHAPITRE 9. SAISIR DES DONNÉES 52 public class MusicianAction extends ActionSupport implements SessionAware { // The object identifier must initiated to // a value the identifier will never reach. // For integer identifier -1 is a good choice. private long id = -1; 5 Map session; // The user session Musician musician; // The object List<Musician> musicians; // List of musicians MusicianDAO musicianDAO 10 private private private private 15 public void prepare(){ musician = (Musician)session.get( MusicianAction.class.getName() ); } public String delete(){ // In this example, the deletion is not // possible. return ERROR; } 20 25 public String list(){ musicians = musicianDAO.getAll(); return SUCCESS; } 30 public String execute(){ if( id == -1 ){ // Update in the database. musicianDAO.saveOrUpdate( musician ); session.remove( MusicianAction.class.getName() ); return list(); } 35 if( id > 0 ){ musician = musicianDAO.get( id ); } else if( id == 0 ){ musician = new Musician(); } session.put( MusicianAction.class.getName(), musician ); return INPUT; 40 45 } public long getId() { return id; } 50 public void setId(long id) { this.id = id; } 55 public void setSession( Map session ){ this.session = session; } public Musician getMusician(){ return musician.clone(); } 60 } F IGURE 9.3 – Code to use the version CHAPITRE 9. SAISIR DES DONNÉES 1 53 <@s.textfield label="ID" readonly="true" key="mailing.id" /> F IGURE 9.4 – Notation avec introspection 4 public void setName( String s ){ musician.setName( s ); } public String getName(){ return musician.getName(); } F IGURE 9.5 – Getter/setter de redirection puis de créer un nouvel objet à partir des données stockées dans ce flux. Pour cela, on utilise des flux stockés en mémoire. La méthode clone() (9.6) montre comment cloner une instance de Serializable. CHAPITRE 9. SAISIR DES DONNÉES 4 public static Serializable clone( Serializable o ) { if( o == null ){ throw new NullPointerException( "o" ); } Serializable o2 = null; ByteArrayOutputStream out; ObjectOutputStream objOut; ByteArrayInputStream in; ObjectInputStream objIn; try { // Serialize out = new ByteArrayOutputStream(); objOut = new ObjectOutputStream( out ); objOut.writeObject(o); objOut.close(); 9 14 // Deserialize in = new ByteArrayInputStream( out.toByteArray() ); objIn = new ObjectInputStream( in ); o2 = (Serializable)objIn.readObject(); 19 } catch(IOException e){ // Should never happen as the operations // are made in memory only. e.printStackTrace(); } catch (ClassNotFoundException ex) { // Should never happen as the class // deserialized is already known by the JVM ex.printStackTrace(); } return o2; 24 29 34 } F IGURE 9.6 – Clonage via une méthode statique 54 Chapitre 10 displaytag displaytag est une librairie permettant d’afficher les informations sous forme d’un tableau HTML mais également de faire des exports sous Excel ou PDF. Elle s’intègre parfaitement à l’environnement Struts 2 et permet de gagner un temps fou au niveau développement. 10.1 Téléchargement Le site officiel se trouve à l’adresse http://displaytag.sf.net, la dernière version est la version 1.1. Vous devez normalement charger au minimum displaytag-1.1-bin.zip (6,61Mo.) qui contient la librarie displaytag-1.1.jar et la documentation API. Il est conseillé de télécharger également le code source contenu dans displaytag-1.1-src.zip (937Ko.). Ouvrez le fichier zippé et copiez displaytag-1.1.jar dans votre répertoire WEB-INF/lib. Pensez à ajouter ce .jar à votre classpath (voir section 2.7.1). Pour information, cette librairie a été développée (en partie du moins) par Matt Raible à qui l’on doit une participation active au monde J2EE. 10.2 Ajouter displaytag dans Struts Struts 2 définit ses propres Taglibs. Ainsi, sous FreeMarker, vous pouvez accéder à la gestion des formulaires assez simplement avec une notation du type <@ww.form> ... </@ww.form>. Ici, ww designe le taglib de Struts 2. Malheurement, Struts 2 a du mal à accepter des taglibs qui ne sont pas les siens. Il est donc nécessaire d’ajouter le code de la figure 10.1 pour permettre à FreeMarker d’utiliser displaytag(pour plus d’information, vous pouvez consulter la fiche JIRA http: //jira.opensymphony.com/browse/WW-844). Une fois cette configuration ajoutée à WEB-INF/web.xml, vous pouvez utiliser 55 CHAPITRE 10. DISPLAYTAG 1 6 11 16 56 <servlet> <servlet-name>JspSupportServlet</servlet-name> <servlet-class> com.opensymphony.webwork.views.JspSupportServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet> <servlet-name>action</servlet-name> <servlet-class> com.opensymphony.webwork.dispatcher.ServletDispatcher </servlet-class> </servlet> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping> F IGURE 10.1 – Insérer des taglib dans FreeMarker displaytag en déclarant dans chaque page où vous y faire référence la ligne suivante <#assign displayTag = JspTaglibs["http://displaytag.sf.net"] /> Une fois cette ligne lue par FreeMarker, vous pouvez utiliser le taglib en le référençant par displayTag. Chapitre 11 Générer des images Tout comme avec PHP, il est possible de créer des images JPEG, PNG ou GIF « à la volée », c’est à dire sans passer par une génération préalable sur le disque. De même, cela est totalement possible via WebWork. Pour cela, il suffit de créer un renderer capable d’afficher des images. JAVA permet de créer des images JPEG à partir de la classe java. awt.BufferedImage. Ceci est automatique grâce à l’utilisation du package com.sun.image.codec.jpeg fourni à partir du JDK1.4. Dans Struts 2, il faut implémenter la gestion des images JPEG. Pour cela, rien de plus simple : il suffit d’une part de définir un « renderer », d’autre part, une interface destinée à gérer la capacité de création des images dans les Actions. 11.1 Créer une interface Pour afficher une image dans une page WEB, il suffit de 2 informations : – le type de l’image, ou si vous préférez, son MIME-Type : pour une image JPEG, il s’agit de "image/jpeg" ; pour du PNG, "image/png"| et pour des images GIF, "image/gif". – de la socket de sortie permettant d’envoyer le flux binaire vers le navigateur. Cela se traduit en JAVA par l’utilisation de la classe java.io.OutputStream. On peut également avoir besoin de la taille de l’image (cela est censé faciliter le travail du navigateur) mais cela n’est pas nécessaire. L’interface proposée (figure 11.1) se compose donc de deux méthodes. La première permet de récupérer son MIME-Type, la seconde d’envoyer les données sur une sortie. Chaque action ayant besoin d’un rendu d’image devra implémenter cette interface. 11.1.1 Le renderer Le renderer va permettre l’affichage de l’image. Pour cela, vous devez très simplement créer un nouveau renderer en plus de ceux fournis par Struts 2. Pour cela, il suffit de créer une classe implémentant l’interface Result. Pour des raisons techniques, nous devons également récupérer l’instance avax.servlet. http.HttpServletResponse nous permettant d’utiliser la sortie. Pour cela, 57 CHAPITRE 11. GÉNÉRER DES IMAGES 1 58 public interface ImageSupport { /** * Return the content type of the image. * * @return a string containing "<code>image/jpeg</code>", * "<code>image/gif</code>" or "<code>image/png</code>". */ public String getContentType(); 6 /** * Writes the image to the output. * * @param out the output where to write. * @throws IOException if an I/O error occurs. */ public void writeImage( OutputStream out ) throws IOException; 11 16 } F IGURE 11.1 – Interface pour une action Struts 2 nous propose d’utiliser l’interface com.opensymphony.webwork. WebWorkStatics afin de récupérer facilement l’information. 1 package xxx; import javax.servlet.http.HttpServletResponse; 6 11 import import import import com.opensymphony.webwork.WebWorkStatics; com.opensymphony.xwork.ActionContext; com.opensymphony.xwork.ActionInvocation; com.opensymphony.xwork.Result; public class ImageResult implements Result, WebWorkStatics { public void execute(ActionInvocation invocation) throws Exception { ImageSupport action = (ImageSupport)invocation.getAction(); ActionContext context = ActionContext.getContext(); HttpServletResponse response = (HttpServletResponse)context.get(HTTP_RESPONSE); response.setContentType( action.getContentType() ); action.writeImage( response.getOutputStream() ); response.getOutputStream().flush(); } 16 21 } F IGURE 11.2 – Classe de rendu Cela permet de coder une classe relativement simple dont le code est disponible figure 11.2. Pour utiliser ce renderer, vous devez l’avoir préalablement déclaré dans votre fichier xwork.xml (voir figure 11.3). 11.1.2 Utilisation Toutes les briques sont en place, vous pouvez maintenant utiliser votre renderer xxx.ImageResult en déclarant dans votre fichier xwork.xml le code décrit en CHAPITRE 11. GÉNÉRER DES IMAGES 1 6 59 <package name="default" extends="webwork-default"> <result-types> <result-type name="image" class="xxx.ImageResult" /> </result-types> ... </package> F IGURE 11.3 – Classe de rendu 11.4. 3 <action name="treeGraph" class="xxx.actions.TreeGraph"> <result name="success" type="freemarker">/www/treeGraph.ftl</result> <result name="jpeg" type="image" /> </action> F IGURE 11.4 – Sample in xwork.xml On the other side, figure 11.5 shows you a standard implementation in your Action implementation and la figure 11.6 l’implementation du coté FreeMarker. CHAPITRE 11. GÉNÉRER DES IMAGES 60 public class TreeGraph extends DefaultAction implements ImageSupport { private BufferedImage image; private int width = 400; private int height = 200; 5 public String execute(){ .. // Work to do return SUCCESS; } 10 public String doMakeImage(){ image = new BufferedImage( width, height, BufferedImage.TYPE_INT_RGB ); ... // Create the contents of the image return "jpeg"; } 15 public String getContentType() { return "image/jpeg"; } 20 public void writeImage(OutputStream out) throws IOException { JPEGImageEncoder encoder; encoder = JPEGCodec.createJPEGEncoder( out ); encoder.encode( image ); } 25 } F IGURE 11.5 – Sample in xwork.xml 5 <body> <img src="treeGraph!makeImage.action?width=#{width}&height=#{height}" border="0"/> </body> F IGURE 11.6 – A simple example in Freemarker Chapitre 12 Logiciels Il existe de nombreux codes sources très simple à utiliser et facilement intégrables à votre application. La liste des composants ci-dessous n’est pas ordonnée et n’est pas exhaustive. 12.1 Microsoft EXCEL Une excellente librarie diffusée par la fondation Apache accessible à l’adresse http: //jakarta.apache.org/poi/ permet de générer des fichiers au format Microsoft EXCEL. D’utilisation facile, elle permet de générer des fichiers directement à partir de votre application, et cela à la volée si nécessaire. La génération de fichier Excel peut également être facilité par l’utilisation de la librairie displaytag (voir chapitre 10). 12.2 Graphiques Pour obtenir de magnifiques graphiques dans vos applications, vous pouvez utiliser la librairie JFreeChart (http://www.jfree.org/jfreechart/). Elle permet de tracer tous les graphiques habituels : camembert, barres, points, etc. 12.3 Planificateur OpenSymphony distribue également un puissant planificateur nommé Quartz. Celui-ci peut être télécharger à l’adresse http://www.opensymphony.com/quartz/. Il permet de lancer des tâches à des moments précis (c’est l’équivalent de la commande crontab sous U NIX). Précise à la seconde près, elle permet, par exemple, la génération de pages en arrière plan afin de limiter l’utilisation de la CPU et l’attente de l’utilisateur lors de la consultation de pages lourdes à charger. Elle permet également de programmer l’envoi de courriels à certains moments (par exemple la nuit) pour éviter de surcharger l’applicatif dans la journée. 61 CHAPITRE 12. LOGICIELS 12.4 62 SSH Le protocole SSH permet d’éxecuter des commandes à distance sur des machines U NIX. Pour cela, il faut se connecter à la machine via un identifiant et un mot de passe ou via un identifiant et une clé de cryptage. Cette solution permet de démarrer des commandes très spécifiques à l’intérieur d’un réseau tout en maintenant un maximum de sécurité (la transmission est cryptée). La librarie Ganymed SSH-2 for Java récupérable à l’adresse http://www.ganymed. ethz.ch/ssh2 permet de limiter au maximum le travail du programmeur en lui donnant une API de haut niveau pour les communications sécurisées. Je vous conseille de regarder l’exemple de base dans le fichier Basic.java dans le répertoire examples. 12.5 RLogin Tout comme le protocole SSH, la commande rlogin permet de se connecter à distance sur une machine de type U NIX. La principale différence réside dans le fait que la protection de ce protocole est faible : il ne peut être envisagé qu’à l’intérieur d’un réseau local. Pour utiliser une librarie simple, je vous propose de jeter un coup d’œil sur Commons Net édité par la fondation Apache (http://jakarta.apache.org/commons/net/). Chapitre 13 Le client lourd Le client lourd, à savoir une application développée sur mesure, est parfois une solution mieux adaptée qu’un site WEB ayant parfois des limitation en terme de saisie ou de consultation dans le cas où l’on travaille sur des quantités importantes de données. Ce chapitre aborde la manière à employer pour ré-utiliser les objets métiers développés dans ce livre. L’architecture présentée avait pour intérêt de séparer la partie présentation des processus métiers. Il paraît donc pertinent de penser que la création d’une application cliente lourde consiste à uniquement remplacer la partie présentation. Il est même possible de tirer avantage de la séparation des couches pour avoir la possibilité de laisser à l’utilisateur le choix d’utiliser l’application cliente ou le client léger selon ses besoins ou les contraintes techniques (présence au bureau, déplacement à l’étranger, etc.) À COMPLÉTER... 63 Chapitre 14 Annexes 14.1 Les des logiciels téléchargés Vous trouverez dans le tableau (voir fig. 14.1) les logiciels ainsi que leur version. Il s’agit des versions que nous avons utilisé dans ce livre : pas nécessairement les dernières (c’est tout particulièrement le cas avec le JDK en version J2SE 5 alors que la version 6 existe et fonctionne parfaitement). Logiciel Eclipse Hibernate Core Hibernate Annotations JDK JAVA (J2SE) Spring Framework Jetty FreeMarker SiteMesh Struts 2 Version 3.4 (JEE) 3.3.1.GA 3.4.0.GA 1.5.0.16 2.0.3 6.1.11 2.3.14 2.3 2.0.11.1 URL http://www.eclipse.org/ http://www.hibernate.org/ http://www.hibernate.org/ http://java.sun.com/ http://www.springframework.org/ http://dist.codehaus.org/jetty/ http://wwww.freemarker.org/ http://www.opensymphony.com/sitemesh/ http://struts.apache.org/2.x/ F IGURE 14.1 – Liste des téléchargements En effet, comme le dit l’adage : « Release Early, Release Often ». Il ne faut donc pas s’étonner que les versions évoluent rapidement et que ce document soit un peu dépassé lors de son édition. Le principal est de pouvoir suivre les explications données quitte à utiliser une version obsolète : les modifications apportées (même entre deux versions majeures) sont souvent faibles afin de garantir une certaine pérennité aux logiciels ouverts. 64