Je préfère une troisième approche qui tire le meilleur parti des éléments suivants Approche 1 y Approche 2 décrit par l'utilisateur1016403 .
Approche 3
- Sauvegarder les propriétés de la base de données sur le
server.xml
- faire référence à la
server.xml
les propriétés de la base de données à partir de l'application web META-INF/context.xml
Avantages de l'approche 3
Alors que le premier point est utile pour des raisons de sécurité, le second est utile pour référencer la valeur des propriétés du serveur à partir de l'application web, même si les valeurs des propriétés du serveur vont changer.
De plus, le fait de découpler les définitions de ressources sur le serveur de leur utilisation par l'application web rend cette configuration évolutive dans des organisations de complexité variable où différentes équipes travaillent sur différents niveaux/couches : l'équipe des administrateurs du serveur peut travailler sans entrer en conflit avec l'équipe des développeurs si l'administrateur partage le même nom JNDI avec le développeur pour chaque ressource.
Mise en œuvre de l'approche 3
Définir le nom JNDI jdbc/ApplicationContext_DatabaseName
.
Déclarer le jdbc/ApplicationContext_DatabaseName
Les diverses propriétés et valeurs de Tomcat dans le fichier server.xml
en utilisant quelque chose comme ça :
<GlobalNamingResources>
<Resource name="jdbc/ApplicationContext_DatabaseName" auth="Container" type="javax.sql.DataSource"
username="dbUsername" password="dbPasswd"
url="jdbc:postgresql://localhost/dbname"
driverClassName="org.postgresql.Driver"
initialSize="5" maxWait="5000"
maxActive="120" maxIdle="5"
validationQuery="select 1"
poolPreparedStatements="true"/>
</GlobalNamingResources/>
Lier le jdbc/ApplicationContext_DatabaseName
Les propriétés de l'application web META-INF/context.xml
par un contexte JNDI privé de l'application java:comp/env/
spécifié dans le name
attribut :
<Context path="/ApplicationContext" ... >
<!--
"global" attribute links to GlobalNamingResources in the ${catalina.base}/conf/server.xml (server administrator team)
"name" attribute is relative to the application-private JNDI context java:comp/env/ and is looked up from the java web application (application developer team)
-->
<ResourceLink global="jdbc/ApplicationContext_DatabaseName" name="jdbc/DatabaseName" type="javax.sql.DataSource"/>
</Context>
Enfin, afin d'utiliser la ressource JNDI, spécifiez le nom JNDI jdbc/DatabaseName
dans le descripteur de déploiement de l'application web :
<resource-ref>
<description>DatabaseName's Datasource</description>
<res-ref-name>jdbc/DatabaseName</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
et dans le contexte du printemps :
<jee:jndi-lookup id="DatabaseNameDataSource"
jndi-name="jdbc/DatabaseName"
expected-type="javax.sql.DataSource" />
Inconvénients de l'approche 3
Si le nom JNDI est modifié, alors les deux fichiers server.xml
et le META-INF/context.xml
devra être modifié et un déploiement sera nécessaire ; néanmoins, ce scénario est rare.
Approche 3 variations
Plusieurs sources de données utilisées par une seule application web
Il suffit d'ajouter des configurations au fichier server.xml
:
<GlobalNamingResources>
<Resource name="jdbc/ApplicationContext_DatabaseName1" ... />
<Resource name="jdbc/ApplicationContext_DatabaseName2" ... />
...
</GlobalNamingResources/>
Ajouter un lien vers une application web META-INF/context.xml
par un contexte JNDI privé de l'application java:comp/env/
spécifié dans le name
attribut :
<Context path="/ApplicationContext" ... >
<ResourceLink global="jdbc/ApplicationContext_DatabaseName1" name="jdbc/DatabaseName1" ... />
<ResourceLink global="jdbc/ApplicationContext_DatabaseName2" name="jdbc/DatabaseName2" ... />
...
</Context>
Enfin, ajoutez l'utilisation des ressources JNDI dans le descripteur de déploiement de l'application web :
<resource-ref>
<description>DatabaseName1's Datasource</description>
<res-ref-name>jdbc/DatabaseName1</res-ref-name> ...
</resource-ref>
<resource-ref>
<description>DatabaseName2's Datasource</description>
<res-ref-name>jdbc/DatabaseName2</res-ref-name> ...
</resource-ref>
...
et dans le contexte du printemps :
<jee:jndi-lookup id="DatabaseName1DataSource"
jndi-name="jdbc/DatabaseName1" ... />
<jee:jndi-lookup id="DatabaseName2DataSource"
jndi-name="jdbc/DatabaseName2" ... />
...
Plusieurs sources de données utilisées par plusieurs applications web sur le même serveur
Il suffit d'ajouter la configuration au fichier server.xml
:
<GlobalNamingResources>
<Resource name="jdbc/ApplicationContextX_DatabaseName1" ... />
<Resource name="jdbc/ApplicationContextX_DatabaseName2" ... />
<Resource name="jdbc/ApplicationContextY_DatabaseName1" ... />
<Resource name="jdbc/ApplicationContextY_DatabaseName2" ... />
...
</GlobalNamingResources/>
les autres configurations doivent pouvoir être déduites du cas de variation précédent.
Plusieurs sources de données vers la même base de données utilisée par plusieurs applications web sur le même serveur.
Dans un tel cas, un fichier de Tomcat server.xml
des configurations comme :
<GlobalNamingResources>
<Resource name="jdbc/ApplicationContextX_DatabaseName" ... />
<Resource name="jdbc/ApplicationContextY_DatabaseName" ... />
se retrouve dans deux applications web différentes META-INF/context.xml
comme :
<Context path="/ApplicationContextX" ... >
<ResourceLink global="jdbc/ApplicationContextX_DatabaseName" name="jdbc/DatabaseName" ... />
</Context>
et comme :
<Context path="/ApplicationContextY" ... >
<ResourceLink global="jdbc/ApplicationContextY_DatabaseName" name="jdbc/DatabaseName" ... />
</Context>
donc quelqu'un pourrait être inquiet du fait que le même name="jdbc/DatabaseName"
est recherchée, puis utilisée, par deux applications différentes déployées sur le même serveur : ce n'est pas un problème car l'adresse de l'utilisateur est la suivante jdbc/DatabaseName
est un contexte JNDI privé de l'application java:comp/env/
donc ApplicationContextX
en utilisant java:comp/env/
ne peut pas (à dessein) consulter la ressource liée à l'article. global="jdbc/ApplicationContextY_DatabaseName"
.
Bien sûr, si vous vous sentiez plus détendu sans ce souci, vous pourriez utiliser une stratégie de dénomination différente, par exemple :
<Context path="/ApplicationContextX" ... >
<ResourceLink global="jdbc/ApplicationContextX_DatabaseName" name="jdbc/applicationXprivateDatabaseName" ... />
</Context>
et comme :
<Context path="/ApplicationContextY" ... >
<ResourceLink global="jdbc/ApplicationContextY_DatabaseName" name="jdbc/applicationYprivateDatabaseName" ... />
</Context>