Usando la variable env en la aplicación Spring Boot.properties

Estamos trabajando en una aplicación web Spring Boot y la base de datos que estamos utilizando es MySql ;

  • la configuración que tenemos es que primero la probamos localmente (significa que tenemos que instalar MySql en nuestra PC);

  • luego presionamos a Bitbucket ;

  • Jenkins detecta automáticamente el nuevo impulso en Bitbucket y realiza una comstackción sobre él (para que la comstackción de Jenkins mvn pase, también necesitamos instalar MySql en las máquinas virtuales que ejecutan Jenkins).

  • si Jenkins construye pases, enviamos el código a nuestra aplicación en OpenShift (usando el complemento de implementación Openshift en Jenkins).

El problema que tenemos como ya lo has descubierto es que:

  • en application.properties no podemos codificar la información de MySql. Dado que nuestro proyecto se ejecutará en 3 lugares diferentes ( local , Jenkins y OpenShift ) necesitamos hacer dynamic el campo del origen de datos en application.properties (sabemos que hay diferentes formas de hacerlo, pero estamos trabajando en esta solución por el momento) .

     spring.datasource.url = spring.datasource.username = spring.datasource.password = 

La solución que surgió es que creamos una variable de entorno del sistema localmente y en Jenkins vm (nombrándolos de la misma manera que OpenShift los nombra) y les asignamos los valores correctos respetuosamente:

 export OPENSHIFT_MYSQL_DB_HOST="jdbc:mysql://localhost" export OPENSHIFT_MYSQL_DB_PORT="3306" export OPENSHIFT_MYSQL_DB_USERNAME="root" export OPENSHIFT_MYSQL_DB_PASSWORD="123asd" 

Hemos hecho esto y funciona. También hemos verificado con Map env = System.getenv(); que las variables de entorno se pueden convertir en variables java como tales:

 String password = env.get("OPENSHIFT_MYSQL_DB_PASSWORD"); String userName = env.get("OPENSHIFT_MYSQL_DB_USERNAME"); String sqlURL = env.get("OPENSHIFT_MYSQL_DB_HOST"); String sqlPort = env.get("OPENSHIFT_MYSQL_DB_PORT"); 

Ahora, lo único que queda es que necesitamos utilizar estas variables de Java en nuestra application.properties y eso es con lo que estamos teniendo problemas.

¿En qué carpeta y cómo necesitamos asignar las variables de password , userName , sqlURL y sqlPort para application.properties para poder verlas y cómo las incluimos en application.properties ?

Hemos intentado muchas cosas, una de ellas es:

 spring.datasource.url = ${sqlURL}:${sqlPort}/"nameofDB" spring.datasource.username = ${userName} spring.datasource.password = ${password} 

Sin suerte hasta ahora. Probablemente no estemos poniendo estas variables env en la clase / carpeta correcta y las usemos correctamente en applicatin.properties .

¡¡Tu ayuda es altamente apreciada!!

¡Gracias!

No necesita usar variables de Java. Para incluir variables de env del sistema, que haya especificado en su pregunta, directamente en el archivo application.properties puede usar la siguiente syntax:

 spring.datasource.url = ${OPENSHIFT_MYSQL_DB_HOST}:${OPENSHIFT_MYSQL_DB_PORT}/"nameofDB" spring.datasource.username = ${OPENSHIFT_MYSQL_DB_USERNAME} spring.datasource.password = ${OPENSHIFT_MYSQL_DB_PORT} 

Pero la forma sugerida por @Stefan Isele es más preferible, porque en este caso debes declarar solo un envlayable: spring.profiles.active . Y Spring leerá automáticamente el archivo de propiedades correspondiente mediante la plantilla application-{profile-name}.properties .

La forma más fácil de tener diferentes configuraciones para diferentes entornos es usar perfiles de resorte. Ver configuración externalizada .

Esto le da mucha flexibilidad, lo estoy usando en mis proyectos y es extremadamente útil. En tu caso, tendrías 3 perfiles ‘local’, ‘jenkins’ y ‘openshift’

A continuación, tiene 3 archivos de propiedades específicas de perfil application-local.properties application-jenkins.properties application-openshift.properties

Allí puede establecer las propiedades para el entorno relacionado. Cuando ejecuta la aplicación, debe especificar el perfil para activarlo como -Dspring.profiles.active=jenkins

Editar

De acuerdo con el documento de spring, solo tiene que configurar la variable de entorno del sistema operativo SPRING_PROFILES_ACTIVE para activar los perfiles y no pasarlos como parámetro.

¿hay alguna manera de pasar la opción de perfil activo para la aplicación web en tiempo de ejecución?

No. Spring determina los perfiles activos como uno de los primeros pasos al crear el contexto de la aplicación. Los perfiles activos se usan para decidir qué archivos de propiedad se leen y qué beans se crean instancias. Una vez que se inicia la aplicación, esto no se puede cambiar.

