Usando vários arquivos de propriedade (via PropertyPlaceholderConfigurer) em vários projetos / módulos

104

No momento, estamos escrevendo um aplicativo que está dividido em vários projetos / módulos. Por exemplo, vamos pegar os seguintes módulos:

  • myApp-DAO
  • myApp-jabber

Cada módulo tem seu próprio arquivo xml de contexto Spring. Para o módulo DAO, tenho um PropertyPlaceholderConfigurer que lê um arquivo de propriedades com os parâmetros de conexão do banco de dados necessários. No módulo jabber, também tenho um PropertyPlaceHolderConfigurer para as propriedades de conexão do jabber.

Agora vem o aplicativo principal que inclui myApp-DAO e myApp-jabber. Ele lê todos os arquivos de contexto e inicia um grande contexto Spring. Infelizmente, parece que só pode haver um PropertyPlaceholderConfigurer por contexto, portanto, o módulo que for carregado primeiro será capaz de ler seus parâmetros de conexão. O outro lança uma exceção com um erro como "Não foi possível resolver o marcador de posição 'jabber.host'"

Eu meio que entendo qual é o problema, mas não sei realmente uma solução - ou a melhor prática para meu caso de uso.

Como eu configuraria cada módulo para que cada um pudesse carregar seu próprio arquivo de propriedades? No momento, movi PropertyPlaceHolderConfigurer dos arquivos de contexto separados e os mesclei no contexto do aplicativo principal (carregando todos os arquivos de propriedade com um único PropertyPlaceHolderConfigurer). No entanto, isso é uma merda, porque agora todos que usam o módulo dao precisam saber que precisam de um PropertyPlaceHolderConfigurer em seu contexto .. também os testes de integração no módulo dao falham etc.

Estou curioso para saber sobre soluções / ideias da comunidade stackoverflow.

preto666
fonte

Respostas:

182

Se você garantir que cada espaço reservado, em cada um dos contextos envolvidos, está ignorando as chaves insolúveis, então ambas as abordagens funcionam. Por exemplo:

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

ou

    <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
fonte
11
Aqui está uma entrada útil sobre o assunto que deve ajudá-lo a resolver ainda mais esses problemas: tarlogonjava.blogspot.com/2009/02/tips-regarding-springs.html
Tim Hennekey
2
OBRIGADO!! ignore-unresolvable = "true" era exatamente o que eu precisava e funcionou!
black666
1
Se você adicionar todos os arquivos em 1 tag, não haverá necessidade de evento ignore-unresolvable="true", caso contrário, será necessário.
Eric Wang
Você pode explicar o significado de ignoreUnresolvablePlaceholders? O que são marcadores de posição não resolvíveis?
emeraldhieu
PropertySourcesPlaceholderConfigureré a implementação de suporte padrão desde Spring 3.1, portanto, é sensato usar em vez de PropertyPlaceholderConfigurercomo a classe de implementação do bean.
jihor
18

Eu sei que essa é uma pergunta antiga, mas o ignore-unresolvableimóvel não estava funcionando para mim e eu não sabia por quê.

O problema era que eu precisava de um recurso externo (algo como location="file:${CATALINA_HOME}/conf/db-override.properties") e o ignore-unresolvable="true"não faz o trabalho neste caso.

O que se precisa fazer para ignorar um recurso externo ausente é:

ignore-resource-not-found="true"

Apenas no caso de alguém esbarrar nisso.

Raul Rene
fonte
3
ignore-unresolvablee ignore-resource-not-foundservem a propósitos diferentes. Para evitar erros quando o arquivo de propriedades não existe, use ignore-resource-not-found="true". Para evitar erros ao usar uma propriedade que não existe no arquivo , use ignore-unresolvable="true". Se você tiver vários arquivos, cada um contendo conjuntos parciais de propriedades, e cada arquivo pode ou não existir, você precisará usar ambos.
datguy
8

Você pode ter vários <context:property-placeholder />elementos em vez de declarar explicitamente vários beans PropertiesPlaceholderConfigurer.

Earldouglas
fonte
Tentei usar dois elementos <context: property-placeholder /> e spring reclamou que não conseguiu identificar a propriedade especificada. Tenho que implementar a resposta aceita para que funcione.
Mushy
4

O PropertiesPlaceholderConfigurerbean possui uma propriedade alternativa chamada "propertiesArray". Use-a em vez da propriedade "propriedades" e configure-a com uma <array>das referências de propriedade.

Stephen C
fonte
2

Tentei a solução abaixo, funciona na minha máquina.

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

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

No caso de vários elementos estarem presentes no contexto Spring, existem algumas práticas recomendadas que devem ser seguidas:

o atributo order precisa ser especificado para corrigir a ordem em que são processados ​​pelo Spring todos os marcadores de posição de propriedade menos o último (ordem mais alta) devem ignore-unresolvable=”true”permitir que o mecanismo de resolução passe para outros no contexto sem lançar uma exceção

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

Onurbaysan
fonte
O pedido especificado é obrigatório? Tentei fazer isso e o jvm reclamou.
Mushy