spring profile groups - java

I have an application, for which I can specify the profiles I want to run it on.
but I also want to group these profiles into things like credentails, application performance, memory-print, application behaviour etc.
Ex. I can run the following profiles
-Dspring.profiles.active=production,cached-local,db-connection-pooled...
but I would prefer initializing it as
-Dspring.profiles.active=production,super-fast
#the above activates method level caches, db connection pooling etc
#super-fast triggered activation of cached-local, db-connection-pooled profiles
or
-Dspring.profiles.active=dev,low-footprint
#the above dosent enable caching, or db connection pooling
can this be achieved without writing any custom code like
How to set active spring 3.1 environment profile via a properites file and not via an env variable or system property.
I am fine even if I can load these from properties files or inside spring-xml config.
I am using xml only config on spring 3.1.

Spring Boot have since added functionality to address this problem, called "Profile Groups". A profile group allows you to define a logical name for a related group of profiles.
For example, we can create a production group that consists of our proddb and prodmq profiles.
This allows for a grouping to be defined, which is added to the spring-profiles-active, which when enabled, in turn, enables other profiles.
For more information see https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.profiles.groups

I don't know of any way to achieve this without custom code which would manipulate the active profiles in a ConfigurableEnvironment.
We're trying to achieve the same indirection pattern as rights vs. roles (group of rights) in a security framework, but since this doesn't come out of the box, I ended up having to work around it.
I kept my profiles general, e.g. production and super-fast in your case, and for each bean that is sensitive to those profiles, I set the correct #Profile. To make refactoring easier, I used two techniques.
Create a meta-annotation for each profile, e.g. #Production, #SuperFast and make the profile name a public constant, e.g. Production.PROFILE_NAME = "production".
When marking the profile of any bean, use your new meta-annotation if it only applies to one profile, or use #Profile({Production.PROFILE_NAME, ...}) if it applies to multiple profiles. You have to do this because you can't apply two profile meta-annotations to the same bean, at least not until 4.0.
For example,
#Profile(Production.PROFILE_NAME)
public #interface Production {
public static String PROFILE_NAME = "production";
}
The point of all this is that you can now use your IDE to look for usages of #Production or Production.PROFILE_NAME if you need to quickly understand or change what beans are being pulled in.

Related

How to append multiple values under the same property key?

I have multiple projects that expose a Prometheus endpoint, like so:
Application1: management.endpoints.web.exposure.include=info,health,prometheus
Application2: management.endpoints.web.exposure.include=info,metrics,prometheus
Application3: management.endpoints.web.exposure.include=info,refresh,prometheus
Instead of adding this Prometheus config to each application separately, I have extracted this to a separate library and added it as a dependency. The lib's application.properties file only consists management.endpoints.web.exposure.include=prometheus.
Whenvever I start up my applications, all of their config is overwritten with prometheus, instead of the value being added to the back of the list.
Is it possible to append multiple values to the same key instead of it being overwritten?
Sounds like you need to use profiles feature. Profiles means that you can run the same project with different profiles where each profile can have its own property files and even different bean implementations per profile. Read this article about profiles and see if that will help: Spring Profiles

Spring boot - Loading configuration property file in to java.util.properties

I need to load a configuration property fully into java.util.Properties file in my spring boot project and then need to pass this wherever needed. With Spring boot I can load the full file and can get the access of the values though keys. But how I can load the whole configuration file into Properties object or pass the spring loaded property (not a single value rather all the values) wherever required?
My current code:
Properties myProps= new Properties();
myProps.load(resourceAsStream);
If you're looking for specific ways of loading them using Spring-boot I'd suggest looking into:
Binding properties to an object by using the #Configuration, #ConfigurationProperties and #PropertySource annotations if you want to enforce and implicitly manage type-safety at all times
The Environment interface you can #AutoWire to your classes, if you don't need to enforce type-safety at all times (you can still do it, but you're not forced to). #PropertySource can be used in this case as well to load properties outside the default default-loaded application.properties, although they'll be loaded only when the application context refreshes (e.g. they won't be available while the application is booting up)
The PropertiesLoaderUtils class, as suggested in the comments, if you want to selectively load a configuration file at runtime for example
I usually recommend the first. The result is the same as using an #AutoWired Environment, with the advantages of implicit type-safety and improved readability. You can then get the properties and write them inside your java.util.properties if you need them to be there.
However, there is more than one way to do that, both using Spring-Boot or not. Loading properties like that is also perfectly fine, although arguably not the best practice since you're using Spring-boot.

