| Astuce | ||
|---|---|---|
| ||
Relecture RB faite le | ||
| Balise Wiki | ||
| {tip:title=Relu}Relecture RB faite le 16/02/2011 {tip} |
Ce
...
chapitre
...
n'a
...
pas
...
la
...
prétention
...
d'être
...
une
...
formation
...
à
...
Spring
...
.
...
Pour
...
plus
...
d'informations,
...
vous
...
pouvez
...
vous
...
reporter
...
à
...
la
...
documentation
...
de springsource ( HTML / PDF ). Ne sont abordés ici que quelques détails permettant de mieux comprendre certains éléments des fichiers de configuration de esup-commons.
| Remarque |
|---|
Esup-commons V2 utilise Spring 3 |
Tout au long de ce chapitre nous allons nous appuyer sur un exemple (configuration du gestionnaire d'exceptions) :
| Bloc de code |
|---|
[springsource|http://www.springsource.org/] ( [HTML|http://static.springsource.org/spring/docs/3.1.0.M1/spring-framework-reference/html] / [PDF|http://static.springsource.org/spring/docs/3.1.0.M1/spring-framework-reference/pdf/spring-framework-reference.pdf] ). Ne sont abordés ici que quelques détails permettant de mieux comprendre certains éléments des fichiers de configuration de _esup-commons_. {note}{_}Esup-commons V2_ utilise Spring 3{note} Tout au long de ce chapitre nous allons nous appuyer sur un exemple (configuration du gestionnaire d'exceptions) : \\ {code} <bean id="exceptionServiceFactory" class="org.esupportail.commons.services.exceptionHandling.CachingEmailExceptionServiceFactoryImpl" parent="abstractApplicationAwareBean"> <property name="smtpService" ref="smtpService" /> <property name="recipientEmail" value="${exceptionHandling.email}" /> <property name="exceptionViews"> <map> <entry key="java.lang.Exception" value="go_exception" /> </map> </property> <property name="logLevel" value="${exceptionHandling.logLevel}" /> <property name="cacheManager" ref="cacheManager" /> <property name="cacheName" value="" /> </bean> {code} ---- h4. Sommaire : {toc:maxLevel=3} ---- h2. Les fichiers de configuration _Spring_ permet de créer des objets (appelés alors _beans_) en les déclarant dans un fichier de configuration _XML_. Le fichier de configuration principal (* |
...
Sommaire :
| Sommaire | ||
|---|---|---|
|
...
Les fichiers de configuration
Spring permet de créer des objets (appelés alors beans) en les déclarant dans un fichier de configuration XML.
Le fichier de configuration principal (properties/applicationContext.xml
...
)
...
est
...
déclaré
...
dans
...
le
...
*web.xml
...
*
...
sous
...
la
...
forme
...
d'un
...
paramètre
...
de
...
l'application
...
:
| Bloc de code |
|---|
} <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:/properties/applicationContext.xml</param-value> </context-param> {code} Dans _ |
Dans esup-commons
...
ce
...
fichier
...
de
...
configuration
...
principal
...
contient
...
seulement
...
des
...
inclusions
...
de
...
fichiers
...
de
...
configuration
...
spécialisés
...
par
...
domaine,
...
comme
...
par
...
exemple:
| Bloc de code |
|---|
} <import resource="exceptionHandling/exceptionHandling.xml" /> {code} |
Il
...
est
...
possible,
...
suivant
...
les
...
besoins
...
de
...
votre
...
application,
...
de
...
supprimer
...
ou
...
d'ajouter
...
des
...
fichiers
...
de
...
configuration
...
spécialisés.
...
L'injection
...
de
...
données
...
Une
...
des
...
caractéristiques
...
de
...
base
...
de
...
Spring
...
est
...
de
...
permettre
...
l'injection
...
de
...
données.
| Remarque |
|---|
| } Cette fonctionnalité est aussi possible avec _JSF _, qui est également utilisé dans _esup-commons _, mais _JSF _est moins puissant que _Spring _dans ce domaine. _esup-commons _n'utilise donc pas l'injection de données de _JSF _. {note} |
L'injection
...
de
...
données
...
permet
...
de
...
renseigner
...
des
...
attributs
...
d'un
...
bean
...
via
...
un
...
fichier
...
de
...
configuration.
...
Le
...
bean
...
doit
...
disposer
...
d'un
...
setter
...
pour
...
l'accès
...
à
...
ces
...
attributs.
...
Voyons
...
quelques
...
exemples...
...
Injection
...
d'une
...
chaîne
...
de
...
caractères
| Bloc de code |
|---|
} <property name="recipientEmail" value="webmaster@domain.edu"/> {code} |
Dans
...
ce
...
cas,
...
la
...
méthode
...
setRecipentEmail()
...
sera
...
appelée
...
avec
...
pour
...
paramètre,
...
la
...
valeur
...
webmaster@domain.edu
...
.
...
Injection
...
d'un
...
autre
...
bean
| Bloc de code |
|---|
} <property name="authenticationService" ref="authenticationService"/> {code} |
On
...
voit
...
ici
...
un
...
autre
...
aspect
...
important
...
de
...
Spring
...
qui
...
est
...
l'utilisation
...
quasi
...
systématique
...
des
...
interfaces.
...
La
...
classe
...
CachingEmailExceptionServiceFactoryImpl
...
(qui
...
correspond
...
au
...
bean
...
exceptionServiceFactory
...
et
...
contient
...
la
...
définition
...
de
...
cette
...
propriété
...
authenticationService
...
)
...
a
...
un
...
attribut
...
authenticationService
...
de
...
type
...
AuthenticationService
...
.
...
AuthenticationService
...
est
...
une
...
interface.
...
Le
...
bean
...
authenticationService
...
doit
...
donc
...
être
...
d'une
...
classe
...
qui
...
implémente
...
cette
...
interface.
...
Ceci
...
permet
...
d'avoir
...
plusieurs
...
implémentations
...
possibles
...
pour
...
cette
...
interface
...
et
...
de
...
choisir,
...
simplement
...
en
...
modifiant
...
un
...
fichier
...
de
...
configuration,
...
laquelle
...
on
...
utilise.
...
Cette
...
approche
...
est
...
particulièrement
...
intéressante
...
:
...
elle
...
permet,
...
par
...
exemple,
...
de
...
très
...
facilement
...
tester
...
une
...
couche
...
de
...
l'application
...
en
...
branchant
...
des
...
implémentations
...
de
...
tests
...
des
...
autres
...
couches
...
avec
...
lesquelles
...
le
...
bean
...
doit
...
interagir.
...
Injection
...
d'une
...
map
| Bloc de code |
|---|
} <property name="exceptionViews"> <map> <entry key="java.lang.Exception" value="go_exception" /> </map> </property> {code} h3. Injection |
Injection d'une
...
liste
| Bloc de code |
|---|
} <property name="servers"> <list> <ref bean="smtpServer1" /> <ref bean="smtpServer2" /> </list> </property> {code} h2. Utilisation de paramètres Afin de centraliser la configuration, une bonne pratique consiste à utiliser un fichier de configuration regroupant les paramètres de |
Utilisation de paramètres
Afin de centraliser la configuration, une bonne pratique consiste à utiliser un fichier de configuration regroupant les paramètres de l'application.
...
Ceci
...
évite
...
notamment
...
de
...
devoir
...
modifier
...
n
...
fichiers
...
différents.
...
Exemple
...
d'utilisation
...
:
| Bloc de code |
|---|
} <property name="recipientEmail" value="${exceptionHandling.email}" /> {code} |
Ici
...
la
...
propriété
...
recipientEmail
...
contiendra
...
la
...
valeur
...
contenue
...
dans
...
le
...
paramètre
...
exceptionHandling.email
...
.
...
Le
...
paramètre
...
exceptionHandling.email
...
est
...
défini
...
dans
...
le
...
fichier
...
default.properties
...
et
...
peut
...
être
...
surchargé
...
dans
...
le
...
fichier
...
config.properties
...
:
| Bloc de code |
|---|
} exceptionHandling.email=bugs@domain.edu {code} {note} Ce mécanisme est rendu possible par la définition |
| Remarque | |||
|---|---|---|---|
Ce mécanisme est rendu possible par la définition d'un bean utilisant la classe _PropertyPlaceholderConfigurer _de Spring dans le fichier *properties/applicationContext.xml * {code}
Ici on définit les propriétés dans le fichier *defaults.properties *.Elles sont éventuellement écrasées par celles définies dans *config.properties *. Ici on utilise aussi la possibilité de surcharger ces valeurs par une référence à un fichier qui sera précisé par une option au lancement de la JVM (Ex : *\-Dapplication.config.location=/tmp/foo.properties *). Afin que le propertyConfigurer ne lève pas une exception au cas où cette dernière possibilité n'est pas utilisée on positionne une des ces propriétés ( *ignoreResourceNotFound *) pour qu'il ignore les éventuelles ressources absentes. {note} h2.les éventuelles ressources absentes. |
L'héritage
...
de
...
configuration
...
Spring
...
n'oblige
...
pas
...
à
...
saisir,
...
dans
...
toutes
...
les
...
définitions
...
de
...
beans
...
,
...
les
...
mêmes
...
propriétés.
...
Pour
...
cela,
...
il
...
est
...
possible
...
d'utiliser
...
le
...
mot-clé
...
parent
...
.
...
Le « parent » a un attribut abstract="true"
...
car
...
il
...
ne
...
doit
...
pas
...
être
...
créé
...
en
...
mémoire
...
par
...
Spring
...
.
...
Cette
...
notation
...
permet
...
de
...
se
...
rapprocher
...
de
...
l'héritage
...
Java
...
qui
...
est
...
beaucoup
...
utilisé
...
dans
...
esup-commons
...
.
...
Exemple
...
d'un
...
bean « parent » ayant aussi lui-même un « parent » :
| Bloc de code |
|---|
un « parent » : {code} <bean id="abstractApplicationAwareBean" parent="abstractI18nAwareBean" abstract="true"> <property name="applicationService" ref="applicationService" /> </bean> {code} {note} |
| Remarque |
|---|
L'attribut *scope *(voir ci-après) n'est pas héritable, il est donc inutile de le préciser pour un bean abstrait. |
Vérification des beans
Les beans manipulés par Spring n'ont pas, par défaut, de dépendances particulières avec Spring.
Il est, par contre, possible de sciemment introduire une dépendance avec Spring pour obtenir des services supplémentaires.
Faire en sorte que votre bean implémente l'interface InitializingBean de Spring en fait partie. Cette interface vous oblige à implémenter une méthode afterPropertiesSet qui sera appelée par Spring juste après l'initialisation du bean. Cette méthode vous permet de vérifier que toutes les propriétés sont bien initialisées. Si ce n'est pas le cas, vous pouvez, par exemple, lever une exception ou affecter une valeur par défaut.
On trouvera par exemple :
| Bloc de code |
|---|
_bean_ abstrait. {note} h2. Vérification des _beans_ Les _beans_ manipulés par _Spring_ n'ont pas, par défaut, de dépendances particulières avec _Spring_. Il est, par contre, possible de sciemment introduire une dépendance avec _Spring_ pour obtenir des services supplémentaires. Faire en sorte que votre _bean_ implémente l'interface *InitializingBean* de _Spring_ en fait partie. Cette interface vous oblige à implémenter une méthode *afterPropertiesSet* qui sera appelée par _Spring_ juste après l'initialisation du _bean_. Cette méthode vous permet de vérifier que toutes les propriétés sont bien initialisées. Si ce n'est pas le cas, vous pouvez, par exemple, lever une exception ou affecter une valeur par défaut. On trouvera par exemple : {code} public void afterPropertiesSet() { super.afterPropertiesSet(); if (!StringUtils.hasText(exceptionView)) { exceptionView = DEFAULT\__SERVLET_\_EXCEPTION_VIEW; logger.info(getClass() + ": no exceptionView set, using default \[" + exceptionView + "\]"); } } {code} h2. Portée des beans _Spring_ offre une notion de portée (*scope*). Par défaut, un _bean_ est de portée *singleton*. _Spring_ crée une seule instance de ce _bean_ pour toute la durée d'exécution de l'application. Il existe aussi des portées *session* et *request* qui, respectivement, permettent d'avoir une instance du _bean_ par session utilisateur (au sens d'une application web) ou par requête (au sens HTTP). Cette notion est particulièrement intéressante pour les contrôleurs web d'une application. Ces derniers sont en général des _beans_ de portée *session*, comme par exemple : {code} |
Portée des beans
Spring offre une notion de portée (scope).
Par défaut, un bean est de portée singleton. Spring crée une seule instance de ce bean pour toute la durée d'exécution de l'application.
Il existe aussi des portées session et request qui, respectivement, permettent d'avoir une instance du bean par session utilisateur (au sens d'une application web) ou par requête (au sens HTTP). Cette notion est particulièrement intéressante pour les contrôleurs web d'une application. Ces derniers sont en général des beans de portée session, comme par exemple :
| Bloc de code |
|---|
<bean id="administratorsController"
class="[...].formation.web.controllers.AdministratorsController"
parent="abstractContextAwareController"
scope="session" />
{code}
|
Usuellement,
...
un
...
bean
...
de
...
scope
...
request
...
peut
...
faire
...
référence,
...
via
...
ses
...
propriétés,
...
à
...
un
...
bean
...
de
...
scope
...
session
...
ou
...
singleton
...
.
...
De
...
même,
...
un
...
bean
...
de
...
scope
...
session
...
peut
...
faire
...
référence
...
à
...
un
...
bean
...
de
...
scope
...
singleton
...
.
...
Une
...
bonne
...
architecture
...
nous
...
amène
...
d'ailleurs
...
à
...
utiliser
...
dans
...
ce
...
sens
...
l'injection
...
de
...
beans.
...
Par
...
défaut,
...
la
...
réciproque
...
provoque
...
une
...
exception
...
...
...
mais
...
il
...
est
...
cependant
...
possible
...
de
...
réaliser
...
cette
...
réciproque
...
par
...
le
...
biais
...
de
...
l'
...
aop
...
,
...
et
...
cela
...
très
...
simplement.
...
Concrètement
...
si
...
nous
...
voulons
...
ici
...
injecter
...
le
...
bean
...
administratorsController
...
qui
...
est
...
de
...
scope
...
session
...
dans
...
un
...
bean
...
de
...
scope
...
singleton,
...
on
...
utilisera
...
la
...
balise
...
aop:scoped-proxy
...
comme
...
ceci
...
dans
...
la
...
déclaration
...
du
...
bean
...
administratorsController :
| Bloc de code |
|---|
* : \\ {code} <bean id="administratorsController" class="[...].formation.web.controllers.AdministratorsController" parent="abstractContextAwareController" scope="session"> <aop:scoped-proxy/> </bean> {code} |
Pour
...
ce
...
faire,
...
on
...
aura
...
pris
...
soin
...
de
...
déclarer
...
comme
...
il
...
se
...
doit
...
l'espace
...
de
...
noms
...
aop,
...
avec
...
dans
...
la
...
balise
...
racine
...
du
...
fichier
...
de
...
configuration
...
de
...
beans
...
Spring
...
ceci
...
:
| Bloc de code |
|---|
} <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd" > ... </beans> {code} {HTMLcomment} h2. Récupération des _beans_ Il est possible de récupérer un _bean_ à partir de son nom à partir du code JAVA. La classe *BeanUtils* fournie par _esup-commons_ V1 n'est plus utilisée. On utilise un mécanisme interne à Spring basé sur l'implémentation de * |
| HTML Comment |
|---|
Récupération des beansIl est possible de récupérer un bean à partir de son nom à partir du code JAVA. La classe BeanUtils fournie par esup-commons V1 n'est plus utilisée. On utilise un mécanisme interne à Spring basé sur l'implémentation de org.springframework.context.ApplicationContextAware |
...
esup-commons |
...
V2 |
...
fournit |
...
une |
...
telle |
...
implémentation |
...
qu'il |
...
suffit |
...
de |
...
déclarer |
...
dans |
...
un |
...
fichier |
...
de |
...
configuration |
...
Spring |
...
(ex |
...
: |
...
properties/applicationContext.xml |
...
) |
...
: |
...
|
...
|
...
Depuis |
...
le |
...
code |
...
java, |
...
on |
...
utilisera |
...
: |
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...
|
...