Reputation: 452
I have a Spring Boot application that uses 3rd-party jar. This jar requires an xml config file, that must be provided by clients on runtime (individually) and cannot be pre-packaged. 3rd party lib loads that file using below sequence (I stripped if
s and null-checks):
FileConfigurator.class.getResource("/" + filename);
Thread.currentThread().getContextClassLoader().getResource("/" + filename);
Thread.currentThread().getContextClassLoader().getResource(filename);
I cannot change the way that lib loads the file (e.g. using Spring's Resource loading), so it must be on classpath. Therefore I seem to lose the possibility of executing it like java -jar my-spring-boot-app.jar
, because -jar
option prevents any additional classpath entries from being added. So I started running it like
java -classpath my-spring-boot-app.jar:./config/: org.springframework.boot.loader.JarLauncher
My directory structure is following:
|-- config
| |-- application.properties
| `-- 3rd-party-config.xml
|-- my-spring-boot-app.jar
But then Spring's autowiring started to fail: Additional application.properties
file in config directory overrides some of settings and using above command causes app startup to fail:
Error creating bean with name 'ORBConfig': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.lang.String com.company.app.communication.corba.orb.ORBConfig.serverName; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'application.corba.serverName' in string value "${application.corba.serverName}"
Field String serverName
is annotated with @Value("${application.corba.serverName}")
, the property is defined in application.properties
file bundled within JAR and value injection works fine when additional application.properties
is not present in config dir.
My actual question is: what is the advisable way of deploying and/or running Spring Boot application, to take advantage of executable Jar feature, provide additional classpath resources on runtime and still be able to override some (but not all) properties by classpath application.properties
file?
Application is packaged using spring boot maven plugin and uses spring-boot-starter-parent
parent POM.
Upvotes: 3
Views: 3947
Reputation: 3620
One simple answer if you won't change the startup command:
move
./config/application.properties
to./config/config/application.properties
If there exist more than one classpath resources with same name, Spring Boot will load only one of them, in you case, Spring Boot load and prioritize property resources as following:
file:config/application.properties
classpath:application.properties
which maybe resolved to either my-spring-boot-app.jar!/applcation.properties
or ./config/application.properties
If your classLoader chosen ./config/application.properties
as second property source. Bang!
Spring Boot's default configuration property resource path priority (highest to lowest precedence) is:
file:config/
file:
classpath:config/
classpath
The ordinary executable jar execution make those two configuration property fall into:
file:config/application.properties
classpath:application.properties
(from jar)And moving ./config/application.propertie
to './config/config/application.properties' becomes:
classpath:config/application.properties
classpath:application.properties
(from jar)Both in the same order and have no ambiguous.
Upvotes: 0