configuration unification Java Spring - java

My application outlines are growing. I am looking for some solution to store configurations for each circuit.
I think that such a configuration format would be nice :
someHost:
test: testUrl
local: localUrl
dev: devUrl
qa: qaUrl
stage: stageUrl
prod: prodUrl
So far, I don’t have an understanding of how to properly configure my application so that it works correctly with the necessary configurations depending on the profile. Do you have any solution?
Stack: Java, Spring Boot 2, Kubernetes

To keep format you propose you will need to create another variable where you will configure prefix.
hostPrefix: dev
someHost:
test: testUrl
local: localUrl
dev: devUrl
qa: qaUrl
stage: stageUrl
prod: prodUrl
Then inject it with #Value in required field with inner placeholders:
#Value("${someHost.${hostPrefix}}")
private String url;
Thats it. In current solution it will be resolved to ${someHost.dev}, which would be resolved to devUrl. You can also use spring profile for that:
#Value("${someHost.${spring.profiles}}")
private String url;

You can use Spring's profiles for that.
Define a profile per environment, and then it can have it's own set of properties and beans

Seems like you already have configuration in yml format. Then you can use spring profiles like this:
spring:
profiles:
active: dev
someHost:
url: devUrl
---
spring:
profiles: test
someHost:
url: testUrl
---
spring:
profiles: qa
someHost:
url: qaUrl
And then you create #Configuration:
#Configuration
#ConfigurationProperties("someHost")
public class SomeHostConfig {
private String url;
}
Or you can use any managed bean field and inject it with #Value:
#Value("${someHost.url}")
private String someHostUrl;
Then you run your application with profile. For example, in maven it would be:
mvn spring-boot:run -Dspring.profiles.active=dev

Related

How to autoselect springprofile when running tests

I am looking for a solution to automatically add the environment variable SPRING_PROFILES_ACTIVE="test" when running unit-tests. The solution should fulfill the following criteria :
Ideally it should be configured via maven pom.xml
If 1 is not possible configuration should be done for IntelliJ via configuration file in the project not via UI setting
The particular environment variable should only be set when running unit tests not when generally launching the app.
Any idea on how to approach this goal is appreciated.
Best
Andy
The SPRING_PROFILES_ACTIVE is a property value that should be set in a file like application-test.properties or application-test.yml
In a yml file it would look like,
spring:
profiles:
active: test
Additionally, there are specific annotations to help identify certain classes/methods as test specific such as #Profile("test") or #ActiveProfiles("test").

Quarkus Consul Config: how to inject application.yaml file from Consul Agent?

I am using Quarkus inside a microservice Java application.
I recently started to migrate from Spring Boot to Quarkus itself.
I am having some trouble while migrating "Spring Cloud Consul" to "Quarkus Consul Config". In order to be more specific, I am getting the following error:
java.lang.RuntimeException: Key 'my/consul/path/application.yaml' not found in Consul
at io.quarkus.consul.config.runtime.ConsulConfigSourceProvider$1.accept(ConsulConfigSourceProvider.java:66)
at io.quarkus.consul.config.runtime.ConsulConfigSourceProvider$1.accept(ConsulConfigSourceProvider.java:56)
at io.smallrye.context.impl.wrappers.SlowContextualConsumer.accept(SlowContextualConsumer.java:21)
at io.smallrye.mutiny.operators.uni.UniOnItemConsume$UniOnItemComsumeProcessor.invokeEventHandler(UniOnItemConsume.java:77)
at io.smallrye.mutiny.operators.uni.UniOnItemConsume$UniOnItemComsumeProcessor.onItem(UniOnItemConsume.java:42)
at io.smallrye.mutiny.operators.uni.UniOnItemTransform$UniOnItemTransformProcessor.onItem(UniOnItemTransform.java:43)
at io.smallrye.mutiny.vertx.AsyncResultUni.lambda$subscribe$1(AsyncResultUni.java:35)
(...)
Inside my Consul instance, the key my/consul/path/application.yaml corresponds to an application.yaml external file that I would like to import from there during the startup phase.
Below you can find my consul config (application.yaml):
quarkus:
application:
name: myapplication
consul-config:
enabled: true
properties-value-keys: my/consul/path/application.yaml
agent:
host-port: http://localhost:9500
prefix: myappprefix
If I try to switch from properties-value-keys to properties-raw-value-keys, I see that my property is not being injected inside my application context:
#ConfigProperty(name = "consultest")
String test;
java.util.NoSuchElementException: SRCFG00014: The config property consultest is required but it could not be found in any config source
Below you can find the application.yaml content (located on Consul):
consultest: testtest
The intent, here, is to delegate application.yaml properties to Consul, divided by environment (dev, test, prod).
I would like to threat my local application.yaml file (located in src/main/resources) as a bootstrap.yaml file, similarly to Spring Boot approach.
How could this be done with Quarkus? Thank you a lot for your support.

