Spring Boot Externalize properties from within application.properties - spring-boot

I want to set my property source location to point to an external directory from within application.propoerties itself.
I know passing command line argument as follows does the job.
java -jar myApp.jar --spring.config.location=/Users/tony/Desktop/override.properties
But I want to set this path from within the application itself rather than passing a command-line argument. I tried adding spring.config.location=/Users/tony/Desktop/override.properties to my application.properties but it doesn't work.
How can I do this?

You can try adding the following annotation to your main class where you call SpringApplication.run() :
#PropertySource("/Users/tony/Desktop/override.properties")
On running the SpringBoot application, it should pick up the properties from there. Excluding the application.properties from src/main/resources using build - resources - resource - excludes - exclude in pom.xml would help to ensure that the packaged jar doesn't include the applcation.properties and would force Spring Boot to pick it up from path specified in #PropertySource
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>**/application.properties</exclude>
</excludes>
</resource>
</resources>
</build>
But keep in mind that in this way, you are creating tight coupling of your properties file with your application. If you keep it as a runtime argument, it would be having enough flexibility to run elsewhere and maintenance would be easier too.

spring.config.location and spring.config.additional-location are only useful when set as Environment Variable, System Property, or command line argument.
The best you can do to specify additional configuration files to be loaded directly in your application.properties file, is to set the spring.config.import property like so:
spring.config.import=file:/Users/tony/Desktop/override.properties
References: https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config-files

Related

Could i use maven profile to swith between different value application.properties

I have application-prod.yml application-dev.yml, and application.properties which containing just one line code like below
spring.profiles.active=dev
for maven production build, it should use spring.profiles.active=prod , then it will build with application-prod.yml, for development build, it should use spring.profiles.active=dev, then maven
will use application-dev.yml to build
could I use pom.xml's different profile to do switch for this value switch in applicaiton.properties?
You can use a Maven property for this, reference it in your yml file (with ${...}) and filter the resource (i.e. the yml file) with the maven resources plugin.
It seems that what you're after is "externalized configuration". According to the excellent 12factor guidelines, it is best not to keep such config inside your code-repository.
Refer to the relevant section in the Spring Boot manual to see which options you have (and there are many). What it comes down to is that you provide your application.yml/properties file on the filesystem and your application will read it from there, rather than from the classpath.
Also, note that spring-profiles are not meant to be used to distinguish between development environments, but rather to put the application in different functional modes (e.g. to enable or disable specific features).
If you want the content of your properties file changed at build time, then you can use Maven filtering. Maven filtering allows to replace a placeholder in your properties (or yaml) file by values from Maven properties.
Assuming you have a property in your POM called targetEnv, which might have either the value dev or prod (depending on the active Maven profile), then you can refer it in your properties file (or yaml file) by using the following syntax :
spring.profiles.active=#targetEnv#
However, if you want to follow Spring Boot recommandations, it is better to enable and disable the Spring profiles by the means of environment variables in your target environment. For instance, you can use an environment variable spring.profiles.active with the desired value and it will override the value in your properties file.
You need to define a custom property in each of your Maven profiles and set their values to match with suffixes of corresponding properties files that you want to load with a particular profile.
<profile>
<id>dev</id>
<properties>
<activatedProperties>dev</activatedProperties>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>release</id>
<properties>
<activatedProperties>release</activatedProperties>
</properties>
</profile>
Next, in the build section of the same file, configure filtering for the Resources Plugin. That will allow you to insert properties defined in the previous step into any file in the resources directory, which is the subsequent step.
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
…
</build>
Finally, add the following line to the application.properties.
spring.profiles.active=#activatedProperties#
For more details, please see spring boot properties per maven profile
For official guide to load from external configLoad from external Config

Maven resource filtering - Explicitly specify which files require property injection

Does the Maven resources plugin allow a flexible way to exclude certain files during the injection of Maven profile properties?
I don't want to exclude the files from assembly, just from the injection phase.
The project I'm working on defines unique Maven Profiles (and corresponding properties) in Settings.xml for each deployment environment. When the project is built the following steps occur
The projects POM defines the resources folder as the target to apply resource filtering
The resources folder contains .XML and .PROPERTIES files
During mvn:deploy Maven injects Profile properties into the .PROPERTIES file as expected
Maven also injects Profile properties into .XML files. This is not desired behavior (these files contain placeholders which allow the project to flexible inject values during deploy of the application)
The resource plugin provides configuration options to define include and exclude options however choosing the exclude option will also exclude the specified file from the assembly folder which is not desired.
Is it possibly to tell Maven which files should have placeholders replaced?
You are probably using the filters mechanism, for which you can decide whether to apply it to a certain folder and which filter should be applied to that folder.
Given the following sample POM:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sample</groupId>
<artifactId>resources-example</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<filters>
<filter>src/main/filters/filter.properties</filter>
</filters>
<resources>
<!-- configuring an additional resources folder: conf -->
<resource>
<directory>${project.basedir}/src/main/conf</directory>
<filtering>true</filtering>
<excludes>
<exclude>*.txt</exclude>
</excludes>
<includes>
<include>*.properties</include>
</includes>
<targetPath>${project.basedir}/target</targetPath>
</resource>
</resources>
</build>
</project>
Note the filters section within the build section. Here we are telling Maven where how filter is, providing placeholders replacement.
Note then the <filtering>true</filtering> addition to a new resource configured afterwards and related includes/excludes patterns. As such, Maven will filter only the *.properties files of this folder.
Now, src/main/conf can contain a conf.properties file with the following content:
## add some properties here
property.example=#property.value1#
property.example2=${property.value2}
(Note the ant and maven style placeholders.)
While the src/main/filters (you need to create this folder) contains the filter.properties file with the following content:
property.value1=filtered-value1
property.value2=filtered-value2
Running the build you will get the conf.properties file in the target directory with the following content:
property.example=filtered-value1
property.example2=filtered-value2
Now, if your filter (file name) is a property injected by a profile, you can then inject different filters depending on the environment and only targeting certain files.

