Spring boot - multi module project multiple application.properties - spring

I have a multi module spring-boot maven project. The parent-project do not have any code or property file, but has spring-boot, test & basic library dependencies configured.
The entity-project inside this that has entities, database configurations & flyway migrations - all configured in its own entity.yml file.
Another sibling rest-project inside this has REST api codes & its own property file rest.yml. This project is dependent on the entity-project. As there can only be one application.yml, I renamed each differently to avoid conflict.
However, rest-project doesn't load the database configurations without explicitly including the entity-project property file, like below
#SpringBootApplication
#PropertySources({ #PropertySource(value = { "classpath:entity.yml" }) })
public class CommandServiceApplication { ... }
Is this is only way to configure, or am I misconfiguring it?

Related

In which class in the source code of spring-boot or spring is the application.yml or application.properties file processed?

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 !

How do I create a CLI utility that shares code with the my Spring Boot application without pulling in everything?

I have a Kotlin Spring Boot application and want to add a little command line utility. The utility is not needed to build the application, it's just an internal tool that shares code with the application. In particular, it uses s a Client class which in turn depends on a Configuration (initialized with values from application.yml) and some external dependencies.
How can I run this utility app without pulling in all of Spring Boot? For example, I don't want the JDBC driver and any web service clients.
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
fun main(vararg args: String) {
runApplication<TheUtility>(*args)
}
#SpringBootApplication
class TheUtility(private val client: TheClient) {
fun run(args: Array<String>) {
// code goes here
}
}
TheClient.kt uses some external libraries defined as project dependencies, plus a configuration:
#Component
#Configuration
class TheClient(
private val config: TheConfig,
#Value("classpath:more-config.json") private val json: Resource
) {
// ...
}
TheConfig.kt:
#ConfigurationProperties(prefix = "my-settings")
data class TheConfig(
var fromApplicationYml: String = ""
}
When I run this, I see messages about bootstrapping Spring Data JPA repositories, Kubernetes, Tomcat, and Hibernate... all of which I don't need in my utility.
(I currently have this in the regular src/main/kotlin/... folders. Is there a better place to put the CLI utility, like in an additional source folder? I really only need to have the external dependencies plus the Spring dependency injection for my configuration.)
How do I create a CLI utility that shares code with the my Spring Boot and uses dependency injection, application without pulling in everything?

Different YAML configuration file for junit test using an Externalized configuration in Spring Boot

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" })

Spring Boot profile specific properties

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.

Unable to resolve ${...} in #PropertySource when using Spring boot

I am using Spring's Java configuration to configure my application. Below is a snippet of the annotations. There is no problem with the application deployed to the Tomcat container. The ${CONFIG_PATH} resolves correctly as the CONFIG_PATH is defined in the system/environment properties.
#Configuration
#ComponentScan(excludeFilters = { #Filter(type = FilterType.ANNOTATION, value = { Configuration.class }) })
#PropertySource(value = { "file:${CONFIG_PATH}/app.properties" })
#EnableAutoConfiguration
#EnableMongoRepositories
public class AppConfig { ... }
I recently started using Spring-Boot so that I can build a standalone executable jar with Tomcat embedded. However, now the #PropertySource(value = { "file:${CONFIG_PATH}/app.properties" }) does not work; it results in the following error.
Exception in thread "main" java.lang.IllegalStateException: Resource not found: file:${CONFIG_PATH}/app.properties
My temporary solution is to hardcode the path as follows.
//#PropertySource(value = { "file:${CONFIG_PATH}/app.properties" })
#PropertySource(value = { "file:/usr/local/etc/app.properties" })
I'm still relatively new to the Spring camp. So I'm sure that I'm missing something. I greatly appreciate any help on this problem.
Thanks in advance.
UPDATE 1:
I looked the at the default appplication.properties and found the 4 location given to be wanting. For reasons of clean deployment, properties file should be not located in the classpath. And having the properties file located relative to where the application is located makes it harder to manage the configuration if we have more than one application deployed.
From the Spring Boot README
If you don't like application.properties as the configuration file name you can switch to another by specifying spring.config.name environment property. You can also refer to an explicit location using the spring.config.location environment property.
I would probably just use this startup parameter (in a bootscript or something) to specify the configuration file.
I guess the reason the replacement doesn't work is due to the nature of spring boot. The application context is also used to bootstrap/configure the servlet container and as such the normal rules for #PropertySource probably doesn't apply. You could (or maybe should) register an issue for this.

Resources