2010-11-30 8 views
8

Je me trouve en train d'utiliser deux beans identiques dans mon applicationContext.xml et mon applicationContext-test.xml. J'aimerais que mon contexte de test puisse hériter du contexte de mon application, pour éviter de me répéter.Comment déclarer un contexte d'application parent

J'ai vu beaucoup de matériel indiquant que vous pouvez déclarer un contexte d'application parent et des beans de référence à partir de ce contexte, mais je ne trouve pas d'exemple utile. Quelqu'un peut-il aider?

Mise à jour Comme quelques informations de fond, mon contexte d'application normale est chargée dans web.xml:

<context-param> 
    <description>Application Contexts for Spring</description> 
    <param-name>contextConfigLocation</param-name> 
    <param-value>/WEB-INF/classes/applicationContext.xml</param-value> 
</context-param> 

<listener> 
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
</listener> 

Mon contexte d'application de test est chargé dans mes tests unitaires:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = "/applicationContext-test.xml") 

Alors disons que j'ai un haricot dans mon contexte habituel:

<bean name="someBean" class="com.foo.MyClass" /> 

Ensuite, dans mon contexte d'application de test, j'aimerais me référer à ce bean. Comment fait-on ça?

Mise à jour

par la suggestion de skaffman, je me suis déplacé le haricot dans un fichier SharedBeans.xml et importé dans mon applicationContext.xml. Cependant, cela provoque une exception SAXParser:

org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Failed to import bean definitions from URL location [classpath:SharedBeans.xml] 
Offending resource: ServletContext resource [/WEB-INF/classes/applicationContext.xml]; nested exception is org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 1 in XML document from class path resource [SharedBeans.xml] is invalid; nested exception is org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element 'bean'. 
    at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:68) 

Je ne peux pas être sûr de ce que je fais mal. Le haricot fonctionnait correctement dans mon fichier de contexte, et tout ce que j'ai fait était couper et coller dans le nouveau fichier. Voici le contenu de SharedBeans.xml dans son intégralité:

<bean name="properties" class="com.foo.Properties"> 
    <constructor-arg><value>${module.name}</value></constructor-arg> 
    <constructor-arg><value>${businessUnit}</value></constructor-arg> 
    <constructor-arg><value>${product}</value></constructor-arg> 
    <constructor-arg><value>${env}</value></constructor-arg> 
    <constructor-arg><value>${machineName}</value></constructor-arg> 
    <constructor-arg><value>${collectionSet.company}</value></constructor-arg> 
    <constructor-arg><value>${route.tag}</value></constructor-arg> 
    <constructor-arg><value>${timeout}</value></constructor-arg>  
</bean> 
+1

Cela dépend de comment vous avez configuré les choses. Veuillez donner un exemple de votre utilisation de vos contextes. – skaffman

+0

@skaffman: Question mise à jour. Exemples appréciés. – Samo

+2

Vous avez toujours besoin de l'élément de niveau supérieur .... – skaffman

Répondre

5

Cela ne me paraît pas particulièrement bon cas d'utilisation d'un contexte parent, qui est surtout utile de mettre en place une hiérarchie (par exemple une racine contexte webapp, contextes multiples de servlets enfants). Pour votre situation, il va être plus simple et plus facile à comprendre si vous venez d'extraire les définitions de beans communs dans un fichier séparé, puis <import> dans chaque fichier de contexte qui en a besoin. Vous pouvez faire cela avec des contextes parent-enfant, mais il va être plus difficile à comprendre, inutilement.

OK, donc un exemple, mettre votre définition de haricot partagé dans un fichier appelé shared-beans.xml, et le mettre (pour l'instant) au plus haut niveau de votre classpath, contenant:

<bean name="someBean" class="com.foo.MyClass" /> 

Puis, à l'intérieur applicationContext-test.xml et /WEB-INF/classes/applicationContext.xml, ajoutez ce qui suit:

<import resource="classpath:/shared-beans.xml" /> 

Toutes les définitions de haricots dans shared-beans.xml va maintenant être importés dans le contexte de chaque application. Vous n'obtenez pas un troisième contexte d'application en faisant cela, vous importez simplement les définitions de bean d'un autre fichier.

+1

Pourriez-vous clarifier s'il vous plaît? Quand vous dites "un fichier séparé", est-ce une usine de haricots? Si non, qu'est-ce que c'est? Vous dites que je peux les importer de ce fichier, mais pouvez-vous donner un exemple démontrant comment cela est fait? – Samo

+0

Je reçois une exception SAXParser. S'il vous plaît voir la question mise à jour. Je ne suis pas sûr de ce que je pourrais faire de mal. – Samo

0

Vous pouvez déplacer votre déclaration commune vers le fichier XML séparé et la placer dans classpath (pour un accès facile depuis le test).Ensuite, vous pouvez effectuer les opérations suivantes:

<context-param> 
    <description>Application Contexts for Spring</description> 
    <param-name>contextConfigLocation</param-name> 
    <param-value> 
     /WEB-INF/classes/applicationContext.xml 
     classpath:/common-beans.xml 
    </param-value> 
</context-param> 

.

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(
    locations = {"/applicationContext-test.xml", "common-beans.xml"}) 

Vous pouvez également inclure common-beans.xml des deux contextes en utilisant <import>, comme le suggère skaffman.

Questions connexes