Unable to retrieve values from property files in Maven

Iam using maven pom.xml ( just started learning )
I had some .properties files (for eg: log4j.properties), I should be able to retrieve values from them either in pom.xml or in web.xml file , I mean if I use something like ${somename.version} in pom.xml or web.xml, this value should be retrieved from .properties files.
My properties files are under as below:
src/main/resources/log4j.properties
src/main/env/dev/config.properties
iam trying as below, BUT unable to retrieve values from properties files.. iam doing something wrong.
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/env/dev</directory>
<filtering>true</filtering>
</resource>
</resources>
please suggest me.
Your configuration is wrong, for reading properties from file use:
<filters>
<filter>src/main/resources/log4j.properties</filter>
</filters>
Your actual configuration is about what files should be filtered.
For more information and example go to: Maven Resource Plugin - Filtering
You can also use Properties Maven Plugin
Resource filtering is meant to set a property in pom.xml and then use it in a property file.
with ${somename.version} in log4j.properties and the appropriate code in pom.xml your ${somename.version} is replaced with what you typed in pom.xml
for example inside pom.xml
<property>
<name>somename.version</name>
<value>123</value>
</property>
in your log4j.property
${somename.version} will be replaced by 123
you will find your file with the replaced value inside the target directory after you launch a mvn package
resources filtering is used when you package with profiles. each profile can change the properties in pom.xml
your properties can hold values that change with environnement like configuration for windows or configuration for linux

Displaying version and date of build in the xhtml page

I want to display the build version and build date on the footer of a JSF application. The pages are XHTML. I'm looking for ways to get the information from pom.xml or other artifacts.
I found the following that uses maven-replace plugin.
http://www.vineetmanohar.com/2010/09/how-to-display-maven-project-version-in-your-webapp/
Are there any other techniques you use?
I'm looking for something like this with JSF - Displaying the build date
One approach that will work: use Maven filtering to put a file in your WAR or JAR containing the required information. Then in your Java webapp, load that file's contents as a ClassPath resource InputStream.
Create a file (let's say "buildInfo.properties") under src/main/resources containing something like:
build.version=${project.version}
build.timestamp=${timestamp}
Note that due to an open defect, you need to define the timestamp property as follows in the <properties> block of your pom:
`<timestamp>${maven.build.timestamp}</timestamp>`
During your build, this file will be filtered with the value of project.version (which you define with <version> in your pom.xml, when you specify
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
In your Java code (JSF bean, whatever), have code like the following:
InputStream in = getClass().getClassLoader().getResourceAsStream("buildInfo.properties");
if (in == null)
return;
Properties props = new Properties();
props.load(in);
String version = props.getProperty("build.version");
// etc.
If your framework supports loading properties as "Resource Bundles" from the classpath (i.e. like in Spring), no need for the preceding Java code that loads the properties file.

I can't get maven to use properties defined in ~/.m2/settings.xml?

I am using ~/.m2/settings.xml to store a number of property names used throughout the pom.xml files in my project. If I make the XML invalid (by adding another < for example), maven immediately generates an error, saying that it cannot parse that file. If I leave the XML valid, settings in my appBeans.xml file do not pick of references to properties defined in settings.xml.
Has anyone experienced this problem? I am sort of at my wits end here.
Reflecting properties from Maven configurations works by resources filtering.
Make sure your settings.xml, project pom and the target xml file contain correct configurations and reside in correct places.
If I understood correctly, you want to store a property name and value in the settings.xml so the props can be used in your project files. I'll provide a working example:
Define a default profile and properties in settings.xml:
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<someProp>Value</someProp>
</properties>
</profile>
</profiles>
Define resource folder's filtering=true in pom.xml:
<build>
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
Define the property in the xml file (that resides in the src/main/resources folder):
...
<element>${someProp}</element>
...
After this you should see the filtered result e.g. in target/classes/appBeans.xml.
Bear in mind that if you're using Eclipse & m2eclipse or similar plugin, it probably won't start using the updated settings.xml without restarting Eclipse and it's automatic build will sometimes overwrite your files in the target folder. I'm talking from experience here :)
Maven properties do not get reflected in miscellaneous XML files.
If you add one of these properties to the <properties/> element of the specific pom that runs the specific plugin that reads allBeans.xml, does that work? I believe that it will not, and your problem will turn out to be adding to the <configuration/> for the plugin to pass the maven properties to it.
If you edit your question to show the plugin that processes appBeans.xml I can make this more specific.

Resources