How to specify an external application.yml in spring with profiles - spring

From the spring documentation http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-yaml i see that an external YAML file is possible.
I was able to use a PropertyPlaceholderConfig FileSystem resourse to load in yaml, but it did not honor the active profile.
I saw for application.properties you can use #PropertySource, but that does not work for YAML according to the docs.
So bottom line question: How do a specify an application.yml in a profile aware fashion in Spring4/spring boot.
Note: It works in src/main/resources/application.yml

In order to specify an external profile aware .yml file the SPRING_CONFIG_LOCATION and SPRING_PROFILES_ACTIVE system variables can be used.
JAVA_OPTS example
-Dspring.profiles.active=dev -Dspring.config.location=file:C:/application.yml
This will allow you to have provide multiple profiles inside of a YML file and let spring do the heavy lifting of evaluating the correct properties:
spring:
profiles: dev
someprop: devprop
---
spring:
profiles: test
someprop: testprop

Related

Should I use only native profile if I want to use local config files in spring boot?

I'm setting local development environment to test using spring boot ver 2.7.1, and I want to use local file hierarchy as config server.
So, I use spring.cloud.config.server.native.searchLocations: ~~~.
I want to boot this project using profile named something other except 'native' (application-native.yml). But it is failed to load the server.
My Question:
When I want to use local files as config files, is it only possible to use 'native' profile?
I tried :
spring:
profiles:
active: local
cloud:
config:
server:
native:
searchLocations:
~~~~
still failed.

Why docker-compose up command always falling back to default spring boot profile?

Why docker-compose up command always falling back to default spring boot profile though we have override it in application.properties file . like
SPRING_PROFILES_ACTIVE=schemaDevelopment
The format for setting the active profile in the application.properties file is wrong, example: spring.profiles.active=production
See https://docs.spring.io/spring-boot/docs/2.7.x/reference/html/howto.html#howto.properties-and-configuration.set-active-spring-profiles
The format SPRING_PROFILES_ACTIVE is used when you set the profile via an environmental variable

Externalize application configuration for Google Cloud Run

I was looking to externalize application configuration for containerized applications on Google Cloud Run. I know there are environment variables available for cloud run application and I want to have something as Config Server for Cloud Run.
Is there any out of the box support available on GCP?
When setting up your Cloud Run deployment, you can simply inject environment variables into your service:
Because Spring Boot comes with application.properties mechanism, you can easily override those values exactly from the environment variables. Do keep in mind, that the syntax is slightly different:
application.properties
spring.profiles.active=dev
environment variables
SPRING_PROFILES_ACTIVE=dev
Injected env variables will take precedence over the ones defined in your application.properties file.
There are two solutions to it :
If your docker file is "ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/****.jar"]" then use "-Dspring.profiles.active=dev" in the container arguments on the cloud run.
In case your docker file has "CMD ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/***.jar"]" You can do it by setting Environment Variable as SPRING_PROFILES_ACTIVE and value as dev in "Variables & Secrets" tab on cloud run Container Configuration

How to do Spring-boot configuration for many clients

I am wondering how to resolve problem: I have a spring-boot app on docker that connects to db and some other service.
Probably some clients will have db on other urls than the others.
I use spring.datasource.url property to connect to DB. Should I add it to args and use:
Properties properties = new Properties();
properties.put("spring.datasource.url", args[1]);
application.setDefaultProperties(properties);
And something like that will override it ? But every run will need adding DB url. Or use something else?
datasource could be read as a variable from the docker-compose file:
assume this is your docker-compose file:
version: '2'
services:
db:
image: customimage_mysql
restart: always
ports:
- "3306:3306"
application:
build: .
ports:
- "9111:9111"
depends_on:
- db
links:
- db
environment:
- database.url=jdbc:mysql://mysql-docker-container:3306/spring_app_db?
Now you have 2 options:
set different values for databse.url inside docker compose and build image for each app correspondingly
set different variables (databse1.url , databse2.url,databse3.url, ...) inside docker-compose file, and reference to them from
application.properties:
application.properties
spring.datasource.url=${database.url}
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.generate-ddl=true
spring.jpa.show-sql=true
server.port=9111
According to the information that you have provided here, the database link should be a configuration to your application. basically you need to have a configurations file
application.properties
And when you want to change the URL, just change it in the configuration file and build.
you can find the documentation here
And moreover if you are using devops environment like kubernetes, you would have to have a config-map and your deployments will get configurations from those config-maps which are like application.properties files.
If you've got lots of deployments each with their own database then that will take some management one way or another. But you don't want it to require lots of builds of your app - you want to externalise that configuration.
Sorting boot has features for externalising configuration (https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html). The simplest for your case would be to use environment variables that override properties by relaxed binding of names (https://github.com/spring-projects/spring-boot/wiki/Relaxed-Binding-2.0). If app is started with an environment variable named SPRING_DATASOURCE_URL then this value will override what you have in your properties for spring.datasource.url. Your properties file effectively sets a default value that you can override. This is out of the box behaviour for Spring Boot and applies to other properties too (inc all the db ones, though if you've got databases of different types then you'll want to include all the relevant driver jars in your build).
Since you're using docker you can set environment variables in the container at deploy/startup time using a -e parameter. So you can override at deploy time for each deployed instance.
You might well use further layers on top of docker like docker-compose or Kubernetes. Then you might get into setting the environment variables in deployment descriptor files that describe your deployment configuration. But that configuration management question is at a different layer/stage and is no longer part of the build step once you have your config externalised.

Spring Config Server properties ordering when directories

We are running Spring Cloud Config Server v1.3.1.
We have Bitbucket hosting Git. The Git environment has a configuration folder where we hold our files. There are a number of subdirectories under the configuration folder. eg
environment/configuration
application-dev.yml
my-service.yml
my-service-ci.yml
my-service.dev.yml
...
environment/configuration/datasources
application-ci.yml
application-dev.yml
...
In the Spring Config Server the application and config server are configured as below:
spring:
application:
name: "#project.name#"
cloud:
config:
server:
git:
uri: https://xxxxx/scm/dep/environment
basedir: ${baseDirectory}/work
searchPaths: configuration, configuration/*
When loading the my-service Spring Boot app with dev profile I would expect the app specific config files (my-service) to load first. ie
environment/configuration/my-service-dev.yml
environment/configuration/my-service.yml
environment/configuration/configuration/application-dev.yml
environment/configuration/application-dev.yml
In reality it loads the folders in reverse order so configuration/* comes first with its subdirectories loaded in alphabetical order. Next comes the files
sitting directly under configuration. This gives below order
environment/configuration/application-dev.yml
environment/configuration/configuration/application-dev.yml
environment/configuration/my-service-dev.yml
environment/configuration/my-service.yml
Spring Boot loads these as a Map containing a list of PropertySources. It iterates from the start and returns the first match. In this case a property in application-dev.yml
would trump the same property in my-service-dev.yml.
Is this intended behaviour or is there a bug when directories are involved?

Resources