Automatization Spring Cloud Profile

Actually have a little problem.
I want switch the url of my bootstrap.yml
It looks as follows:
spring:
application:
name: <project-name>
profiles:
active: dev
cloud:
config:
uri: http://<git-repository>:8080
fail-fast: false
This works, but i want have an propertie or anything what can switch if are in local or another enviroment.
I try to see this documentation but dont see any work for me.
I don't think Spring Cloud is any different from any Spring application, so you could use the Spring profiles.
Something similar is suggested on this answer: https://stackoverflow.com/a/22759706/6908551.
You could define a separate .yml file just for your cloud config uri, like cloud-config-dev.yml, cloud-config-prod.yml. Then, for a Java config, you could have something like:
#Configuration
public class MyApplicationConfiguration {
#Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
String activeProfile = System.getProperty("spring.profiles.active", "production");
String ymlFilename = "cloud-config-" + activeProfile + ".yml";
PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
configurer.setLocation(new ClassPathResource(ymlFilename));
return configurer;
}
}
I would define a bootstrap.yml file by environment.
Define a default bootstrap.yml in src/main/resources and define a specific bootstrap.yml file for each environment.
Then there are multiple ways.
Not exhaustive :
1) For each environment where the configuration file differs, run your spring boot jar by specifying the system property spring.cloud.bootstrap.location with the expected value such as :
java -jar ... -Dspring.cloud.bootstrap.location=bootstrap-dev.yml ....
That overrides the current location of that file.
2) Take advantage of Spring Boot profile feature : bootstrap.yml is compatible with. For example if the dev profile is enabled, the bootstrap-dev.properties in the classpath will be used.
I tend to use the first way because that is more explicit for non Spring Boot users.
Source : 1.3 Changing the Location of Bootstrap Properties

Spring boot profiles with external properties

I would like to setup 3 profiles in spring boot: production,development,test with using an external config file.
Application class:
#SpringBootApplication
public class Application {
public static void main(String[] args){
SpringApplication.run( Application.class, args );
}
}
AppConfig class:
#Configuration
#PropertySources({
#PropertySource("config/application.yml"),
#PropertySource(value = "file:${external.config}")
})
#ConfigurationProperties
public class AppConfig {
}
config/application.yml:
---
spring.profiles: production
endpoints.enabled: false
---
spring.profiles: development,test
endpoints.enabled: true
info.version: #project.version#
info.test: Test dev or test
info.profile: ${spring.profiles.active}
---
external.config: ${user.home}/.myapp/application.properties
.myapp/application.properties:
spring.profiles.active=production
info.version=5
The output of spring-boot-actuator /info
{
version: "5",
test: "Test dev or test",
profile: "production"
}
Expected output:
404 because of the endpoints.enabled: false
The spring-boot-actuator /env
spring.profiles.active: "production"
You should probably prefix the application.yml file with classpath:
In any case, why not just use the spring profile to drive configuration directly in java configuration? IMO, this would be cleaner and would make your properties more type-safe & re-factor friendly and not prone to spelling mistakes.
UPDATE:
According to the docs, you can't load yml files with the #PropertySource annotation:
http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-yaml-shortcomings
So if you need to use files, you'll need to use plain properties files. You could use property-specific application properties files shown here.
In addition to application.properties files, profile-specific
properties can also be defined using the naming convention
application-{profile}.properties.

Spring Datasources based on Environment

I am trying to configure my Spring Boot application to use specific datasources when certain environmental variables exist. For example, if the MY_PROD_DATASOURCE environmental variable exists, I would like to use my production datasource; otherwise, I would like to use my local datasource (of the same type).
I have found something in the Spring reference that explains how a single datasource could be declared in my application.properties. Specifically, a MySQL datasource could look like:
spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
spring.datasource.driverClassName=com.mysql.jdbc.Driver
However, I do not see how I could change the datasource properties conditionally in this file. Is there another way to do it?
In Spring Boot you can:
Externalize application.properties from your jar and provide file per environment by adding path as a startup parameter:
java -jar your-app.jar --spring.config.location=/path/to/app.properties
Use Spring profiles. Create application-${profile}.properties for each profile, in each one different datasource properties
Use Spring profiles and instead of application.properties, put your properties to application.yaml where you can put properties for all environments using convention as below:
spring:
profiles: development
server:
port: 9001
---
spring:
profiles: production
server:
port: 0
Use environment variables and set SPRING_DATASOURCE_URL, SPRING_DATASOURCE_USERNAME, SPRING_DATASOURCE_PASSWORD, and (optionally) SPRING_DATASOURCE_DRIVER_CLASS_NAME.
Learn more in the Spring Boot reference section on How to change configuration depending on the environment and External Configuration.

Categories

Resources