How can I make a profile-specific bootstrap.yml?

I want to have different property values in a bootstrap.yml file depending on a spring profile passed to a starting application (the same way as it works for application-{profile-name}.yml).
How is it possible?
According to the documentation it should work pretty much the same.
Changing the Location of Bootstrap Properties:
If there is an active profile (from spring.profiles.active or through the Environment API in the context you are building), properties in that profile get loaded as well, the same as in a regular Spring Boot app — for example, from bootstrap-development.properties for a development profile.
That is it should be possible to suffix the bootstrap yaml with the environment name to make it take effect.

Get list of Spring property placeholder and their resolved values

I would like to make all property placeholder and their resolved values of a running Spring (Boot) application available for process monitoring. In the first step this could be just by writing them to the logs or by creating a 'resolved.properties' file similar to the application.pid file.
All properties where property placeholder are used (implicit/explicit) should be considered.
Motivation: It is usually hard during operation to know the values of resolved properties. System properties or command line arguments are "visible" but e.g. hidden default values in the code (like #Value("${timeout:30000}")) are hard to find out. I would like to be able to answer the question "How does the configuration of the running application looks like?" in a generic way that I can use in all of my spring applications.
I know about the Spring Boot Actuator /configprops endpoint, but this only includes #ConfigurationProperties. I would like to get a list of all properties where placeholder are used.
The requirement does not seem to be new (see here or here) but I wonder if there is an appropriate (bootiful) way nowadays.
There is (currently) no way to obtain all the properties in the Environment abstraction. This is intentional as can be read here. This is also why it isn't possible to obtain all the values used for resolution.
The values and resolutions are logged at runtime telling which key was resolved from where at runtime. But that logging is quite verbose and logged each time a StringValueResolver is used.
You might get a partial result by providing your own customized PropertySourcesPlaceholderConfigurer which maintains a collection of resolved key/value pairs. But not every resolution uses the PropertySourcesPlaceholderConfigurer some directly use a StringValueResolver implementation bypassing the PropertySourcesPlaceholderConfigurer.
It doesn't cover all your needs (ie: properties from all files, default values, application arguments, etc.).
I'll still keep the answer for other readers/future reference.
Spring Boot's Actuator /env endpoint
You may use the /env endpoint. It lists a bunch of stuff but it also includes the content of application.properties (near the end):
applicationConfig: [classpath:/application.properties]={myproperty=blah, server.port=8080}

How to prevent Spring Boot Devtools from caching few files

I am using spring cache to cache my database results, when spring cache is enabled along with spring boot devtools we receive weird exception ClassCastException due to known limitation is spring dev tools.
Now I want to exclude the class which contains cache from auto restart or reload, How we can achieve this?
You can workaround this issue pretty easily.
First of, you can disable caching completely, simply add the following to your configuration:
spring.cache.type=none
You could add that as a system property, or in the run configuration of your IDE so that it only applies when you're using devtools on your box.
Then you can switch to a cache manager implementation that does not serialize the content of object. One way to achieve that is to create a cache manager in memory with a certain profile:
#Configuration
#Profile("dev")
public DevConfig {
public CacheManager cacheManager() {
return new SimpleCacheManager();
}
}
And then enable the dev profile (again via a property or in the run config of your IDE). This might now work if you have complex eviction rules.
Finally, you can fix the underlying problem by adding (including) the cache library (the component that is responsible of the serialization) in the application classloader. See this link for more details.
The restart technology provided by Spring Boot works by using two classloaders. Classes that do not change (for example, those from third-party jars) are loaded into a base classloader. Classes that you are actively developing are loaded into a restart classloader. When the application is restarted, the restart classloader is thrown away and a new one is created. This approach means that application restarts are typically much faster than “cold starts”, since the base classloader is already available and populated.
By default, any open project in your IDE is loaded with the “restart” classloader, and any regular .jar file is loaded with the “base” classloader. If you work on a multi-module project, and not every module is imported into your IDE, you may need to customize things. To do so, you can create a META-INF/spring-devtools.properties file.
The spring-devtools.properties file can contain properties prefixed with restart.exclude and restart.include. The include elements are items that should be pulled up into the “restart” classloader, and the exclude elements are items that should be pushed down into the “base” classloader. The value of the property is a regex pattern that is applied to the classpath, as shown in the following example:
restart.exclude.companycommonlibs=/mycorp-common-[\\w\\d-\.]+\.jar
restart.include.projectcommon=/mycorp-myproj-[\\w\\d-\.]+\.jar
see Spring boot devtools docs

Categories

Resources