Esto es en respuesta a una serie de comentarios ya que mi reputación no es lo suficientemente alta como para comentar directamente.

Puede especificar el perfil en tiempo de ejecución siempre que el contexto de la aplicación aún no se haya cargado.

 // Previous answers incorrectly used "spring.active.profiles" instead of // "spring.profiles.active" (as noted in the comments). // Use AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME to avoid this mistake. System.setProperty(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME, environment); ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/META-INF/spring/applicationContext.xml"); 

Aquí hay un código de fragmento a través de una cadena de archivos de propiedades de entornos que se están cargando para diferentes entornos.

Archivo de propiedades bajo los recursos de su aplicación ( src / main / resources ): –

  1. application.properties 2. application-dev.properties 3. application-uat.properties 4. application-prod.properties 

Idealmente, application.properties contiene todas las propiedades comunes que son accesibles para todos los entornos y las propiedades relacionadas con el entorno solo funcionan en el entorno específico. por lo tanto, el orden de carga de estos archivos de propiedades será de esa manera:

  application.properties -> application.{spring.profiles.active}.properties. 

Fragmento de código aquí: –

  import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; public class PropertiesUtils { public static final String SPRING_PROFILES_ACTIVE = "spring.profiles.active"; public static void initProperties() { String activeProfile = System.getProperty(SPRING_PROFILES_ACTIVE); if (activeProfile == null) { activeProfile = "dev"; } PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer(); Resource[] resources = new ClassPathResource[] {new ClassPathResource("application.properties"), new ClassPathResource("application-" + activeProfile + ".properties")}; propertySourcesPlaceholderConfigurer.setLocations(resources); } } 

Tal vez escribo esto demasiado tarde, pero he tenido el problema similar cuando he intentado anular los métodos para leer las propiedades.

Mi problema ha sido: 1) Leer propiedad de env si esta propiedad se ha configurado en env 2) Leer propiedad de la propiedad del sistema si esta propiedad se ha configurado en la propiedad del sistema 3) Y por último, leer desde las propiedades de la aplicación.

Entonces, para resolver este problema, voy a mi clase de configuración de beans

 @Validated @Configuration @ConfigurationProperties(prefix = ApplicationConfiguration.PREFIX) @PropertySource(value = "${application.properties.path}", factory = PropertySourceFactoryCustom.class) @Data // lombok public class ApplicationConfiguration { static final String PREFIX = "application"; @NotBlank private String keysPath; @NotBlank private String publicKeyName; @NotNull private Long tokenTimeout; private Boolean devMode; public void setKeysPath(String keysPath) { this.keysPath = StringUtils.cleanPath(keysPath); } } 

Y sobrescribir fábrica en @PropertySource. Y luego creé mi propia implementación para leer propiedades.

  public class PropertySourceFactoryCustom implements PropertySourceFactory { @Override public PropertySource createPropertySource(String name, EncodedResource resource) throws IOException { return name != null ? new PropertySourceCustom(name, resource) : new PropertySourceCustom(resource); } } 

Y creó PropertySourceCustom

 public class PropertySourceCustom extends ResourcePropertySource { public LifeSourcePropertySource(String name, EncodedResource resource) throws IOException { super(name, resource); } public LifeSourcePropertySource(EncodedResource resource) throws IOException { super(resource); } public LifeSourcePropertySource(String name, Resource resource) throws IOException { super(name, resource); } public LifeSourcePropertySource(Resource resource) throws IOException { super(resource); } public LifeSourcePropertySource(String name, String location, ClassLoader classLoader) throws IOException { super(name, location, classLoader); } public LifeSourcePropertySource(String location, ClassLoader classLoader) throws IOException { super(location, classLoader); } public LifeSourcePropertySource(String name, String location) throws IOException { super(name, location); } public LifeSourcePropertySource(String location) throws IOException { super(location); } @Override public Object getProperty(String name) { if (StringUtils.isNotBlank(System.getenv(name))) return System.getenv(name); if (StringUtils.isNotBlank(System.getProperty(name))) return System.getProperty(name); return super.getProperty(name); } } 

Entonces, esto me ha ayudado.

Utilizando Spring context 5.0 he logrado cargar correctamente el archivo de propiedades correcto basado en el entorno del sistema a través de la siguiente anotación

 @PropertySources({ @PropertySource("classpath:application.properties"), @PropertySource("classpath:application-${MYENV:test}.properties")}) 

Aquí el valor de MYENV se lee del entorno del sistema y si el entorno del sistema no está presente, se cargará el archivo de propiedades del entorno de prueba predeterminado, si proporciono un valor MYENV incorrecto, no podrá iniciar la aplicación.

Nota: para cada perfil, desea mantener: necesitará crear un archivo application- [profile] .property y aunque utilicé Spring context 5.0 y no Spring boot , creo que esto también funcionará en Spring 4.1