Site icon Blog Zenika

Configuration dynamique du déploiement d'une application Spring

Le mécanisme de découpage des fichiers de configuration Spring permet de répartir les définitions de bean en fonction de leur type. Il est ainsi possible de configurer des éléments, comme la datasource, dans un fichier spécifique. Dans le cadre d’un test on pourra initialiser l’application contexte de Spring avec les fichiers applicationConfig.xml et test-infrastructure.xml, utilisant une dataSpurce locale, et dans un environnement de production on pourra utiliser les fichiers applicationConfig.xm et prod-infrastructure.xml utilisant une dataSource récupérée via JNDI. La question qui se pose maintenant est la suivante : Comment choisir dynamiquement les fichiers à utiliser en fonction de l’environnement de déploiement ?

Prenons l’exemple de code Java suivant :

  1. ApplicationContext context = new ClassPathXmlApplicationContext(
  2. new String[] {
  3. « classpath:com/zenika/spring/config/applicationContext.xml »,
  4. « classpath:com/zenika/spring/config/test-infrastructure.xml »,
  5. });

Pour s’exécuter dans un environnement de production, il faut modifier ce code afin de remplacer le fichier test-infrastructure.xml par le fichier prod-infrastructure.xml.
Le contenu du fichier test-infrastructure.xml

  1. <beans>
  2. <bean id=« dataSource » class=« org.springframework.jdbc.datasource.DriverManagerDataSource »>
  3. <property name=« driverClassName » value=« org.hsqldb.jdbcDriver »/>
  4. <property name=« url » value=« jdbc:hsqldb:xdb »/>
  5. <property name=« username » value=« sa »/>
  6. <property name=« password » value=«  »/>
  7. </bean>
  8. </beans>

Le contenu du fichier prod-infrastructure.xml

  1. <beans>
  2. <jee:jndi-lookup id=“dataSource” jndi-name=“java:comp/env/jdbc/credit” />
  3. </beans>

Déplaçons maintenant la dépendance à se fichier d’infrastructure au niveau de la configuration XML afin de rendre le code java immuable quel que soit l’environnement de déploiement ou d’exécution.
Le code Java n’importe plus qu’un seul fichier de configuration et peut donc s’écrire :

  1. ApplicationContext context = new ClassPathXmlApplicationContext(« classpath:com/zenika/spring/config/applicationContext.xml »);

Modifions maintenant le fichier applicationContext.xml afin d’utiliser la balise <import/> et d’importer le fichier qui nous intéresse avec la définition de la dataSource

  1. <beans>
  2. <bean id=« demoRepository » class=« com.zenika.spring.config.DemoRepository »>
  3. <constructor-arg ref=« dataSource »/>
  4. </bean>
  5. <import resource=« test-infrastructure.xml »/>
  6. </beans>

Dernière étape, rendre dynamique le choix du fichier importé en fonction d’une propriété système. On modifie pour cela la commande d’import en déclarant ici une variable ${env}

  1. <beans>
  2. <bean id=« demoRepository » class=« com.zenika.spring.config.DemoRepository »>
  3. <constructor-arg ref=« dataSource »/>
  4. </bean>
  5. <import resource=« ${env}-infrastructure.xml »/>
  6. </beans>

Il ne reste plus qu’à renseigner cette variable au démarrage de l’application, ou de la classe de test Java, en settant une propriété système.

Le remplacement de la variable ce fait par Spring au niveau de la classe DefaultBeanDefinitionDocumentReader

  1. /**
  2.  * Parse an « import » element and load the bean definitions
  3.  * from the given resource into the bean factory.
  4.  */
  5. protected void importBeanDefinitionResource(Element ele) {
  6. String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
  7. if (!StringUtils.hasText(location)) {
  8. getRea derContext().error(« Resource location must not be empty », ele);
  9. return;
  10. }
  11. // Resolve system properties: e.g. « ${user.dir} »
  12. location = SystemPropertyUtils.resolvePlaceholders(location);
  13. }
Quitter la version mobile