Using spring cloud config properties can be defined for different services and different environments, e.g. using a native profile we could have the following tree in the server:
resources
config
service-a
service-a-local.properties
service-a-test.properties
service-b
service-b-local.properties
service-b-test.properties
and have client services bootstrapped with configuration from the server, using one of the available options, such as #Value annotations etc. This however will only see the properties slice from the config server for the calling service (or whatever spring.application.name is used).
How can service-a access properties of service-b (or any other service) dynamically? The default property source locator uses a "/{name}/{profile}" path for fetch requests. I suppose one could restructure the entire configuration and put all services' properties in one file per environment, using some appropriate naming convention for the properties (e.g. using the service name as the prefix), and then explicitly prefix the calling-site property references with that prefix, but is there another/more elegant option, before using a discovery/mesh alternative?
Related
I know Springboot applications can use application.properties or application.yaml files to retrieve variables like database connectivity setting, username, password etc.
However, and because of sensitive information, our development team has these only for test environment but not for production environments. These are not available to developers.
These are provided by security team and set up directly on server in server configuration files on Liberty server (these are server.xml files located in the server installation directory).
Developers have their own instance of Liberty server running where they have their own versions of server.xml files. If we could make Springboot read these files, then we could make it mimic production server environments and make transition easier instead of reading local application.properties files.
Is this possible?
If not, what would be a workaround?
First, usually developer/application doesn't need direct access to props like database connectivity setting, username, password because all that is configured in server in data source configuration, so application just needs JNDI name of the datasource to connect to it.
Second, if you use technology that cannot be configured in server, developers and security team should utilize environment variables for such props.
Liberty can read env variables, or also define them via server.env and then utilize in server.xml config for example:
<dataSource jndiName="jdbc/myDS">
...
<properties.db2.jcc serverName="${JDBC_HOST}" portNumber="${JDBC_PORT}" databaseName="${JDBC_DB}" user="${JDBC_USER}" password="${JDBC_PASSWORD}"/>
</dataSource>
Similarly you can use env vars in your springboot either configuring it in application.properties like this:
jdbc.user=${JDBC_USER}
or directly in code:
#Value("${JDBC_USER}")
private String jdbcUser;
Utilizing env variables has additional benefit that you can override them later if deploying in containers for example.
I will talk about alternative solution.
Firstly I do not understand how developer will access production server properties.
And for securing sensitive properties you could use property encryptor tool. Sensitive properties will be in encrypted format in application.properties and during server startup it will decrypt encrypted properties and use accordingly.
Here is a such library for property encrytion library
My java microservice (developed in Spring boot) loads S3 bucket from an application properties file. S3 bucket names for 4 different AWS regions are different (bucker-east-1, bucker-west-2 etc) hence how do I load AWS region-specific properties from application properties? For example, for us-west-2 region, bucker-us-west-2 property should be loaded, etc. is there any existing support for this type of feature in SPring boot?
There's at least a couple of ways you could handle this.
Use environment variables: Using env variable in Spring Boot's application.properties
Feasibly you could structure the names to be something like bucket.name=<bucket-prefix>-${AWS_REGION}
Use Spring profiles. You can create separate properties files for each region.
For example, you'd have application-us_east_1.properties, application-us_east_2.properties. You then can add the appropriate spring profile upon deployment by passing in the JVM parameter, -Dspring.profiles.active=us_east_1 to activate us_east_1. Alternatively, you can use the SPRING_PROFILES_ACTIVE environment variable similarly.
I want to use a common application properties file for multiple microservices which will have some common configuration like DB Source config etc..I have use the config Server with Eureka server and zull Proxy.
Issue:
When using configServer we need to provide the spring.application.name = 'xyz'
which in turn find the xyz.properties for this microservice configuration.
The same way when we register the service with zuul proxy also need the same application name for configure the service path as zuul.routes.xyz.path = /iii/*.
Now I want that multiple service will share the same property file(xyz.properties) but need to register the zuul route as well so I have to provide the different name for each service. If I will provide the different name to each service they will not be able to locate the same property file.
I am new to spring boot micro services.
spring.config.client.name supports multiple names separated by commas to load the configuration properties.
In this case, store the common properties in common.yml and xyz properties in xyz.yml. Finally, mention spring.cloud.config.name: xyz,common
spring:
cloud:
config:
uri: http://localhost:8888
name: xyz,common
Output:
Fetching config from server at : http://localhost:8888
Located environment: name=xyz,common, profiles=[default], label=null, version=91edcf96c6a88707bf39014a16ad5d301d6b4575, state=null
Located property source: CompositePropertySource {name='configService', propertySources=[MapPropertySource {name='configClient'}, MapPropertySource {name='https://github.com/BarathArivazhagan/config-server-repository/common.yml'}, MapPropertySource {name='https://github.com/BarathArivazhagan/config-server-repository/xyz.yml'}]}
I would like to point out that the provided solution leverages the "spring.config.client.name" client side property semantics to achieve a config server behavior of serving properties files from multiple files other than application[-profile].* and {appname}[-profile].*
However, note that for a simple case and considering a root dir, the config server serves properties from files defined in this root dir or under a folder with the name of the application, that the property files under it correspond to, i.e. */{appname}/application[-profile].** or */{appname}/{appname}[-profile].**
The "spring.config.client.name" environment property instructs the config server which application names the requesting app matches with. This means that given a spring.config.client.name=a,b , the config server will assume serving properties defined for app (with name) a and b to the requesting app! This is not the exact same thing as I want my properties been served from file names a and b! Therefore we are abusing the property semantics for managing our config server serving from the file names we would like it to.
However, due to the actual semantics of spring.config.client.name the config server will serve everything applicable from
/a[-profile].*
/b[-profile].*
/a/{applicable names}
/b/{applicable names}
The caveat here is that we achieve what we want only for the root directory and, moreover, if we have a configserver that serves multiple springboot apps we loose the ability to have all our properties under our application's name-folder.
Even worse, if there exists another app (or -attention!- will exist in the future) with the same name as one of our desired property file names, the config server will start serving to our app ALL the configuration defined for that other app!!! This could end up in wrong and even harmful served configuration!
(I repeat it will serve everything applicable under /{other-app-name-that-i-happened-to-use-as-filename-and-defined-it-through-spring.config.client.name}/*!!!)
So beware when pirsuiting this approach!
I have issued a pull request for spring-cloud-config-server 1.4.x, that supports defining additional file names, through a spring.cloud.config.server.searchNames environment property, in the same sense one can do for a single springboot app, as defined in the Externalized Configuration.Application Property Files section of the documentation, using the spring.config.name enviroment property. I hope they review it soon
We are thinking of migrating our Spring system to use Spring Cloud Config.
The system is made up of multiple services and some share properties for common resources such as the DB datasource. For these we have a 'base' config file which contains the commonly used properties in one place. Each of the services read the common file first and then overload their properties file on top. This saves us repeating common properties.
I can't see how we do the same with spring cloud config, I can see options for different repositories but not overloading property files.
application.yml or application.properties is common to all applications.
Does anybody knows if it is possible to expose more than 1 property file per application in Spring Cloud config server?
For example I would like to have defined in my git repo properties for the same app, but in different files:
myapp-customer-services.yml
myapp-products-services.yml
and have all those properties defined inside the files, exposed under "myapp".
No that's not possible currently. I'm not sure it really makes much sense to be honest, since you can easily clearly delineate different sets of properties within a YAML file using separate documents.
Yes it is possible to expose more than 1 property file per application in Spring Cloud config server
You can access it in you client by using following properties
first specify profile which you want
example
myapp-customer.yml
myapp-products.yml
spring.profiles.active=customer,products
spring.cloud.config.name=myapp