I have a couple of Linux Environments into which my spring boot application is going to be deployed i.e QA & PROD.
If I set a System property such as thsese and pull them in the Spring Boot app to set the active environments,
ENVIRONMENT=QA in QA and
ENVIRONMENT=PROD in PROD
are there any potential limitations (technicnal, administration, continuous integration issues etc.)that I might face or is there a better approach to pick up the active environment?
Just name your environment variable SPRING_PROFILES_ACTIVE and it will automatically get picked up by Spring Boot, no need to implement any custom logic for that (see the documentation about externalized configuration: http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config).
Related
I am writing a batch using Spring Boot 2.7.1 and spring-boot-starter-batch . The batch needs 2 different WebClient to call 2 different APIs with different authentication systems, that I configure through standard Spring Boot properties (spring.security.oauth2.client etc).
It works well, but I realized the batch was listening on port 8080 when running, because I have imported spring-boot-starter-web , which enables the auto-configuration of my WebClient , by injecting a ClientRegistrationRepository . It's not a major issue, but it prevents me from launching the batch twice in parallel for instance, because the port is already used... so I would like to disable the web server part.
The problem is that when I disable the web server, either through properties, code or dependencies (by removing spring-boot-starter-web), then the batch doesn't start anymore, because ClientRegistrationRepository is not loaded anymore, because I require
a bean of type 'org.springframework.security.oauth2.client.registration.ClientRegistrationRepository' that could not be found
This is because, there's a conditional on Spring's OAuth2ClientAutoConfiguration :
#AutoConfiguration(before = SecurityAutoConfiguration.class)
#ConditionalOnClass({ EnableWebSecurity.class, ClientRegistration.class })
#ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
#Import({ OAuth2ClientRegistrationRepositoryConfiguration.class, OAuth2WebSecurityConfiguration.class })
public class OAuth2ClientAutoConfiguration {
}
Because the application is not of type SERVLET, but NONE, this doesn't get enabled.
I've tried to "force load" it :
#ImportAutoConfiguration(OAuth2ClientAutoConfiguration.class)
but it doesn't work.
Looking into the source code, I see that OAuth2ClientAutoConfiguration is actually loading 2 config classes, but they are not public, so I can't import them directly :
#Import({ OAuth2ClientRegistrationRepositoryConfiguration.class, OAuth2WebSecurityConfiguration.class })
there must be a trick to achieve that.. but what is it ?
With Spring Boot, you can customize the port of your webapplication by setting the property server.port=8095 in your application.properties or any customized env properties file ie application-dev.properties, application-prod.properties and so on.
Using these property, your webapplication will listen on the port of your choice and will not conflict anymore with other stuff. And if you need multiple instances running in parallel, run them with a range of ports could be great (#see https://stackoverflow.com/a/56884100/390462. You can add listeners too (#see https://stackoverflow.com/a/51876661/390462). Or at least multiple instances of your batch application with differents server.port values.
If you want to disable the webserver, the best bet is to use the property : spring.main.web-application-type=none.
I've just found something interesting using AuthorizedClientServiceOAuth2AuthorizedClientManager in your service layer (#see https://stackoverflow.com/a/60173451/390462
I have a micronaut application in which I want to override the default configuration properties based on a profile I pass through an environment variable.
Tha application has a default application.yml
I am currently passing:
MICRONAUT_CONFIG_FILES=classpath:application.yml,/path/to/application-prod.yml
MICRONAUT_ENVIRONMENTS=prod
However just application-prod.yml is taken into account (unlike for Spring Boot where it updates the defaults).
What is the best way to achieve the update? The only solution so far is to replicate all the settings in application-prod.yml but it seems pretty anti-DRY.
My project has a bootstrap.yaml and a config server that deliver its appropriate profile. Everything is working great but I have to accomplish some others task like CI and CD.
My problem comes because the Jenkins machine is not allowed to resolved external domains and try to compile and run the Spring boot app without an a profile.
So my question is:
Is there a way to load application.properties when the config server
is not resolved?
Yes, there is a natural way based on the order in which Spring Boot loads PropertySources.
You can include properties you want to be applied in application.properties.
In case config server is not available - properties from application.properties will be used. If config server is available - you'll receive properties from there.
You might also want to disable config server connectivity for your CI using environment variable SPRING_CLOUD_CONFIG_ENABLED=false.
I have multiple microservices which communicates with each other through REST calls.
I have used spring boot and spring rest and have configured the URLS of the rest end points in application.properties file.
Now the problems is if the URL for one end point changes then I to have to manually modify all the property files of the services which are calling that particular end point which has got changed.
Is there a workaround for this so that the URLS can be somehow placed in a centralized location so that any modification does not impacts the other services which are using it.
You can use spring-cloud to achieve this. Usual way used in spring-cloud is by configuring the required properties in a git repo. And then those properties can be accessed by any micro-service you want with minimal configurations. You can refer projects in this repo
limits-services acts as a client that needs certain properties those are configured in spring-cloud-config-server. Hope this helps.
In case with microservices you can use Spring Cloud Config (Spring Cloud Config, Spring Cloud Config Server). It's very usefull and you can update your configuration at runtime.
Spring Cloud Config provides server and client-side support for externalized configuration in a distributed system. With the Config Server you have a central place to manage external properties for applications across all environments. The concepts on both client and server map identically to the Spring Environment and PropertySource abstractions, so they fit very well with Spring applications, but can be used with any application running in any language. As an application moves through the deployment pipeline from dev to test and into production you can manage the configuration between those environments and be certain that applications have everything they need to run when they migrate.
As others have mentioned you can use Spring Cloud Config Server to remotly load your application configuration. All you need is git repository containing your configuration.
Spring cloud configuration supporst Git, database as your store for configuration.
Idea is to create an spring-boot app that can provide configuration to other applications.
#SpringBootApplication
#EnableConfigServer
public class ConfigServer {
public static void main(String[] args) {
SpringApplication.run(ConfigServer.class, args);
}
}
You can configurae port and provide your git repository using key spring.cloud.config.server
server.port: 8888
spring.cloud.config.server.git.uri: file://${user.home}/config-repo
At client side, if you have spring-config in your classpath, application will try to connect to an application runnign at port 8888 to retrieve configuration.
More information can be found here.
may put configuration inside a database.
after that need have one centralize cache service that used by other services, can be .jar service,
then the values can be load inside a cache class in this service,
then in the front end side need have update button for updating the cache after modify the URL value in the database, so then all impacted services can use new value.
and also to be easier may have stand alone UI for update those configuration rather than updating database directly.
You can use Microconfig.IO to manage your service configuration and it's placeholders functionality to reference configuration values of certain services from others. So in your case you configure your deploy url in your server and put placeholders on it in your clients. This allows you to edit value only in one place and then everyone who depend on it will get it automatically.
I am trying to have separate property files for prod and dev environment.
I have two property files application-prod.properties, application-dev.properties placed in classpath:/config
I added VM option -Dspring.profiles.active=dev
According to what I understand from the documentation and many other references on the web, on accessing Spring Environment as environment.getProperty("") the property in "application-dev.properties" should be loaded. However, I am getting null and as it seems the property files are not read by Spring.
I also tried defining both the files in #PropertySource. Doing this, the file defined second is picked up and the corresponding property is returned. Spring is not choosing the file based on the active profile.
Am I missing something?
I also came across a issue raised through some SO questions, but I am not sure if it refers to the same problem.
Right, so documentation you are pointing to is from Spring Boot project. That is not the same as Spring Framework. If you are not using Spring Boot, -Dspring.profiles.active=dev wouldn't work.
You have two options:
Introduce Spring Boot to your project ans turn on auto-configuration (#SpringBootApplication or #EnableAutoConfiguration).
Use plain Spring Framework features like PropertyPlaceholderConfigurer, but it doesn't give you same flexibility as Spring Boot features and you will need to create some boilerplate code to handle various envs.