Perfil predeterminado en Spring 3.1

100

En mi aplicación tengo frijoles anotados con @Profile("prod")y @Profile("demo"). El primero, como puede adivinar :), se usa en beans que se conectan a la base de datos de producción y el segundo anota beans que usan alguna base de datos falsa ( HashMapo lo que sea), para acelerar el desarrollo.

Lo que me gustaría tener es el perfil predeterminado ( "prod") que se usará siempre si no se reemplaza por " algo más ".

Perfecto sería tener en mi web.xml:

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

y luego anular esto con -Dspring.profiles.active="demo"para que pueda hacer:

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

Pero, lamentablemente, esto no está funcionando. ¿Alguna idea de cómo podría lograr eso? Establecer -Dspring.profiles.active="prod"en todos mis entornos no es una opción.

Michał Margiel
fuente

Respuestas:

67

Mi experiencia es que usando

@Profile("default")

el bean solo se agregará al contexto si no se identifica ningún otro perfil. Si pasa en un perfil diferente, por ejemplo -Dspring.profiles.active="demo", este perfil se ignora.

Paul Philion
fuente
4
La respuesta aceptada depende de web.xml (y está bien), pero esta respuesta funciona tanto si tiene web.xml como si no, por lo que es más útil para todos.
Jay
1
esta solución es mucho más limpia
cahen
¿Es esta una característica oficial o algún efecto secundario? ¿Le gustaría enlazar a la documentación de Spring donde se describe esta característica?
rustyx
111

Defina su entorno de producción como perfil predeterminado en su web.xml

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

y si desea utilizar un perfil diferente, páselo como propiedad del sistema

mvn -Dspring.profiles.active="demo" jetty:run
Andih
fuente
3
No, intentó definir el perfil activo en web.xml y como propiedad del sistema. En mi solución, configuro un perfil predeterminado en web.xml y sobrescribo / defino el perfil activo a través de la propiedad del sistema. Si no hay un perfil activo explícito , se utilizará el predeterminado.
andih
1
¡Gracias! ¡esto es exactamente lo que quería! No pude encontrarlo en ninguna parte: /
Michał Margiel
Un problema con este enfoque: si se establece spring.profiles.default=proden application.properties, entonces application-prod.propertiesno va a ser cargado. Esto es contrario a la intuición.
gamliela
@gamliela El enfoque no establece el perfil predeterminado en un application.propertiesarchivo. Para saber que se application-prod.propertiesdebe utilizar tendrás que conocer el perfil. Eso es lo que hace este enfoque. Define perfiles fuera del contexto de primavera, ya sea web.xml(predeterminado) o mediante la variable de entorno (sobrescribe el predeterminado).
andih
@andih Sí, lo sé, pero solo digo que no es intuitivo y, por lo tanto, problemático. Desde que application-default.propertiesse cargó, también espero que application-newdefault.propertiestambién se cargue. No es un problema con su solución, es un problema con Spring ...
gamliela
6

Tengo el mismo problema, pero uso WebApplicationInitializer para configurar ServletContext mediante programación (Servlet 3.0+). Entonces hago lo siguiente:

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
fuente
5

También puede considerar eliminar el perfil PROD y usar @Profile ("! Demo")

blacelle
fuente
2
Supongo que esto no funcionaría en caso de que tengas más de dos perfiles, ¿verdad?
Chop
3

Acerca de la configuración del perfil de producción predeterminado ya publicado @andih

La forma más fácil de establecer el perfil predeterminado para el complemento maven jetty es incluir el siguiente elemento en la configuración de su complemento:

<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
fuente
3

Spring proporciona dos propiedades separadas al determinar qué perfiles están activos:

  • spring.profiles.active

y

  • spring.profiles.default

Si spring.profiles.activese establece, su valor determina qué perfiles están activos. Pero si spring.profiles.activeno está configurado, Spring buscaspring.profiles.default.

Si no se establece spring.profiles.activeni spring.profiles.default, entonces no hay perfiles activos, y solo se crean aquellos beans que no están definidos como en un perfil. Cualquier bean que no especifique un perfil pertenece al defaultperfil.

Touhidur Rahaman Khan
fuente
-1

Puede configurar su web.xml como recurso filtrado y hacer que maven complete este valor desde la configuración del perfil de maven, eso es lo que hacemos.

en pom filtra todos los recursos (puede hacerlo si no tiene una marca $ {} en ellos)

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

en web.xml poner

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

en pom crea perfiles 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>

Ahora puedes usar

mvn jetty:run -P DEMO

o simplemente -P DEMOcon cualquier comando experto

Hurda
fuente
1
No estoy seguro, pero creo que eso no funcionará. En mi humilde opinión, embarcadero: la ejecución no se ejecutará en la fase en la que se filtran los recursos.
Michał Margiel
de caurse, debe ejecutar mvn clean compile jetty: ejecute -P DEMO, pero con el código no compilado lo ejecuta automáticamente
Hurda
10
Entiendo que uno de los principales objetivos de Spring 3.1 Profiles es generar un solo archivo WAR listo para implementarse en todos los entornos. El uso de perfiles de Maven es un paso atrás al estado anterior: donde se necesitaba el empaquetado de un archivo WAR para cada entorno ...
edrabc
@edrabc estaba pidiendo mvn jetty: run - no hay archivo WAR.
Hurda
De acuerdo @Hurda. Pero también estaba pidiendo ejecutar el comando en múltiples entornos: tener una combinación de perfiles de Maven y perfiles de primavera podría ser un poco engañoso ...
edrabc