I have a spring boot application which reads properties from a remote config server via spring cloud, and it works fine with different configuration files defined in the remote repository, i'm running it with following command :
java -jar my-app.jar --spring.profiles.active=my-custom-profile
However, in some special cases i would want to be able to run the application while changing some of the remote properties (these changes are not fixed, so i can't create some custom profiles for them), so i've tried to override them directly via the command line this way :
java -jar my-app.jar --spring.profiles.active=my-custom-profile --my.first.property=value1 --my.second.property=value2
But it doesn't seem to be taken into consideration, because the application still takes the remote properties on startup.
Is there any proper way to achieve that ?
Remote properties defined by Spring Cloud Config take precedence over any other property sources. If you want to override those with local properties, you need to explicitly allow this as described in Overriding the Values of Remote Properties:
spring.cloud.config.allowOverride=true
spring.cloud.config.overrideNone=true
Related
I have a Spring Boot application for UI test automation using Cucumber and Selenium.
The application is expected to test multiple environments.
To begin with I have created json files with required properties like URLs, credentials etc. and load it(pass the file path as a property and use it) while triggering the test (mvn test -DconfigFile=config/env1_config.json).
I see that using profiles while running test is an option-Dspring.profiles.active=client1 but as i will configure multiple pipelines in Jenkins for testing multiple environments to use same project with different configuration files, it will clone the entire project and run tests in workspace corresponding to the pipeline. To avoid keeping multiple copies of the project, i am planning to use Rest API to trigger Selenium tests and have configuration files in Git.
Is it possible to create multiple application properties files with custom properties, place them in Git and use required property file in a Spring Boot application(inside a Rest API impl) based on a property or RequestParam using Spring Cloud Config or something?
you can use spring boot profiles and pass it as maven argument
just pass -Dspring.profiles.active=test1 as command line argument
you can read more here
You can do it by setting spring.profiles.active environment variable. Like if you are using property file for every environment by convention application-dev.properties, application-qa.properties. You can define you spring.profiles.active as dev and qa.
You can refer to the below link for more in site on same.
https://stackabuse.com/spring-boot-configuring-properties/
You can use Spring cloud server and client.
Make A project With Dependency Spring cloud server and make config file(appilcation.properties) there. For use that config file in other microservice
just add spring cloud cilent dependency in other projects and add this line in application.properties
spring.cloud.config.uri:[your spring cloud server project url]
refrence:-
spring cloud server:-
https://www.youtube.com/watch?v=gb1i4WyWNK4&list=PLqq-6Pq4lTTaoaVoQVfRJPqvNTCjcTvJB&index=11
spring cloud client:- https://www.youtube.com/watch?v=E2HkL766VHs&list=PLqq-6Pq4lTTaoaVoQVfRJPqvNTCjcTvJB&index=12
Sharing the approach I ended up with as it might help someone someday.
As i wanted to create a Rest API and use properties from different config files in API implementation, based on the api request,
I created a Spring Cloud Config Server application that connects to application properties repo in git and I consumed Rest APIs exposed by Spring Cloud Config Server (host:port/app/profile) in the service layer of my Rest API implementation.
I am trying to build a sample app on Spring boot and spring cloud.
I have written my database and hibernate configuration in config.properties property file which is located in my desktop and I want my spring boot to make use of this configuration.
My project have 3 modules
API
DataLayer
ServiceLayer
This is the code that I have mentioned in the application.property file of API
spring.profiles.active=native
spring.cloud.config.server.native.searchLocation=C:/Users/DEV/Desktop/configuration/config.properties
and the property file of DataLayer and ServiceLayer is empty
But when I run the API I am getting the following error
***************************
APPLICATION FAILED TO START
***************************
Description:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
Action:
Consider the following:
If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).
Process finished with exit code 1
Could any one help me with this error.
Thanks in advance.
This is can not be done from your API module. You added configuration server properties to your 'client' (from configuration point of view) application.
If you want to use Spring Cloud Config to configure your project you should have separate application that will manage your configuration. Let's call it config-server. (You should properly configure maven or gradle dependencies, see documentation) To configure usage of native profile in the config-server in application.properties you have to add properties that you mentioned in the question (example for native profile).
spring.profiles.active=native
spring.cloud.config.server.native.searchLocation=file:<path-to-the-directory-with-conf-files> or classpath:/<path-to-the-directory-with-conf-files>
Note: config-server can handle configuration for lot of services.
More can be found in the documentation Spring Cloud Config Server section.
Then in your API (or any other module) which is a spring boot app you should add spring-cloud-config-client dependency and add bootstrap.properties (or .yml) configuration file. There your should add properties that will describe communication with config-server. By default config-server listens on port 8888.
spring.application.name=<your app name>
spring.cloud.config.uri=http://localhost:8888 # this is also default value for this property
At start-up it will go by http to config-server and fetch your configuration properties based on service name (spring.application.name).
More can be found in Spring Cloud Config client section
Important: make sure your properly organize files in your configuration directory (which is used by native profile by config-server), find some samples. Property files naming are important. For start you can try to use your-application-name.properties
You have to have file: prefixed to the property file location.
Documentation from https://cloud.spring.io/spring-cloud-config/multi/multi__spring_cloud_config_server.html
There is also a “native” profile in the Config Server that does not use Git but loads the config files from the local classpath or file system (any static URL you want to point to with spring.cloud.config.server.native.searchLocations). To use the native profile, launch the Config Server with spring.profiles.active=native.
[Note]
Remember to use the file: prefix for file resources (the default without a prefix is usually the classpath). As with any Spring Boot
configuration, you can embed ${}-style environment placeholders, but
remember that absolute paths in Windows require an extra / (for
example, file:///${user.home}/config-repo).
[Warning]
The default value of the searchLocations is identical to a local Spring Boot application (that is, [classpath:/, classpath:/config,
file:./, file:./config]). This does not expose the
application.properties from the server to all clients, because any
property sources present in the server are removed before being sent
to the client.
[Tip] A filesystem backend is great for getting started quickly and for testing. To use it in production, you need to be sure that the
file system is reliable and shared across all instances of the Config
Server.
I'm new to java and k8, and I have some doubts about how to handle application configurations for my java apps. I've got one spring boot app and the other three use wildfly.
So, they all got hardcoded application configurations, and when starting them the just use something like:
java -Dswarm.project.stage=development -jar foobar/target/foobar-swarm.jar
except for the spring boot which has an application.properties file that consists of application configuration data.
So basically the three java apps have backed in two files (which I know is a no no):
- project-stages.yml
- standalone.xml
And when the developer wants to deploy to production he uses:
java -Dswarm.project.stage=production -jar foobar/target/foobar-swarm.jar
And, now we come to kubernetes which has three ways of dealing with application configuration data:
1.) Env variables
2.) Config maps
3.) Secrets
I was thinking of using configmaps instead of env variables because they have more benefits.
So, the developer gave me the possibility of overwriting those hardcoded variables with an external file : Dsystem.properties.file=/var/foobar/environment.properties
But I'm still overwriting an hardcoded files with an external file, and I'm not happy with that solution!
So, I'm basically looking on advise can those hardcoded files be supplied externally and populated with configmaps in k8 - what would be the best practice of handling the config files in the world of k8?
Tnx,
Tom
There are several questions in the post, but I can address only the one related to spring-boot.
The simplest and the most convenient way of specifying configurations to spring boot app is via its built in profiling feature. As you already mentioned you have application.properties. You can create similar files according to your usage cases: application-production.properties, application-staging.properties, application-k8s.properties, etc.
Kubernetes deployment doesn't change this in any way.
You can control which configuration to pick by setting SPRING_PROFILES_ACTIVE env variable from the kubernetes.
You might have something like this:
docker run -e SPRING_PROFILES_ACTIVE=k8s -d -p 0.0.0.0:8080:8080 \
--name=yourapp your_image_name bash -c "java -jar yourapp.jar"
It will pick configuration from application-k8s.properties.
Configuration files support environment variables as well.
You can have placeholders like ${YOUR_DB} in your properties files and Spring will automatically pick up env variable with name YOUR_DB. It is convenient to use this feature let's say when your app pod must have its own db pod.
If I got your question right you are asking how to configure a Spring Boot application via a k8s ConfigMap. Yes, you can do that.
Create a Docker image with WORKDIR work_dir in which you start the Spring Boot application eg via java -jar /work_dir/app.jar
Create a ConfigMap
Run a container of the above mentioned image within k8s
Mount the ConfigMap for the Spring Boot application.properties into the Container as /work_dir/config/application.properties
On changes in the ConfigMap the file within the container gets updated. You have to restart the Spring Boot Application to set your changes active.
I have 2 app engine projects that I have created in the Developers Console. One project is my production application and the other I plan to use for staging. I am developing my application using Cloud Endpoints.
I would like to have the applicationId, WEB_CLIENT_ID, ANDROID_CLIENT_ID, etc.. all be configurable such that in the terminal I can specify a 'stage' and 'prod' flag to use different configurations and push to to each respective project.
Something like:
mvn appengine:update -env=production
and
mvn appengine:update -env=stage
To do this I figure I'll need to parameterize <application> inside appengine-web.xml and also have the Constants.java file read from a config file.
How can I have different configurations for each environment?
A different approach that you could use would be to put all your CLIENT_IDs into the #API, #APIMethod annotations. This would allow the same code to be accessed from different clients via the authentication mechanisms.
I'm exploring the possibilities of Spring Boot right now, and I'm at a slight impasse. I want to be able to run two Spring Boot applications at once, both on the same server, but at different paths (one deploys on /, the other deploys at /another-path).
Because this is an embedded Tomcat instance running within Spring Boot, there's no configuration files available for me to change.
Is there a standard way to do this? Is it possible?
Spring Boot comes with some pre-built property support. If you create an application.properties file, you can include:
server.port=<another port>
server.address=<another IP address>
server.sessionTimeout=<another timeout setting>
server.contextPath=/your-other-path
This can be in application.properties adjacent to your runnable JAR, embedded inside the JAR file, or simply applied as a -Dserver.contextPath=/your-alt-path with the java command. These are cascading, meaning you can embed one set of defaults inside the JAR, override with a local application.properties file, and then finally override application.properties with the -D options.
As it uses an embedded tomcat you should be able to add a /META-INF/context.xml to each application which specifies the path (at least this should work for a normal tomcat).
That works for our normal embedded tomcat stuff, so I would expect it to work for Spring Boot as well.