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