Bonjour à tous,
j'utilise Spring dans mon projet, qui inclut plusieurs sous-projets (je vous fait grâce du pourquoi du découpage)
/infra
/svc-client
/research
/simulations
Et dans chaque projet, on a le découpage en codes sources et ressources :
/src
/main
/java
/resources -> c'est là que sont mis les fichiers "properties", de configuration spring, etc
/test
/java
/resources
Le fichier père de configuration Spring est
simulations/src/main/resources/beanRefFactory.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<!-- ********************************************* -->
<!-- Will load the infra layer (JMS factopry etc) -->
<!-- ********************************************* -->
<!-- <bean id="infra" lazy-init="false" -->
<!-- class="org.springframework.context.support.ClassPathXmlApplicationContext"> -->
<!-- <constructor-arg> -->
<!-- <list> -->
<!-- <value>infra-context.xml</value> -->
<!-- </list> -->
<!-- </constructor-arg> -->
<!-- </bean> -->
<!-- ******************************* -->
<!-- Will load the data server layer -->
<!-- ******************************* -->
<bean id="dataserver.client" lazy-init="false"
class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<list>
<value>data-server-client-context.xml</value>
<value>data-server-client-rmi-proxy-context.xml</value>
</list>
</constructor-arg>
</bean>
<!-- **************************** -->
<!-- Will load the service layer -->
<!-- **************************** -->
<bean id="svc.client" lazy-init="false"
class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<list>
<value>svc-client-context.xml</value>
<value>svc-client-rmi-proxy-context.xml</value>
<value>infra-context.xml</value>
</list>
</constructor-arg>
<constructor-arg>
<ref bean="dataserver.client" />
</constructor-arg>
</bean>
<!-- **************************** -->
<!-- Will load the service layer -->
<!-- **************************** -->
<bean id="research" lazy-init="false"
class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<list>
<value>research-context.xml</value>
</list>
</constructor-arg>
<constructor-arg>
<ref bean="svc-client" />
</constructor-arg>
</bean>
</beans> |
Lorsque, dans mon code Java, je charge le fichier de configuration Spring, je charge le bean "research", qui demande alors à charger le bean "svc-client".
SingletonBeanFactoryLocator.getInstance().useBeanFactory("research");
Ici, petit apparté : j'aurais bien voulu découper davantage : en appelant le bean "svc-client" et "infra" dans la balise "constructor-arg". Toutefois, j'ai alors l'erreur suivante :
"Could not resolve matching constructor (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)"
(quand j'ai 2 fois la balise "<constructor-arg>", chacune avec un bean)
C'est pourquoi, pour simplifier, j'inclus le fichier "infra-context.xml" dans le bean "svc-client".
Mais passons ...
Les fichiers en question sont :
research/src/main/resources :
research-context.xml
infra/src/main/resources :
infra-context.xml et infra.properties
svc-client/src/main/resources :
rmi-client.properties
svc-client-context.xml
svc-client-rmi-proxy-context.xml
Le fichier "svc-client-context.xml" est le suivant :
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:component-scan base-package="com.truc.svc.client" />
<context:annotation-config />
</beans> |
Le second fichier, svc-client-rmi-proxy-context%.xml est une définition des services. Il est assez long, je n'en montre qu'un bout pour être plus concis :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<bean id="svcClientPropPlaceholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:rmi-client.properties</value>
</property>
<property name="systemPropertiesModeName">
<value>SYSTEM_PROPERTIES_MODE_OVERRIDE</value>
<!-- variable will be overridden by environment variables -->
</property>
</bean>
<!--
RMI services. Should be used unless RMI port is not accessible.
-->
<bean id="testService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl"
value="rmi://${rmi.svcserver.name}:${rmi.svcserver.port}/rmiTestService" />
<property name="serviceInterface" value="com.nexar.svc.client.bucket.BucketService" />
<property name="refreshStubOnConnectFailure" value="true" />
</bean> |
Les variables, du type "rmi.svcserver.name" sont définies dans le fichier de propriétés "rmi-client.properties"
Le dernier fichier, "infra-context.xml" est le suivant :
(lui aussi est un peu long, je le résume) :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com.truc.infra" />
<context:annotation-config/>
<bean id="infraPropPlaceholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:infra.properties</value>
</property>
<property name="systemPropertiesModeName">
<value>SYSTEM_PROPERTIES_MODE_OVERRIDE</value>
<!-- variable will be overridden by environment variables -->
</property>
</bean>
<!-- *** Messaging *** -->
<!-- General infos -->
<!-- JMS ConnectionFactory to use -->
<bean id="jmsFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://${jms.broker.url}:${jms.broker.port}" />
</bean> |
Idem, les variables du type "jms.broker.port" sont définies dans le fichier "infra.properties"
Enfin, dans le fichier "research-context.xml", j'utilise simplement une référence à un bean défini ailleurs, "jmsfactory", pour pouvoir écouter des Topics :
1 2 3 4 5 6 7
| <bean id="messageListener" class="com.nexar.research.listener.JMSResearchMessageListener" />
<bean id="jmsContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsFactory" />
<property name="destination" ref="volartTopic" />
<property name="messageListener" ref="messageListener" />
</bean> |
Quand je lance le programme, lorsqu'il parse la configuration de Spring 'fichier "beanRefFactory" du programme "simulations", j'ai l'erreur suivante :
Invalid bean definition with name 'jmsFactory' defined in class path resource [infra-context.xml]: Could not resolve placeholder 'jms.broker.url'
J'en déduis qu'il n'arrive pas à charger la valeur de "jms.broker.url", dans le fichier "infra-context.xml" (les valeurs se trouvent dans "infra.properties" dans le même répertoire").
Pourtant, dans le projet "svc-client", j'ai aussi un fichier xml qui a des variables chargées via un fichier de propriétés ("svc-client-rmi-proxy-context.xml" avec "rmi-client.properties"), et je n'ai pas de message d'erreur (et en plus, c'est un fichier qui, me semble t'il, est chargé en premier, et ce sans erreur.
Alors ?
D'où peut venir le fait que Spring ne charge pas correctement le fichier "infra.properties" ?
Cordialement,
Partager