Perfil padrão no Spring 3.1

100

Em meu aplicativo, tenho beans anotados com @Profile("prod")e @Profile("demo"). O primeiro, como você pode imaginar :), é usado em beans que se conectam ao banco de dados de produção e o segundo anota os beans que usam algum banco de dados falso ( HashMapou qualquer outro) - para tornar o desenvolvimento mais rápido.

O que eu gostaria de ter é o perfil padrão ( "prod") que será usado sempre se não for substituído por " outra coisa ".

Perfeito seria ter em meu web.xml:

<context-param>
     <param-name>spring.profiles.active</param-name>
     <param-value>prod</param-value>
</context-param>

e, em seguida, substituir isso com -Dspring.profiles.active="demo"para que eu pudesse fazer:

mvn jetty:run -Dspring.profiles.active="demo". 

Mas, infelizmente, isso não está funcionando. Alguma ideia de como eu poderia conseguir isso? Definir -Dspring.profiles.active="prod"em todos os meus ambientes não é uma opção.

Michał Margiel
fonte

Respostas:

67

Minha experiência é que usando

@Profile("default")

o bean somente será adicionado ao contexto se nenhum outro perfil for identificado. Se você passar em um perfil diferente, por exemplo -Dspring.profiles.active="demo", este perfil será ignorado.

Paul Philion
fonte
4
A resposta aceita depende do web.xml (e tudo bem), mas essa resposta funciona quer você tenha o web.xml ou não e, portanto, é mais amplamente útil para todos.
Jay
1
esta solução é muito mais limpa
cahen
Este é um recurso oficial ou algum efeito colateral? Você gostaria de fazer um link para a documentação do Spring onde este recurso é descrito?
enferrujado,
111

Defina seu ambiente de produção como perfil padrão em seu web.xml

<context-param>
   <param-name>spring.profiles.default</param-name>
   <param-value>prod</param-value>
</context-param>

e se você quiser usar um perfil diferente, passe-o como propriedade do sistema

mvn -Dspring.profiles.active="demo" jetty:run
andih
fonte
3
Não ele tentou definir o perfil ativo no web.xml e como propriedade do sistema. Na minha solução configuro um perfil padrão no web.xml e sobrescrevo / defino o perfil ativo via propriedade do sistema. Se não houver um perfil ativo explícito, o padrão será usado.
andih
1
Obrigado! isso é exatamente o que eu queria! não consegui encontrar em lugar nenhum: /
Michał Margiel
Um problema com esta abordagem: se você definir spring.profiles.default=prodem application.properties, então application-prod.propertiesnão será carregado. Isso é contra-intuitivo.
gamliela
@gamliela A abordagem não define o perfil padrão em um application.propertiesarquivo. Para saber o que application-prod.propertiesdeve ser usado, você terá que conhecer o perfil. É isso que essa abordagem faz. Ele define perfis fora do contexto da mola web.xml(padrão) ou via variável de ambiente (sobrescrever o padrão).
andih 01 de
@andih Sim, eu sei disso, mas só digo que não é intuitivo e, portanto, problemático. Já que application-default.propertiesfoi carregado, também espero que application-newdefault.propertiesseja carregado. Não é um problema com a sua solução, é um problema com o Spring ...
gamliela 01 de
6

Eu tenho o mesmo problema, mas eu uso WebApplicationInitializer para configurar o ServletContext programaticamente (Servlet 3.0+). Então, eu faço o seguinte:

public class WebAppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext sc) throws ServletException {
        // Create the 'root' Spring application context
        final AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        // Default active profiles can be overridden by the environment variable 'SPRING_PROFILES_ACTIVE'
        rootContext.getEnvironment().setDefaultProfiles("prod");
        rootContext.register(AppConfig.class);

        // Manage the lifecycle of the root application context
        sc.addListener(new ContextLoaderListener(rootContext));
    }
}
mcoolive
fonte
5

Você também pode considerar a remoção do perfil PROD e usar @Profile ("! Demo")

blacelle
fonte
2
Suponho que isso não funcionaria caso você tenha mais de dois perfis, certo?
Corte em
3

Sobre a configuração do perfil de produção padrão já postado @andih

A maneira mais fácil de definir o perfil padrão para o plugin maven jetty é incluir o elemento abaixo na configuração do plugin:

<plugin>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-maven-plugin</artifactId>
    <configuration>
        <systemProperties>
            <systemProperty>
                <name>spring.profiles.active</name>
                <value>demo</value>
            </systemProperty>
        </systemProperties>
    </configuration>
</plugin>
Jakub Kubrynski
fonte
3

Spring fornece duas propriedades separadas ao determinar quais perfis estão ativos:

  • spring.profiles.active

e

  • spring.profiles.default

Se spring.profiles.activeestiver definido, seu valor determinará quais perfis estão ativos. Mas se spring.profiles.activenão estiver definido, o Spring olha paraspring.profiles.default.

Se nem spring.profiles.activenem spring.profiles.defaultestiver definido, não haverá perfis ativos e apenas os beans que não estão definidos como estando em um perfil são criados. Qualquer bean que não especifique um perfil pertence ao defaultperfil.

Touhidur Rahaman Khan
fonte
-1

Você pode configurar seu web.xml como recurso filtrado e ter esse valor preenchido pelo maven nas configurações de perfil do maven - é isso o que fazemos.

no pom filtrar todos os recursos (você pode fazer isso se não tiver $ {} marcação neles)

<webResources>
    <resource>
        <directory>src/main/webapp</directory>
        <filtering>true</filtering>
    </resource>
</webResources>

em web.xml colocar

<context-param>
     <param-name>spring.profiles.active</param-name>
     <param-value>${spring.prfile}</param-value>
</context-param>

em pom criar perfis maven

<profiles>
    <profile>
        <id>DEFAULT</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <spring.profile>prod</spring.profile>
        </properties>
    <profile>
    <profile>
        <id>DEMO</id>
        <properties>
            <spring.profile>demo</spring.profile>
        </properties>
    <profile>
</profiles>

Agora você pode usar

mvn jetty:run -P DEMO

ou simplesmente -P DEMOcom qualquer comando maven

Hurda
fonte
1
Não tenho certeza, mas acho que não vai funcionar. IMHO jetty: run não irá executar a fase em que os recursos são filtrados.
Michał Margiel
de caurse, você precisa executar mvn clean compile jetty: execute -P DEMO, mas com código não compilado ele executa automaticamente
Hurda
10
Eu entendo que um dos principais objetivos do Spring 3.1 Profiles é gerar um único arquivo WAR pronto para ser implementado em todos os ambientes. Usar perfis Maven é um retrocesso ao estado anterior: onde o empacotamento de um arquivo WAR era necessário para cada ambiente ...
edrabc
@edrabc ele estava pedindo mvn jetty: run - não há arquivo WAR.
Hurda
Concordo @Hurda. Mas ele também estava pedindo para executar o comando em vários ambientes: ter uma combinação de perfis Maven e perfis Spring pode ser um pouco enganador ...
edrabc