Uso de varios archivos de propiedades (a través de PropertyPlaceholderConfigurer) en varios proyectos / módulos

104

Actualmente estamos escribiendo una aplicación que se divide en varios proyectos / módulos. Por ejemplo, tomemos los siguientes módulos:

  • myApp-DAO
  • myApp-jabber

Cada módulo tiene su propio archivo xml de contexto Spring. Para el módulo DAO tengo un PropertyPlaceholderConfigurer que lee un archivo de propiedades con los parámetros de conexión de base de datos necesarios. En el módulo jabber también tengo un PropertyPlaceHolderConfigurer para las propiedades de conexión del jabber.

Ahora viene la aplicación principal que incluye myApp-DAO y myApp-jabber. Lee todos los archivos de contexto e inicia un gran contexto de Spring. Desafortunadamente, parece que solo puede haber un PropertyPlaceholderConfigurer por contexto, por lo que cualquier módulo que se cargue primero puede leer sus parámetros de conexión. El otro arroja una excepción con un error como "No se pudo resolver el marcador de posición 'jabber.host'"

Entiendo cuál es el problema, pero realmente no conozco una solución, o la mejor práctica para mi caso de uso.

¿Cómo configuraría cada módulo para que cada uno pueda cargar su propio archivo de propiedades? En este momento, saqué PropertyPlaceHolderConfigurer de los archivos de contexto separados y los combiné en el contexto de la aplicación principal (cargando todos los archivos de propiedades con un solo PropertyPlaceHolderConfigurer). Sin embargo, esto apesta, porque ahora todos los que usan el módulo dao tienen que saber que necesitan un PropertyPlaceHolderConfigurer en su contexto ... también fallan las pruebas de integración en el módulo dao, etc.

Tengo curiosidad por conocer soluciones / ideas de la comunidad de stackoverflow.

negro666
fuente

Respuestas:

182

Si se asegura de que todos los marcadores de posición, en cada uno de los contextos involucrados, ignoren las claves que no se pueden resolver, ambos enfoques funcionan. Por ejemplo:

<context:property-placeholder
location="classpath:dao.properties,
          classpath:services.properties,
          classpath:user.properties"
ignore-unresolvable="true"/>

o

    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:dao.properties</value>
                <value>classpath:services.properties</value>
                <value>classpath:user.properties</value>
            </list>
        </property> 
        <property name="ignoreUnresolvablePlaceholders" value="true"/>
    </bean>
Tim Hennekey
fuente
11
Aquí hay una entrada útil sobre el tema que debería ayudarlo a resolver aún más estos problemas: tarlogonjava.blogspot.com/2009/02/tips-regarding-springs.html
Tim Hennekey
2
¡¡GRACIAS!! ignore-unresolvable = "true" era exactamente lo que necesitaba y funcionó.
black666
1
Si agrega todos los archivos en 1 etiqueta, entonces no necesita evento ignore-unresolvable="true", de lo contrario necesita.
Eric Wang
¿Puedes explicar el significado de ignoreUnresolvablePlaceholders? ¿Qué son los marcadores de posición irresolubles?
emeraldhieu
PropertySourcesPlaceholderConfigureres la implementación de respaldo predeterminada desde Spring 3.1, por lo que es sensato usarla en lugar de PropertyPlaceholderConfigurercomo la clase de implementación de bean.
jihor
18

Sé que esta es una vieja pregunta, pero el ignore-unresolvable propiedad no me funcionaba y no sabía por qué.

El problema era que necesitaba un recurso externo (algo así como location="file:${CATALINA_HOME}/conf/db-override.properties") y ignore-unresolvable="true"no funciona en este caso.

Lo que se debe hacer para ignorar un recurso externo faltante es:

ignore-resource-not-found="true"

En caso de que alguien más se encuentre con esto.

Raul René
fuente
3
ignore-unresolvabley ignore-resource-not-foundsirven para diferentes propósitos. Para evitar errores cuando el archivo de propiedades no existe, utilice ignore-resource-not-found="true". Para evitar errores cuando usa una propiedad que no existe en el archivo , use ignore-unresolvable="true". Si tiene varios archivos, cada uno de los cuales contiene conjuntos parciales de propiedades, y cada archivo puede existir o no, deberá usar ambos.
datguy
8

Puede tener varios <context:property-placeholder />elementos en lugar de declarar explícitamente varios beans PropertiesPlaceholderConfigurer.

Earldouglas
fuente
Intenté usar dos elementos <context: property-placeholder /> y Spring se quejó de que no podía identificar la propiedad especificada. Tengo que implementar la respuesta aceptada para que funcione.
Mushy
4

El PropertiesPlaceholderConfigurerbean tiene una propiedad alternativa llamada "propertiesArray". Use esto en lugar de la propiedad "propiedades" y configúrelo con <array>referencias de propiedad.

Stephen C
fuente
2

Probé la solución a continuación, funciona en mi máquina.

<context:property-placeholder location="classpath*:connection.properties" ignore-unresolvable="true" order="1" />

<context:property-placeholder location="classpath*:general.properties" order="2"/>

En caso de que haya varios elementos presentes en el contexto de Spring, hay algunas mejores prácticas que deben seguirse:

El atributo de orden debe especificarse para fijar el orden en el que Spring los procesa. Todos los marcadores de posición de propiedad menos el último (el orden más alto) deberían tener ignore-unresolvable=”true”para permitir que el mecanismo de resolución pase a otros en el contexto sin lanzar una excepción.

fuente: http://www.baeldung.com/2012/02/06/properties-with-spring/

onurbaysan
fuente
¿Se requiere un pedido especificado? Intenté esto y el jvm se quejó.
Mushy