Existe-t-il des modèles ou des meilleures pratiques qui peuvent être utilisés pour simplifier la modification des profils de configuration pour les applications Web Java dans plusieurs environnements. Par exemple, les URL JDBC, SOAP end-points , etc.
Pour vous aider à clarifier ma question, je travaille avec plusieurs grandes applications Web Java qui, au cours d'un cycle de publication donné, se déplacent dans 6 environnements différents; développement, intégration, assurance qualité, performances et finalement obtiennent déployée sur plusieurs serveurs de production. Dans chaque environnement, la configuration doit changer. À l'heure actuelle, la plupart des modifications de configuration pour chaque déploiement sont effectuées manuellement, ce qui prend du temps et est ouvert aux erreurs.
Existe-t-il un moyen de supprimer l'intervention manuelle de ce processus?
J'ai tendance à travailler plus avec .NET ces derniers temps, donc mon Java est assez rouillé. Je suis sûr que cela fonctionnerait dans n'importe quel langage avec un petit ajustement.
Nous utilisons une extension du système de configuration .NET qui nous permet d'utiliser des paramètres spécifiques à l'environnement et/ou à l'application en conjonction avec une configuration plus globale. Le système de configuration utilise un paramètre Global pour chaque machine l'identifie comme dev, beta ou production (par défaut). Un ensemble de fichiers chargés dans l'ordre et le paramètre du dernier fichier remplace tout paramètre défini dans un fichier précédemment chargé. Les fichiers sont chargés dans l'ordre suivant:
Tous les fichiers sont sous contrôle de code source, et puisque l'environnement est défini sur la machine sur laquelle l'application s'exécute; comme il n'accèdera pas à la configuration "beta" à moins que la configuration de la machine ne l'identifie comme "beta", nous pouvons promouvoir tous les fichiers de configuration sans craindre de pointer par inadvertance notre application de production vers une base de données de développement.
Je suis surpris que personne n'ait cité l'API de configuration de Jakarta Commons ( http://commons.Apache.org/configuration/ ) pour répondre à cette question. Il vous permet d'avoir une hiérarchie de fichiers (ou d'autres sources de configuration comme XML, JNDI, JDBC, etc.). C'est ce dont parlait Jeremy Seghi et cela vous donne un bon moyen d'avoir à la fois des valeurs par défaut et des remplacements locaux.
La meilleure partie est qu'il s'agit d'une solution de travail testée, vous n'avez donc pas à créer quelque chose vous-même.
Voici quelques pratiques que j'ai utilisées ou rencontrées. Leur combinaison est généralement nécessaire dans la pratique.
Substitution des valeurs de variable dans les conffiles lors de la construction
Voici un exemple de la façon dont cela peut être fait avec Apache Ant. Propriétés de la fourmi (${var.name}
) peut être contrôlé avec les fichiers de configuration de construction:
<filterset id="variables.to.replace">
<filter token="APPNAME" value="${app.name}"/>
<filter token="WEBAPP-PATH" value="${webapp.path}"/>
<filter token="ENCRYPT-ALGORITHM" value="${encrypt.algorithm}"/>
<filter token="ERROR-MAILTO" value="${error.mailTo}"/>
<!--...-->
</filterset>
<!-- Then, when building & copying the conf, replace the variables: -->
<copy todir="${properties.target.dir}">
<!-- env specific conf files -->
<fileset dir="${basedir}/env/${run.env}/webapp/WEB-INF/classes" />
<filterset refid="variables.to.replace"/>
</copy>
La bonne chose est que vous obtenez un contrôle fin sur les différentes configurations au moment de la construction. Ce qui est mauvais, c'est que le système a tendance à devenir très complexe et difficile à maintenir si vous utilisez largement cette méthode pour un grand nombre de configurations différentes. De plus, devoir construire les conffiles signifie également des cycles de développement plus lents.
Substitution des variables de conf inside war au démarrage de la webapp
C'est ce que je fais habituellement lorsque j'utilise Spring Framework, même s'il n'y a qu'une seule configuration possible, tirant parti des avantages de la séparation des préoccupations. Avec Spring, vous pouvez faire remplacer les valeurs conf par PlaceholderPropertyConfigurer dans le contexte Spring au démarrage de la webapp. Dans ce cas, vous devez de toute façon choisir la bonne configuration, qui peut être configurée par exemple au moment de la construction.
Par rapport au remplacement du temps de génération, il est plus facile de manipuler temporairement les valeurs dans une webapp non compressée, si nécessaire. Bien sûr, la webapp doit être redémarrée si vous changez quoi que ce soit, et les modifications manuelles ne persisteront pas lors des redéploiements de la webapp. Spring est également limité au contexte Spring, donc cela ne fonctionne pas par exemple dans web.xml (mais avoir des variables dans web.xml devrait probablement être évité de toute façon en raison de ses limites).
Lecture de la conf locale à partir d'un fichier prédéfini
Cette approche est probablement la plus simple à mettre en place: il suffit d'inventer un chemin de fichier de configuration, par ex. $HOME/mywebapp/conf.properties
et faites en sorte que votre application Web le lise au démarrage.
La bonne chose ici est que vous n'avez pas à vous soucier de la conf lors de la construction/déploiement de la webapp. Quoi qu'il en soit, vous devriez avoir des valeurs par défaut de conf sensibles qui peuvent ensuite être remplacées par la conf locale.
Avoir la conf dans une base de données
Il s'agit de la solution la plus flexible pour remplacer les paramètres de conf, mais elle peut également se compliquer dans certains cas. Avoir la conf dans une table avec des colonnes name
et value
devrait fonctionner dans la plupart des cas.
Bien sûr, vous ne pouvez pas configurer les URL de connexion JDBC dans une table de base de données, mais c'est une bonne solution pour une simple configuration textuelle/numérique qui affecte le fonctionnement de la webapp une fois la connexion db établie. Pour éviter une dégradation des performances, assurez-vous de mettre en cache la configuration d'une manière ou d'une autre si elle sera fréquemment utilisée.
Pratiques supplémentaires
Comme l'a souligné kgiannakakis, cela aide également à mettre en place une page de diagnostic de configuration d'une sorte pour votre application.
Cela dépendra largement des options que les serveurs d'applications Web vous offrent. Nous avons plusieurs environnements pour JBoss avec différentes URL JDBC, le nom JNDI reste le même sur tous les serveurs, juste la configuration sur l'instance locale change, donc rien ne va de build en build.
Je suppose que la réponse courte est que la meilleure pratique consiste à externaliser les configurations et à conserver un bon fichier en place avec les paramètres corrects pour chaque serveur, et à ce que l'application Web lise cette configuration. La nature exacte de l'externalisation et de la lecture dépendra de la configuration spécifique et du serveur d'applications.
EDIT: Ces configurations n'existent pas dans le cadre de la guerre (l'oreille dans notre cas) de cette façon, elles ne sont pas écrasées.
Au début, ayez tous les paramètres de configuration qui changent fréquemment en un seul endroit. C'est vraiment difficile, si vous avez besoin de configurer JNDI, d'éditer les valeurs de la base de données et de modifier les fichiers de propriétés, tout en même temps, afin de terminer la configuration. Préférez le support le plus facile à modifier et aussi plus facile à vérifier que tout est correctement configuré. Je dirais que les fichiers de propriétés sont la meilleure solution. Vous pouvez facilement les modifier et vous n'avez qu'à les parcourir rapidement pour voir que tout va bien. Si vous optez pour des fichiers de propriétés, sélectionnez soigneusement un emplacement standard pour eux et affectez une variable d'environnement pour le chemin.
Cela aide également si vous disposez d'un test simple qui vérifie que tout est correctement configuré. Par exemple, vous pouvez avoir une page de test qui affiche les paramètres de configuration et effectue des tests de base, comme essayer de se connecter à une base de données ou à des serveurs distants.
Vous pouvez utiliser le modèle de configuration des composants dans la langue de votre choix
Il est décrit dans les livres de la POSA (je pense que dans le 4ème volume)
(dans Java vous pouvez utiliser le composant commons-configuration ).
Le bon exemple que vous voulez est utilisé dans Seam ou Grails (emprunté à Rails). Il existe des profils, par défaut trois: prod, dev, test, mais vous pouvez en définir plus si vous le souhaitez.
La construction d'un projet dans Seam se fait par des fichiers Ant. Chaque fichier dont le contenu peut varier est défini pour chaque profil, par ex. source de données, scripts SQL ou fichiers de propriétés.
import-dev.sql
import-prod.sql
import-test.sql
Lorsque le fichier ant est exécuté avec le profil choisi, le fichier approprié est pris et le nom du profil est tronqué à partir de ce nom de fichier.
Ci-dessous, un extrait de code que vous pouvez placer dans vos cibles
<copy tofile="${war.dir}/WEB-INF/classes/import.sql"
file="${basedir}/resources/import-${profile}.sql"/>
URL JDBC, les noms de pilotes peuvent être externalisés dans des fichiers de propriétés (bien sûr avec des noms de profil comme suffixes)
<filterset id="persistence">
<filter token="transactionManagerLookupClass" value="${transactionManagerLookupClass}"/>
<copy tofile="${war.dir}/WEB-INF/classes/META-INF/persistence.xml"
file="${basedir}/resources/META-INF/persistence-${profile}.xml">
<filterset refid="persistence"/>
</copy>
ou les valeurs des propriétés que vous pouvez passer à l'appel de génération ant à partir de la ligne de commande. Voici un petit exemple de ce que fait Seam.
Une autre option consiste à utiliser Maven . De manière maven, cela se fait par propriétés et par profils , mais vous pouvez également utiliser des modules séparés pour diviser la configuration et créer d'autres modules avec des fonctionnalités principales. Des exemples de cas d'utilisation typiques de propriétés et de profils maven sont la configuration d'exécution pour plusieurs bases de données, serveurs de déploiement, etc. C'est encore plus difficile lorsque vous souhaitez créer une configuration pour différents fournisseurs, mais pour Maven, ce n'est pas un problème :)
Un excellent exemple d'utilisation des profils maven est ce formulaire de publication blog Carlos Sanchez .
Pour résumer, je recommande fortement de rechercher Ant/Seam une paramétrisation Maven (profils). Ces solutions ont un autre avantage: le script ant ou maven peut être exécuté sur le serveur CI (comme Hudson ) et laisser exécuter/tester simultanément tous vos profils.
Il existe plusieurs façons possibles d'aborder cela:
utilisez les fichiers de propriétés comme vous le faites, mais ajoutez un fichier de "métadonnées" qui est utilisé pour sélectionner le fichier de propriétés utilisé en définissant une mappe entre une valeur d'environnement (par exemple nom d'hôte localhost) sur le nom du fichier de propriétés à charger.
placez vos propriétés dans une base de données et définissez la connexion de la base de données aux tables de propriétés de votre serveur d'applications en tant que ressource récupérée par votre application Web.
ne placez pas les fichiers de propriétés dans votre .war ou .ear, mais créez des archives properties-deployhost.jar contenant les fichiers de propriétés par hôte cible. liez le fichier .jar approprié à l'application Web déployée en l'ajoutant au chemin de classe (par exemple via des bibliothèques partagées dans la configuration du serveur d'applications par application Web).
Seule la première d'entre elles n'a pas besoin d'étapes manuelles supplémentaires lors du déploiement au détriment de la mise à jour de votre source de configuration et de la création de nouveaux fichiers de déploiement lorsque vos systèmes cibles sont renommés.
Je suis sûr que beaucoup de variantes sur ces derniers et votre approche sont possibles, quel est le meilleur choix dépend de votre situation.
Ce que nous faisons fonctionne plutôt bien.
Au démarrage, nos programmes lisent un fichier de configuration dans un chemin codé en dur. Disons que c'est:
/config/fun_prog/config.xml
Chaque programme a un chemin codé en dur différent (FunProgram est dans fun_prog, Super Server est dans sup_serv, peu importe), donc nous n'avons pas à nous soucier qu'ils marchent les uns sur les autres.
Les fichiers XML sont lus par une petite bibliothèque de configuration que nous avons créée. Le fichier XML contient les informations de connexion à la base de données, généralement les données de configuration du serveur de messagerie, les adresses e-mail auxquelles envoyer des notifications, s'il doit fonctionner en mode test, les URL des services externes, etc.
Ainsi, lorsque nous devons apporter des modifications, nous copions le fichier de configuration, modifions ce que nous voulons et redémarrons le programme. Étant donné que nous avons une configuration de serveur standard, tout programme peut être déployé sur n'importe quel serveur en copiant simplement ces fichiers (et le bricolage httpd.conf nécessaire).
Ce n'est pas luxueux, mais cela fonctionne très bien. Il est extrêmement simple à comprendre, à ajouter de nouvelles options de configuration, à sauvegarder et à modifier. Fonctionne sur toutes les plates-formes (unix est évident, Windows traduit les chemins commençant par/en c:\pour qu'il fonctionne sans modifications là aussi).
Nos postes de travail exécutent essentiellement le même logiciel que le serveur, juste avec quelques modifications dans ce fichier de configuration.
Veuillez consulter cette URL: http://issues.Apache.org/jira/browse/CONFIGURATION-394
Le cadre de configuration que nous recherchons est quelque chose en plus de la configuration Apache Commons et doit prendre en charge les problèmes de concurrence, les problèmes JMX et la plupart des magasins (par exemple, le fichier de propriétés, les fichiers .xml ou les préférencesAPI).
Ce que l'équipe de weblogic fournit sur la "console d'administration", c'est à travers lequel vous pouvez avoir des mises à jour transactionnelles (atomiques) sur les configurations afin que les auditeurs enregistrés soient informés.
Les gars d'Apache insistent sur le fait que ce projet est hors de portée de la configuration de Commons, peut-être!
J'ai joint un cadre de configuration simple, regardez s'il vous plaît.