I have a executeable jar what I want to configure by properties outside of the jar. What works fine is application.properties, when putting it to config folder close to the jar. But I have a second property-file what seems not to be picked up and I would like to have the best practice for that.
The folder config looks like:
In the config-folder you will find:
Both property-files are also in the src/main/resources folder.
My StartClass looks like:
#SpringBootApplication
#PropertySource("migration-shrink.properties")
public class MigrationShrinkApplication implements CommandLineRunner {}
My bat file looks like:
java -jar migration-shrink-0.0.1-SNAPSHOT.jar -Dspring.config.location=./config/migration-shrink.properties
I wanted to separate Spring-Configuration from Application-Configuration, thats why I have two different property-files.
Thank you!
The #PropertySource annotation is not necessary.
As of Spring Boot 2.0, you can declare additional locations with:
-Dspring.config.additional-location=./config/migration-shrink.properties
Keep in mind that those additional locations are searched before others, so values can be overridden in the other locations.
See the Spring Boot reference documentation.
Related
In which class in the source code of spring-boot or spring is the application.yml file or application.properties processed?
For spring boot (version 2.x) the application properties are loaded from the environment into the context via a PropertySourceLoader.
In for example the spring-boot-2.6.3.jar we can find the following file:
META-INF/spring.factories
# PropertySource Loaders
org.springframework.boot.env.PropertySourceLoader=\
org.springframework.boot.env.PropertiesPropertySourceLoader,\
org.springframework.boot.env.YamlPropertySourceLoader
Where PropertiesPropertySourceLoader loads .properties and .xml files, and YamlPropertySourceLoader loads .yml and .yaml.
These are loaded with the SpringFactoriesLoader, which we can see in action in org.springframework.boot.context.config.ConfigFileApplicationListener (deprecated) or org.springframework.boot.context.config.StandardConfigDataLocationResolver (via ConfigDataEnvironmentPostProcessor -> ConfigDataEnvironment -> ConfigDataLocationResolvers) :
this.propertySourceLoaders = SpringFactoriesLoader.loadFactories(PropertySourceLoader.class,
getClass().getClassLoader());
You can read in the ConfigFileApplicationListener JavaDoc that the properties are indeed loaded with this class:
EnvironmentPostProcessor that configures the context environment by loading properties from well known file locations. By default properties will be loaded from 'application.properties' and/or 'application.yml' files in the following locations:
file:./config/
file:./config/*/
file:./
classpath:config/
classpath:
...
If you're interested in context loading from the environment in spring(boot), I suggest you setup your project with maven, download the sources jars, and have a look around in the mentioned factories file. You will find more relevant code in the org.springframework.boot.env and org.springframework.boot.context (config and properties) packages.
You can find your application.yml or application.properties at the src/main/resources. You can have as many as possible configurations for your spring boot application for every case. Lets assume that you have 3 local-profiles like demo, production and server, so you made 3 configuration and assumingyou set for active profile the demo at the application.yml . I hope you get the idea. Its the first thing that actually is running before the springboot is up.
Please look the officials docs !
I am following a tutorial on using external configuration files for Spring Boot. I got everything to work exactly as intended but I'm having issues overriding the default YAML config for my tests.
Could someone please point me in the right direction or advice if using '#PropertySource' is the best way to load config files into the project (There is a bunch of properties and I would like to keep the application.yaml as clean as possible)
Project Structure:
src: - main/resources/foo.yml <-- always loads this one
- test/resources/foo.yml <-- never loads
What I tried:
#PropertySource(value = "classpath:foo.yml")
Doesn't load test/resoruces/foo.yml to the classpath
ActiveProfiles()
How I usually change config properties but in this case, it's not a profile so it doesn't work.
Details:
Spring boot: 2.2.7.RELEASE
Try this:
#TestPropertySource(properties = { "spring.config.location=classpath:foo.yml" })
i have created springboot project which gives fat-jar. i want to push external xml file in runtime into it.i want to place that xml file into spring-boot-tomcat container. tried many ways to do it (#import, --spring.config.location,etc) those ways didn't work out for me.
That xml file is ApplicationInsight.xml, which is used to post telemetry from our application to Azure portal.
Highly appreciate any help.
Based on the GitHJub issue, I think part of the problem is how you are passing JVM parameters, and how you are using "spring.config.location".
I am not familiar with Azure Insights really, but if I understand correctly, it is trying to load the ApplicationInsights.xml file to configure itself, and it's doing this automatically. So you really can't set it up in the WebConfigurerAdapter as I previously suggested because it has already initialized itself before that, correct? I left that part in anyways, but I get that it needs to be loaded sooner so I provided a few additional ways to add the file to the classpath ASAP.
New Stuff
First take a look at this line you had originally posted ala GitHub:
java -jar build/libs/file-gateway.jar --spring.config.location=classpath:/apps/conf/ApplicationInsight.xml
Instead the value should be just a folder path, without "classpath" of "file" prefix. Also, try using '-D' instead of '--'.
java -jar build/libs/file-gateway.jar -Dspring.config.location=/apps/conf/
The property is supposed to either refer to a directory containing auto configuration property files for Spring Boot. It can also work for referring to a specific "application.properties|yml" file.
With that, my previous suggestion may work for you.
Old Suggestion
If you require a unique way for loading resources, you can add a resource handler to your application.
#Configuration
#EnableWebMvc
public class MvcConfig extends WebMvcConfigurerAdapter {
#Value("${telemetry.folder}")
private String telemetryFolder;
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceLocations(telemetryFolder);
}
}
And/or you could load it with apache IO:
#Value("${telemetry.file}")
private String telemetryFile;
#Autowired
private ResourceLoader resourceLoader;
public String telemtryXml(){
return org.apache.commons.io.IOUtils.toString(resourceLoader.getResource(telemtryFile).getInputStream());
}
But this will only work if the api you are using doesn't need to be initialized much earlier.
More New Stuff
In your last post on the GitHub issue, you tried this:
java -jar build/libs/file-gateway.jar -applicationinsights.configurationDirectory="/apps/conf/"
Instead, try adding the property as a jvm parameter like this:
java -jar build/libs/file-gateway.jar -Dapplicationinsights.configurationDirectory=/apps/conf/
Notice that I added a capital 'D' character after the, and I removed the quotes from the path.
Other ways to add the file to classpath are.
Add the directory to the JVM classpath.
java -cp "build/libs/file-gateway.jar:/apps/conf/*" your.package.MainSpringBootApplication
This requires that you specify the main class which is (commonly) annotated with '#SpringBootApplication' and contains the main method. You do not execute the jar like before, but you do still add it to the classpath.
Forget about SpringBoot, and go back to your roots as a JEE developer. Add a "context.xml" for your app under the "src/main/resources/META-INF" folder, or "src/main/webapp/META-INF". I prefer the later if I'm building an executable war file, and the former for jars.
Example context.xml:
<?xml version='1.0' encoding='utf-8'?>
<!-- path should be the context-path of you application.
<Context path="/">
<Resources className="org.apache.catalina.webresources.StandardRoot">
<PreResources base="/apps/conf"
className="org.apache.catalina.webresources.DirResourceSet"
internalPath="/"
webAppMount="/WEB-INF/classes"/>
</Resources>
</Context>
You can also use JVM parameters with EL.
So if you execute the jar with this:
java -jar build/libs/file-gateway.jar -Dapplicationinsights.configurationDirectory=/apps/conf/
You could set the resources base with this:
<!--snip -->
<PreResources base="${applicationinsights.configurationDirectory}"
<!--snip -->
Hope that helps:)
I have a simple SpringBoot application with the following structure:
I'm using a standard application.yml file where I'm storing all the necessary props and use #ConfigurationProperties annotation to inject them where necessary.
Now for one bean I have quite a lot of props and I don't want to overwhelm my common application.yml file with all that props. So I want a separate one (which I placed under service dir in classpath).
According to Spring docs I can use something like:
java -jar myproject.jar --spring.config.location=classpath:/service/application.yml
But that's not working, I got NullPointer which means property was not injected.
What Am I doing wrong? How can I use another *.yml file together with application.yml?
P.S. I know I could place it under the config folder in classpath, but what if I need two custom files?
If you have 2 configs in different places, spring.config.location will accept a comma separated list of those locations
--spring.config.location=classpath:/resources/,classpath:/service/
You could also just call the other file like "config.yml" and then use a different name
--spring.config.name=application,config
I'm using Sprint Boot, and would like to have multiple profile specific property files. The docs state:
In addition to application.properties files, profile specific
properties can also be defined using the naming convention
application-{profile}.properties.
http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-external-config-profile-specific-properties
However I have multiple properties files (e.g. db.properties). I'm loading currently load this non-profile specific file as:
#Configuration
#PropertySource( {"classpath:db.properties"} )
class DataSourceConfig {
#Value("db.server") String server;
...
}
How can I combine these two things together, so it loads db-dev.properties like Spring Boot does for application.properties
It sounds like it should be easy, but I can't work out how to do it?!
Java -jar my-spring-boot.jar --spring.profiles.active=test you can set profile.active=your environment via commandline
I just saw that you use #PropertySource. The docs say:
Profile specific variants of both application.properties (or application.yml) and files referenced via #ConfigurationProperties are considered as files are loaded.