Hi I am little bit confusign about using profiles in spring.My Scenario is I have a custom properties file.And It is values changes for each environment(dev,test,prod).I use same bean for each environment.But I want to change values for each environments.
In this property files all keys are same,only their values different.
mydev.properties
mytest.properties
myprod.properties
So How should I implement profile logic to my code in my scenario(Bean is same ,values are different)
//Here is my bean
#Component
#PropertySource("my.properties")
#ConfigurationProperties(prefix = "my")
public class MyProperties
{
....
I will add to 'spring.profiles.active' to my propertysource and is this enough?
//I plan to add spring.profiles.active
#Component
#PropertySource("my${spring.profiles.active}.properties")
#ConfigurationProperties(prefix = "my")
public class MyProperties
{
....
Please go through the Spring Boot Reference : Section 2.4. Profile-specific Properties
In addition to application.properties files, profile-specific
properties can also be defined by using the following naming
convention: application-{profile}.properties.
One need to define the profile specific properties in application-{profile}.properties
and declare the active profile
You can use a spring.profiles.active Environment property to specify
which profiles are active.
To answer your concern , the property value for the current active profile will be wired to the bean. Also note that
Profile-specific properties are loaded from the same locations as
standard application.properties, with profile-specific files always
overriding the non-specific ones, whether or not the profile-specific
files are inside or outside your packaged jar.
If several profiles are specified, a last-wins strategy applies. For
example, profiles specified by the spring.profiles.active property are
added after those configured through the SpringApplication API and
therefore take precedence.
In your case , the ideal way to define profile specific properties would be
application-dev.properties
application-test.properties
application-prod.properties
Related
I have a custom starter that other projects depends on, and that starter applies some configurations including a PropertySource
#Configuration
#PropertySource(value = "classpath:application-geoip.yml", factory = YamlPropertySourceFactory.class)
public class CustomStarterAutoConfiguration
{...}
application-geoip.yml contains properties specific to it's business and an enablement value
...
geoip2:
enabled: true
...
The starter provides the geoip beans with condition to above enabled parameter.
#Configuration
#ConfigurationProperties(prefix = "geoip2")
#ConditionalOnProperty(prefix = "geoip2", name = "enabled", havingValue = "true")
public class GeoIP2ConfigurationProperties {...}
#Configuration
#ConditionalOnProperty(prefix = "geoip2", name = "enabled", havingValue = "true")
public class GeoIPConfig {
// define required beans here with dependency to config from above #Configuration bean
}
I ship my starter with this and then create a project depending on this starter.
In my project, when I check above beans (even the property already set to true) in the context I can not see the beans initiated.
Debugged a bit and see that; While annotation ConditionalOnProperty is being processed, the context does not have the geoip2.enabled set. But If I wait until the app start and listen the ApplicationStartedEvent event. I can see the property is there.
event.getApplicationContext().getEnvironment().getProperty("geoip2.enabled") returns true.
so If I am assuming it correct, the PropertySource annotation seems to processed after ConditionalOnProperty annotation. Not always, but mostly. Depends on who wins the race.
Why I am trying this, I would like to carry the property from core with a default value. then using projects can override it in their own application.yaml files. I treid to add the property on simple project's application.yaml file and this time the property picked up and beans initiated as expected.
Rather than using #PropertySource, your custom starter should provide an EnvironmentPostProcessor implementation that's registered in META-INF/spring.factories. This post-processor is called once the Environment has been created but before the application context is refreshed and any beans are created. It should add a PropertySource to the environment that contains the geoip2 properties. If you position your PropertySource appropriately, these properties could then be overridden by those in the user's application.yaml file.
You can learn more in the reference documentation.
I want to read values from an active profile or can say active properties file.
I have three properties files
application-dev.properties
application-stage.properties
application-prod.properties
I have set an active profile to dev as follows
spring.profiles.active=dev
My application-dev.properties file has one entry that i want to read in my class.
application-dev.properties file
fix.connection.type=initiator
I tried reading this entry
#Configuration
#PropertySource("classpath:application-${spring.profiles.active}.properties")
#Component
public class AdaptorDestination {
#Value("${fix.connection.type}")
private String connectionType;
}
Exception
nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.profiles.active' in value "classpath:application-${spring.profiles.active}.properties"
Please help me out
You don't need to use #PropertySource annotation in order to load a property using #Value annotation.
Spring will load #Value property automatically from the current active profile.
Also, you don't need to specify ${spring.profiles.active} in the #PropertySource annotation as Spring always loads properties from the currently active profile by default.
Spring automatically resolves file name based on the profile suffix.
So you need only specify the base filename, e.g.:
#PropertySource("classpath:application.properties")
If the currently active profile is "dev" Spring will load properties at first from application.properties file and then override them with properties from application-dev.properties file.
You can read more here
You can use the annotation #Profile("profile-name") to determinate when to execute the method.
Spring Profiles
I am writing a spring mvc application. I want to make use of spring profiles' features. I want to have a single application.properties with common and profile specific properties. I also want to have a set a default profile in the same file. How do i do this?
You could create an extra spring configuration class to dynamically return the properties based on the spring profile:
#Configuration
#PropertySource("classpath:application.properties")
public class QuotePropertyConfiguration {
#Inject
private Environment environment;
#Bean
public String getMySpecificProperty() {
return environment.getProperty("myprop." + Arrays.toString(env.getActiveProfiles()) + ".thing");
}
}
That will return you e.g. myprop.dev.thing, myprop.test.thing, myprop.prod.thing etc. depending on the active spring profiles.
Alternatively you can also do this with multiple application.properties files: From the spring documentation:
In addition to application.properties files, profile-specific
properties can also be defined using the naming convention
application-{profile}.properties. The Environment has a set of default
profiles (by default [default]) which are used if no active profiles
are set (i.e. if no profiles are explicitly activated then properties
from application-default.properties are loaded).
I have some common properties that every projects should set, such as
feign.hystrix.enabled=false
feign.httpclient.enabled=true
I don't want to repeatedly add these props in every project so I'm going to create an extra jar file containing #Configruation class. How to add properties in #Configuration class? Thanks!
PropertySources
You may load an application.properties from another jar this way:
#PropertySources({
#PropertySource("classpath:common.properties")
})
#Configuration
public class SomeJavaConfig {
}
You can find the reference in Spring's documentation:
Spring Boot uses a very particular PropertySource order that is
designed to allow sensible overriding of values. Properties are
considered in the following order:
...
#PropertySource annotations on your #Configuration classes.
Spring-cloud-config
I won't go in all the details, but another option is to use spring-cloud-config to define these properties in a git (using spring-cloud-config-server). Then, have your spring-boot application load the application.properties using spring-cloud-config-client directly from git.
Check this:
https://cloud.spring.io/spring-cloud-config/spring-cloud-config.html
https://spring.io/guides/gs/centralized-configuration/
When defining properties in YAML for a Spring Boot 1.4 application, I have to use the main/resources/application.yaml file. So far, so good.
How can I override these dependencies using YAML depending for a specific profile when running or testing the application.
When using Spring Boot 1.4 (this applies for release 1.3 as well) YAML properties are always defined in the main/resources/application.yaml file. Depending on the chosen profile, the properties can be overridden by another set of properties.
To override these properties for test, a YAML file has to be given in the /test/resources/application-.yaml file, where is replaced by the active profile. It is important to see that the profile always has to be given, even when there is no active profile. In that case, the profile is ‘default’.
To override the properties when running the application, properties can be overridden for a specific profile using in a file called main/resources/application-.yaml file. Even for this situation, if no profile is given, the profile for the filename is ‘default’.
Example
The test class Spring14ApplicationTests.java for Spring Boot 1.4 has the following definition
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
public class Spring14ApplicationTests {
…
}
For Spring Boot 1.3, the same file has the following definition
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes=SpringDb14Application.class)
#WebAppConfiguration
public class SpringDb14ApplicationTests {
...
}