J'ai une application Web qui s'appuie sur certaines ressources et certains paramètres à configurer après son installation, comme une connexion JDBC.
Ce que j'ai trouvé, c'est de fournir un META-INF/context.xml
qui est copié dans [engine-name]/[server-name]/[app-name].xml
par Tomcat lorsque je déploie l'application. De cette façon, tout ce que je fournis est un fichier de guerre qui peut être copié dans le dossier appBase (webapps). La documentation de Tomcat dit s'il existe un tel fichier, il ne sera pas écrasé, ce qui est vraiment génial, car les modifications apportées après le déploiement ne seront pas perdues.
Mais il y a un problème subtil ici: puisque nous déployons l'application en copiant dans le répertoire webapps, Tomcat désinstallera d'abord l'application existante ainsi que le fichier de configuration. De cette façon, le fichier de configuration sera perdu/écrasé, ce qui n'est pas souhaitable. Tomcat ne le fera pas modifier ce comportement pour autant que je sache.
La question est: existe-t-il un moyen de contourner ce problème en installant l'application de manière à ce que Tomcat ne supprime pas le fichier de configuration existant. Ou, existe-t-il une meilleure façon de conditionner l'application?
Veuillez noter que nous ne voulons pas définir autoDeploy sur false et que nous ne pouvons pas utiliser d'intervention humaine pour l'installation (ce qui exclut l'utilisation de l'application Web Tomcat Manager).
Si j'obtiens le fichier de configuration du fichier .war et le copie séparément en tant que [engine-name]/[server-name]/[app-name].xml
, Tomcat l'associera toujours à mon application et la supprimera une fois que j'aurai copié un nouveau fichier .war.
Une autre hypothèse est la suivante: nous ne connaissons pas à l'avance les valeurs de la configuration. Nous ne fournirons qu'un exemple de configuration (un espace réservé, si vous le souhaitez) tandis que la configuration réelle sera effectuée ultérieurement (pas nécessairement au moment de l'installation).
Merci
J'ai réussi à résoudre ce problème d'une manière ou d'une autre.
1- Installez un répertoire WAR éclaté quelque part extérieur AppBase de Tomcat, supposons qu'il se trouve dans /usr/local/MyApp
. [Vous pouvez utiliser un fichier WAR pour cette étape au lieu du répertoire WAR, si votre application s'exécute à partir d'une guerre non explosée.]
2- Copiez le fichier de configuration du contexte dans [Tomcat.conf]/[engine]/[hostname]
répertoire, appelons-le MyApp.xml
. Ce fichier pointera vers l'emplacement de l'application:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Context configuration file for my web application -->
<Context docBase="/usr/local/MyApp" privileged="true" antiResourceLocking="false" antiJARLocking="false">
<Resource name="jdbc/myapp-ds" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000" username="XXX" password="XXX"
driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/mydb" />
</Context>
3- Vous êtes maintenant libre d'aller modifier le fichier de configuration.
4- Mettez à jour l'application en copiant la nouvelle version de votre application dans/usr/local/MyApp
Remarques:
a) Cette solution s'applique également à un fichier .war non développé, mais puisque nous utilisons Log4JConfigListener de Spring, il ne s'exécuterait pas à partir d'un fichier .war non explosé. Tomcat n'explose pas les fichiers .war placés hors du dossier appBase (webapps).
b) Cette approche ne vous empêche pas d'avoir context.xml dans /usr/local/MyApp/META-INF/context.xml car il ne sera pas utilisé par Tomcat dans cette configuration. Vous pouvez l'utiliser dans votre environnement de développement, où vous videz votre fichier .war dans le dossier appBase (webapps).
C'est ce que j'ai jusqu'à présent, toujours à la recherche de meilleures solutions.
La solution est simple: ne mettez pas de configuration dans votre context.xml.
Voici une solution que nous utilisons (qui fonctionne bien pour un certain nombre de clients externes divers):
Nous avons une seule guerre qui sera utilisée dans plusieurs environnements, webapp.war. Nous avons trois environnements, développement, intégration et production. L'intégration et la production sont chez le client. Nous ne connaissons pas les mots de passe et les chemins de fichiers pour les sites d'intégration et de production des clients.
Nous utilisons une combinaison de deux choses: la recherche JNDI pour les éléments de base de données et les fichiers de propriétés externes.
Dans le context.xml
qui est livré pendant la guerre, nous avons un ResourceLink
<ResourceLink name="jdbc/webapp"
global="uk.co.farwell.webapp.datasource.MySqlDataSource" />
Cela donne une référence à une source de données définie globalement, qui est définie dans le server.xml
pour Tomcat.
<Resource auth="Container"
driverClassName="com.mysql.jdbc.Driver"
name="uk.co.farwell.webapp.datasource.MySqlDataSource"
password="xxx" url="xxx" username="fff" />
Ainsi, les détails de la base de données peuvent être modifiés en modifiant le server.xml
sans changer le webapp.war
. Surtout, cela ne doit être fait qu'une seule fois pour chaque serveur, pas au redéploiement.
Dans notre configuration de printemps, pour définir le dataSource
nous avons:
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/webapp" />
Pour les autres propriétés, nous avons un fichier global application.properties qui est livré avec le webapp.war, mais ne fait pas partie de la guerre. Ceci est référencé par un -D
sur la ligne de commande pour démarrer Tomcat. -Duk.co.farwell.webapp.applicationDir="/usr/xxx/fff"
. Nous prenons la définition et lisons le fichier de propriétés. Les trucs de la base de données pourraient également se faire de cette façon, mais nous perdrions le regroupement effectué par Tomcat.
Autre chose: nous n'avons pas à reconstruire si les serveurs sont déplacés ou si les machines sont modifiées pour une raison quelconque. C'est une question pour le client et les personnes chargées de l'infrastructure.
C'est ainsi que nous pouvons gérer l'externalisation du contexte webapp à partir du fichier .WAR
Par exemple J'ai une webapp appelée VirtualWebApp.
Je vais créer un fichier comme VirtualWebApp.xml avec la définition de contexte ci-dessous:
<Context docBase="/home/appBase/VirtualWebApp" path="/VirtualWebApp" reloadable="true">
<Environment name="webservice.Host" type="Java.lang.String" value="1.2.3.4" />
<Environment name="webservice.port" type="Java.lang.String" value="4040" />
</Context>
Pour accéder à ces variables d'environnement, vous devez écrire le code ci-dessous (il suffit de rechercher):
InitialContext initialContext = new javax.naming.InitialContext();
Host = (String)initialContext.lookup("Java:comp/env/webservice.Host");
port = (String)initialContext.lookup("Java:comp/env/webservice.port");
En se référant à Documentation Apache Tomcat 5.5 :
Dans le fichier $ CATALINA_HOME/conf/context.xml: les informations de l'élément Context seront chargées par toutes les webapps
Vous pouvez facilement essayer cette approche, cela pourrait fonctionner, mais je ne suis pas sûr que ce soit une bonne solution, surtout si vous exécutez plusieurs applications Web sur Tomcat.
@ n0rm1e: je ne sais pas si Tomcat fournit une sorte de solution pour votre problème. Mais une solution possible peut être: - créer un script ant avec les étapes suivantes:
i) Vérifiez l'existence du fichier .xml dans le répertoire [nom-moteur]/[nom-serveur]. S'il existe, sauvegardez-le/renommez-le.
ii) copiez votre fichier war sur les webapps Tomcat. Redémarrez le serveur Tomcat.
iii) recopiez le fichier de configuration sauvegardé dans le répertoire [nom-moteur]/[nom-serveur]
Je ne sais pas comment modifier le comportement de Tomcat mais je pourrais penser à 2 solutions différentes:
env
à vos scripts de construction et en fonction de la valeur, il place l'environnement spécifique context.xml
dans votre WAR pendant la construction.install
pour chaque environnement qui redéploie d'abord le fichier WAR (le place dans le répertoire webapps
), puis modifie l'installation de Tomcat en fonction de l'environnement, par exemple nom d'hôte différent pour JDBC DataSource dans context.xml
.J'utilise beaucoup cette dernière approche car elle fonctionne dans les environnements d'entreprise. Les politiques de séparation des tâches interdisent souvent à l'équipe de développement de savoir, par exemple. mots de passe de la base de données de production. L'option n ° 2 résout ce problème car seules les opérations informatiques ont accès aux scripts d'installation spécifiques à l'environnement après leur création.