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
Related
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.
When running
./mvnw spring-boot:run
current spring boot application can open in the browser with current URL
http://localhost:8080/
but not
http://localhost:8080/AppName
So even in Swagger the APIs has to retrieve like this
http://localhost:8080/api/swagger.json
instead of this
http://localhost:8080/AppName/api/swagger.json
So how to add the AppName in the context? Easy in the old days where web.xml is xml based, in java based config I have add
spring.application.name=AppName
but still don't resolve the issue.
So how to add the AppName in the context?
Spring Boot, by default, serves content on the root context path (“/”), But we can change it in different ways.
1) Using application.properties / yml
For Boot 1.x, the property is server.context-path=/AppName
For Boot 2.x, the property is server.servlet.context-path=/AppName
2) Using Java system property
public static void main(String[] args) {
System.setProperty("server.servlet.context-path", "/AppName");
SpringApplication.run(Application.class, args);
}
3) Using OS Environment Variable
On Linux:- $ export SERVER_SERVLET_CONTEXT_PATH=/AppName
On Windows:- set SERVER_SERVLET_CONTEXT_PATH=/AppName
4) Using Command Line Arguments
$ java -jar app.jar --server.servlet.context-path=/AppName
5) Using Java Config
With Spring Boot 2, we can use WebServerFactoryCustomizer:
#Bean
public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>
webServerFactoryCustomizer() {
return factory -> factory.setContextPath("/AppName");
}
With Spring Boot 1, we can create an instance of EmbeddedServletContainerCustomizer:
#Bean
public EmbeddedServletContainerCustomizer
embeddedServletContainerCustomizer() {
return container -> container.setContextPath("/AppName");
}
Note:- Priority order in descending order, which Spring Boot uses to select the effective configuration:
Java Config
Command Line Arguments
Java System Properties
OS Environment Variables
application.properties in Current Directory
application.properties in the classpath (src/main/resources or the packaged jar file)
Set the context path
Spring Boot 1.x: server.contextPath=/AppName
Spring Boot 2.x: server.servlet.contextPath=/AppName
You should use
server.servlet.context-path for Spring Boot 2.x
server.context-path for Spring 1.x
in your application.properties file.
Add the following line in your application.properties (works with Spring Boot 1.x):
server.contextPath=/AppName
if your version is 2.x, the use the following:
server.servlet.contextPath=/AppName
I have Spring Boot Application and i have 3 property files: applications.properties, applications-dev.properties, applicaton-prod.properties. In applications.properties i specify that spring.profiles.active=prod. But I want to allow startup of application without prod profile(applicaton-prod.properties). It means that spring must startup application in dev profile(applications-dev.properties) automatically. How can i implement this? May be some MissingOnProfile annotation exist?) My task is to create different application behaviour based on application.properties files. Also i use #Profile annotation in each bean that depends on particular profile. All task is to create WebInstaller, and in finish step i will create application-prod.properties and by using RestartEndpoint i will restart application context and required beans from application-prod.properties will injected. But i need to make startup withoud application-prod.properties, but if this file exist i will startup in prod profile.
You can do this:
SpringApplication application = new SpringApplication(IdMatrixApplication.class);
File file = new File("src/main/resources/dev/application-prod.properties");
if (file.exists()) {
application.setAdditionalProfiles("prod","dev");
}
application.run(args);
You are setting the profile information in the wrong place. The file application.properties contains properties that are common to all profiles (dev, stage, prod etc). For profiles you should, as you suggested, create a file of the name application-{profile}.properties which will override certain properties according to the environemnt defined by variable profile.
The usual approach is to pass this variables as parameters to the JVM (e.g:-Dprofile=dev), which you can set by modifying the run configuration of the servlet container if you are launching from an IDE. In case of a stand-alone tomcat you can pass this information through JAVA_OPTIONS variable found in the file setenv.sh.
If you need to manually implement some kind of business logic with profiles, for example, specify that the active profile by default prod
In application.properties define spring.profiles.active=prod
and for example if the application-prod.properties is missing, then the active profile should be the dev, you can implement this with EnvironmentPostProcessor:
Allows for customization of the application's Environment prior to the application context being refreshed
Implement EnvironmentPostProcessor with your business logic
public class ProfileResolverEnvironmentPostProcessor implements EnvironmentPostProcessor {
#Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
ClassPathResource prodPropertiesResource = new ClassPathResource("application-prod.properties");
// if "application-prod.properties" missing and "prod" profile active
if (!prodPropertiesResource.exists() && environment.acceptsProfiles("prod")) {
environment.setActiveProfiles("dev");
//environment.addActiveProfile("dev");
}
}
}
Register your EnvironmentPostProcessor implementation class in META-INF/spring.factories
org.springframework.boot.env.EnvironmentPostProcessor=\
com.example.ProfileResolverEnvironmentPostProcessor
Also, take look at Spring Boot documentation Customize the
Environment
Additional:
Of course, you can specify beans that will be active if the profile is missing #Profile("!prod")
But this does not work in your case if you define spring.profiles.active=prod, because the active profile prod will be in the Environment but it has nothing to do with the fact that the application-prod.properties is missing
If you want this then why you need application-dev.properties. Keep Your dev properties in application.properties. If profile set then applicatoin.properties value will be overwrite. Spring boot read both application.properties && application.yml and replace value if profile active
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.
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.