How to append multiple values under the same property key? - java

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

Related

How can I externalize some config variables in spring boot?

I have a yaml file that contains some credentials for azure keyvault. This project is I am working on is a shared git repo so I would like to set these values as environment variables for the whole project not just for myself
application.yml:
azure:
keyvault:
uri:someUri
client-id:someClientId
client-key:someClientKey
but I want to have them set up like this:
azure:
keyvault:
uri: ${uri}
client-id:${clientId}
client-key:${clientKey}
Is there a way to set those values and have this work for others without them having to manually set these values in their environment?
You can ignore the .yaml in gitignore so you can use your config in your environment. And if you pull from others their config won't overwrite your config.
If you want if like dynamically
java -jar myapp.jar --spring.application.json='{"foo":"bar"}'
You can add variables like this in start command. Configure in your Run configuration.
The syntax you've presented above is supposed to work.
I usually use capital letters for 'convention' but other than that its fine.
However providing such a syntax effectively means that you don't want to define property values in your application so you'll have to get them from elsewhere.
From your question I understand is that your primary concern is your teammates and in your setup each one of your peers has clientId, key, etc.
In this case you can create a script that will "export" all the variables to be environment variables automatically, they'll run it only one time and it will work since than.
Another option which is kind of similar is providing a property SPRING_APPLICATION_JSON that will refer to the json with a configuration, spring boot application can read it as written in the official documentation

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.

Where to define properties in SpringBoot which are common across all environments?

I have few properties common to all environments (Ex. spring.jpa.properties.hibernate.ejb.interceptor) which I have kept in application.properties under resource directory.
I have DB properties defined in environment based properties file which I pass externally through command line while starting the app:
java -jar -Dspring.config.location=<path-to-file> mySpringBootProject.jar
However, spring.jpa.properties.hibernate.ejb.interceptor is not being set when I am passing properties file externally.
Do I need to define common properties even in external file?
Or is there a way I can define them in a single place which is reused when not overridden?
You can use multiple profiles to do this. For example, create property files:
application-dev.properties
application-prod.properties
application.properties
Place your environment-specific properties in the application-${env}.properties file and your common properties in application.properties.
There are multiple ways to tell spring which profiles to use, for example the --spring.profiles.active flag.
See the Spring Boot documentation for more details about the property file search order.
application.properties will normally be overridden by Boot projects. Instead, you can add a properties file in a non-conflicting location (such as src/main/resources/my/package/foo.properties) and use #PropertySource on your autoconfiguration file to add it.
Properties is a file extension for files mainly used in Java related technologies to store the configurable parameters of an application. The advantage of using properties file is, we can configure things which are environment specific (or are prone to change over a period of time) without the need of changing anything in code. Hence inheriting common properties is not a good approach. If a property seems to be static for all e.g. environments, then it shouldn't be a property.
But, it could be we have multiple development environments and production, where we would share same properties in the environments meant for development purposes and different properties for production. In this case we could create a common properties file and inherit it in all our environment specific properties files. Another scenario could be, that at the moment of development the property is same for all environments, but we would like to provide the option of changing it in the future, when required.

spring profile groups

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.

Best way to reference the file system in a spring mvc app

In a spring mvc application, what is the best way to reference the filesystem?
Say I want to know the root of my applications path?
Should I create a properties file and hard code this value in the property file, then create different versions for production and development environments?
I might want to reference a file outside of my application also, so I guess a property file is best suited for this correct?
I understood your question as a config/release problem, not coding problem. If you want to access file (say with absolute path) there are different ways to achieve it:
if you use maven to build your app. create maven profile with corresponding property, e.g. file.path and at build-time fill the property to spring bean (e.g. a String)
create different properties files, which containing config parameters for different environments. and let maven fill the placeholder in spring conf, which properties file should be used.
use spring profile. put server-relevant beans in profiles, and your application choose the right profile (the set of beans) at runtime.
well if you have different databases for different environments, you could consider to save some config parameters in a config table. And application loads those data when it starts or when it needs. At least this is another option.
did that answer your question? or I am just talking about something else?...
Get real path and complete your remaining action
String realContextPath = session.getServletContext().context.getRealPath(request.getContextPath());

Categories

Resources