I have external property files in spring boot based project, I am configuring like below.
#Configuration
#PropertySource("file:${application_home}config.properties")
#ComponentScan({"com.myorg.project","com.myorg.project.module"})
#EnableAutoConfiguration
#EnableSpringDataWebSupport
public class Application extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Now I have many environments like dev,prod,staging. Like this I am having almost 7 environment.
I am maintaining like below
dev-config.properties
prod-config.properties
stg-config.properties
So adding any new config parameters becoming tedious task, as developers interested only in adding to dev-config.properties so extending the same to other is becoming problematic also developer may miss adding the same config variable name to other config files.
Is there any way where adding any config variable should be reflected other with default(if any change required will be handled by devops)
Is there anyway maintain what is changing from current release to old release ?
Because of this it is affecting CI-CD also.
Related
By default Spring Boot will automatically load properties from classpath:/application.properties
I want to know where is this auto configuration source code.
I want to exclude from my app.
IE: #EnableAutoConfiguration(exclude=XXXXAutoconfiguration.class)
The reason is:
Because I cannot override the default application.properties by an external property using #PropertySource
#SpringBootApplication
#ComponentScan(basePackages = {"com.test.green.ws"})
#PropertySource(value = {"classpath:/application.properties", "file:/opt/green-ws/application.properties"})
public class GreenWSApplication {
public static void main(String[] args) {
SpringApplication.run(GreenWSApplication.class, args);
}
}
There are many ways to override property keys without disabling the whole externalized configuration feature; and that's actually the goal.
You can see here the order the properties are considered in. For example, you can add that external properties file in a config folder right next to the packaged JAR, or even configure the file location yourself.
Now if you really want to disable all of that (and the Boot team strongly suggests not to do that), you can register your own EnvironmentPostProcessor (see here) and remove PropertySources from MutablePropertySources, which you can fetch with configurableEnvironment. getPropertySources().
There's no easier way to do that because:
this comes really early in the application init phase, before auto-configurations
this is not something you should do, as it will have many side effects
This question is somewhat similar to this existing question
I am still trying to navigate or trying to find right spring boot code, which i can customize. I need to develop java SDK which connects with existing config server and provides values to key. This SDK will be used in java applications, which might or might not be spring application. Same SDK will be used by QA for regression testing of config server.
So question is, if given
Config server URL
application name
active profile (no need for label, it will be default master),
Can I initialize some config client class which will give me simple methods like public String getKeyValue(final String key)
I am looking at source of classes like ConfigServicePropertySourceLocator, CompositePropertySource, ConfigClientAutoConfiguration, ConfigServiceBootstrapConfiguration etc.
Do I need to build Environment object manually? If yes, how?
I have some success. Posting a possible answer for others to further fine tune it.
#SpringBootApplication
public class ConfigSDKApp {
#Autowired
public SomeSpringBean someBean = null;
private static ConfigSDKApp INSTANCE = null;
public synchronized static ConfigSDKApp getInstance(String[] args) {
if (null != INSTANCE) {
return INSTANCE;
}
SpringApplication sprApp = new SpringApplication(ConfigSDKApp.class);
sprApp.setWebEnvironment(false);
ConfigurableApplicationContext appContext = sprApp.run(args);
ConfigSDKApp app = appContext.getBean(ConfigSDKApp.class);//new ConfigSDKApp();
INSTANCE = app;
return INSTANCE;
}
}
It's kind of singleton class (but public constructor). Hence code smell.
Also, what if this SDK is running with-in springboot client. ApplicationContext & environment is already initialized.
I have two small apps, one uses spring-boot-starter-amqp, other uses spring-data-hadoop-boot. I can run them separately without any problems.
When I join them together, app start fails with exception: org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
My main class is pretty much generic and it works fine for both of them separately:
#PropertySource("file:conf/app.properties")
#SpringBootApplication
public class Job {
public static void main(String[] args) throws Exception {
SpringApplication.run(Job.class, args);
}
}
I am at lost here. AFAIK #SpringBootApplication contains all annotations needed, including auto configuration and components scanning. I've had no need to configure web environment as I am not using it. Why do I need to do it when both dependencies are in class path, and how do I fix it?
UPDATE
I dug a little bit in the Spring Boot code. Main problem is that SpringApplication.deduceWebEnvironment() automatically detects what kind of environment should be configured based on existence of certain classes in class path.
For web environment two classes are being checked. When both of them are in class path, web environment is detected which requires proper configuration, obviously.
javax.servlet.Servlet
org.springframework.web.context.ConfigurableWebApplicationContext
spring-boot-starter-amqp:1.3.1.RELEASE contains ConfigurableWebApplicationContext, and spring-data-hadoop-boot:2.3.0.RELEASE-cdh5 contains Servlet (in native Hadoop libs).
Now, when run alone, one of above classes is missing in both cases, which results in web environment not being set.
But when I use both of them - both classes can be found. Web environment is detected, false positive, and it requires configuration, which I am not able (and don't want) to provide.
So question now is - can I force non web environment, even when I have those classes in class path? Or is there any other way to solve the issue? (other than excluding them from Gradle dependencies)
Solved.
Following this question: How to prevent spring-boot autoconfiguration for spring-web?
I run application as follows.
#PropertySource("file:conf/app.properties")
#SpringBootApplication
public class Job {
public static void main(String[] args) throws Exception {
new SpringApplicationBuilder(Job.class).web(false).run(args);
}
}
Answers to above question also suggested to use property spring.main.web_environment=false or annotation #EnableAutoConfiguration(exclude = WebMvcAutoConfiguration.class). Both solutions haven't worked for me. Only programmatic solution works in my case.
I have a project setup something like this:
-common-lib (common lib to included by multiple services)
-event-lib (spring framework 4 (read IOC) library for our event buffer. I want to embed the prod configuration within the app so consumers can use it without configuring it.
-serviceA (depends on event-lib, springboot application)
-serviceB (depends on event-lib, spring framework application)
I've been struggling on how to manage configuration in a Java-annotated way.
In the example below (running in the event library as a spring framework 4 project):
I couldn't get the PropertySource to honor the enviornment's spring.profiles.active
The environment wouldn't set an active profile even though -Dspring.profiles.active="dev" was specified)
#Configuration
#ComponentScan(basePackages = "com.*")
#PropertySource("classpath:events-{$spring.profiles.active}.properties")
public class EventConfiguration {
#Inject
private ConfigurableApplicationContext ctx;
#Inject
private Environment environment;
#Value("${events.asset-processing-queue}")
private String assetProcessingEventQueue;
}
It didn't make much sense to me, since multiple profiles could be activated at once (and that approach to referencing files is dependent on having only 1 set active).
Ideally, I am trying to find a solution that:
Uses either yaml or a combination of properties files for all the environment properties needed
Has some sort of intelligent hierarchy of what properties should be loaded. E.g. if I specify a property in my shared lib, honor it unless the consumer overrides it with their own value.
Can work in a spring framework 4 or spring boot app (we do some stuff with AWS lambda and dont want the spring boot overhead)
Relies only on java annotation and flat files for the properties. (Prefer to avoid XML).
Here's how we did it:
#PropertySource("classpath:/${env}.config.properties")
public class Application implements RequestHandler<Request, Object> {
#Override
public Object handleRequest(Request request, Context awsContext) {
ExecutionEnvironment env = getEnvironment(awsContext.getFunctionName());
System.setProperty("env", env.toString());
This respects the environment property.
We need to have common XML configuration parameters(like timetolive) for Jcache configuration.
We are using EhCache for Development and might be using some other Jsr107 compliant cache provider, like Infinispan, in other environment.
is it possible to have single configuration file being used by both Caching provider, and we need to change only some parameters, if required, for different environment?
Is it ok to define these properties in properties file and use them to initialize Cache managers based on Profile?
I went through jsr107 documentation but didn't find common xml caching attributes.
Technology : Spring boot 1.2.3, Java 7
It really depends on what you need to use. JCache exposes a Configuration and MutableConfiguration classes that you can use to configure some settings.
Spring Boot 1.3 (about to be released) has a complete JCache integration; when you add a JSR-107 provider in your project, Spring Boot will automatically create a CacheManager for you. If you define a bean of type JCacheManagerCustomizer, it will be invoked to customize the cache manager before the application starts servicing requests.
For instance, this is a very basic configuration that changes the expiration policy:
#SpringBootApplication
#EnableCaching
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Bean
public JCacheManagerCustomizer cacheManagerCustomizer() {
return cm -> {
MutableConfiguration<Object, Object> configuration = new MutableConfiguration<>()
.setExpiryPolicyFactory(CreatedExpiryPolicy
.factoryOf(Duration.ONE_HOUR));
cm.createCache("foo", configuration);
};
}
}
JSR-107 does not specify anything with regards to external configuration - xml, properties, you name it.
As such any externalized configuration solution will have to be provided by your code or a framework like [Spring][1].
[1]: See Stéphane Nicoll's answer