Ejecutando diferentes recursos según el ambiente de ejecución

April 8, 2017    spring


Codigo fuente de este ejemplo

Introducción

Casi siempre necesitamos personalizar la configuración de nuestra aplicación según el entorno en el que se ejecuta, por ejemplo la url de la base de datos, el servidor de correos ó la url de los servicios web cambian si nuestra aplicación está corriendo en un ambiente de desarrollo, QA, producción, etc. Cambiar estas URL’s o recursos manualmente puede ocasionarnos graves problemas, ¿Les ha pasado que han subido a producción apuntando alguna URL de desarrollo?… Bueno, a mi si.

Primer ejemplo

Teniendo nuestra aplicación Spring Boot, vamos a crear una clase que imprima un simple texto dependiendo del ambiente de ejecución.

    @Component
    public class PrimerEjemplo {

        private Environment env;

        @Autowired
        public PrimerEjemplo(Environment env) {
            this.env = env;
        }

        public void imprimir(){
            System.out.printf("Enviando un correo electronico usando el servidor SMTP %s",
                    env.getProperty("url.smtp"));
        }
    }

Según la documentación de Spring,Environment es una interfaz que representa el entorno en el cuál está corriendo la aplicación actual y modela dos aspectos claves del entorno de la aplicación: profiles y properties.

Por lo anterior es que podemos usar el método getProperty para obtener el valor de la propiedad url.smtp definida en el archivo principal de configuración de spring boot.

application.properties

url.smtp="200.123.45.65"

Para ejecutar este primer ejemplo basta agregar a la clase principal de spring boot un CommandLineRunner.

@SpringBootApplication
public class DemoApplication {

    @Autowired
    PrimerEjemplo ejemplo;

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}

	@Bean
	public CommandLineRunner commandLineRunner(){
        return new CommandLineRunner() {
            @Override
            public void run(String... args) throws Exception {
                ejemplo.imprimir();
            }
        };
    }
}

Al ejecutarlo veremos en la consola lo siguiente:

Enviando un correo electronico usando el servidor SMTP 200.123.45.65

Agregando el archivo application-dev.properties

Hasta ahora solo hemos leído una propiedad del archivo application.properties usando la interfaz Environmentpero no hemos visto nada sobre los ambientes de ejecución.

Vamos a crear un archivo de propiedades adicional agregando la misma clave url.smtp pero con diferente valor.

application-dev.properties

url.smtp=10.60.34.123

Para que Spring pueda obtener el valor de una propiedad mediante la interfaz Environment se utiliza la convención de nombres application-{profile}.properties

En el archivo build.gradle agregamos lo siguiente,

bootRun {
    args = ["--spring.profiles.active=dev"]
}

Al ejecutar nuevamente la aplicación, ahora obtendremos el siguiente texto en la consola,

Enviando un correo electronico usando el servidor SMTP 10.60.34.123

¿Todas las propiedades que existen en application.properties debo tenerlas en application-dev.properties? La respuesta es no. En este ejemplo, spring buscará la propiedad url.smtp primero en el archivo application-dev.properties y de no encontrarla buscará en el archivo por default application.properties

Lo anterior es una excelente forma de sobre escribir propiedades y no tener propiedades duplicadas, en su lugar solo tendremos aquellas cuyo valor si dependa del ambiente de ejecución.

Conclusiones

Mientras desarrollamos alguna aplicación spring boot como por ejemplos servicios REST, podemos correr la aplicación con la tarea bootRun y agregar al archivo build.gradle la variable de entorno spring.profiles.active estableciendo el perfil dev.

Si tenemos un ambiente de QA o pre producción seguramente desplegaremos un archivo WAR. Podemos agregar la variable de entorno al momento de levantar el servidor. En JBoss EAP o Wildfly sería algo así

./standalone.sh -Dspring.profiles.active=qa

Por lo tanto también deberemos tener un archivo application-qa.properties

Finalmente cuando se trate de desplegar la aplicación en producción, podemos no establecer ningún valor para spring.profiles.activey de esta forma spring buscará todas las propiedades en el archivo por default application.properties


Codigo fuente de este ejemplo


blog comments powered by Disqus