How to load all .yml files from resources directory at the time of application startup in spring? - spring

I have 2-3 .yml files in resources directory in a spring application.
I want to load all these files at the application startup automatically.
I tried below code but did not work.
ConfigurableApplicationContext applicationContext = new SpringApplicationBuilder(YamlLoadApplication.class)
.properties("spring.config.name:applicationTest,CountriesData",
"spring.config.location:src/main/resources/")
.build().run(args);
ConfigurableEnvironment environment = applicationContext.getEnvironment();
MutablePropertySources sources = environment.getPropertySources();
Please help me to solve this. What is the best way to achive this? I would be using all these yml files values throughout the application.
Thanks

You can use #PropertySource annotation to externalize your configuration to a properties file.
Spring recommends using Environment to get the property values.
env.getProperty("mongodb.db");
You can mention the property files which are using in the class.
#Configuration
#PropertySource({
"classpath:config.properties",
"classpath:db.properties"
})
public class AppConfig {
#Autowired
Environment env;
}
From Spring 4 you can ignoreResourceNotFound to ignore the not found properties file
#PropertySources({
#PropertySource(value = "classpath:missing.properties", ignoreResourceNotFound=true),
#PropertySource("classpath:config.properties")
Examples are from the article - https://www.mkyong.com/spring/spring-propertysources-example/
Refer the article if you need more information
From Spring documentation

One issue here "spring.config.location:src/main/resources/" sets spring.config.location to src/main/resources/ which is not a class path resource but a file system resource. This is looked up from the current directory you're running your Spring Boot application from.
Several fixes:
Specify a full file system path like this:
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext;
applicationContext = new SpringApplicationBuilder(YmlsApplication.class)
.properties("spring.config.name:applicationTest,CountriesData",
"spring.config.location:/Users/msimons/tmp/configs/")
.build().run(args);
ConfigurableEnvironment environment = applicationContext.getEnvironment();
MutablePropertySources sources = environment.getPropertySources();
sources.forEach(p -> System.out.println(p.getName()));
}
Or specify a classpath resource. Notice that I put the config files under a separate directory, which lives in src/main/resources/custom-config:
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext;
applicationContext = new SpringApplicationBuilder(YmlsApplication.class)
.properties("spring.config.name:applicationTest,CountriesData",
"spring.config.location:classpath:/custom-config/")
.build().run(args);
ConfigurableEnvironment environment = applicationContext.getEnvironment();
MutablePropertySources sources = environment.getPropertySources();
sources.forEach(p -> System.out.println(p.getName()));
}
Notice classpath: inside the path and also starting the directory at the root level of resources with /.

Related

Failed to configure a DataSource from command line

I'm trying to change Datasource setting from command Line. I have a application.properties with default setting. I would like to modify the parameters in the file from command Line, but when I pass Datasource arguments , I receive an error. I read on Externalized Configuration document :"Accessing Command Line Properties
By default, SpringApplication converts any command line option arguments (that is, arguments starting with --, such as --server.port=9000) to a property and adds them to the Spring Environment. As mentioned previously, command line properties always take precedence over other property sources".
I supposed that arguments overwrite the default setting into application.properties, but I'm missng some steps about that.
I've tried without spring.datasource.url or Placeholders in Properties. Below application.properties.
spring.datasource.url = jdbc:oracle:thin:#servername:port:DB11G
#spring.datasource.url = ${spring.datasource.url}
spring.datasource.driver.class=oracle.jdbc.driver.OracleDriver
spring.datasource.username = dbUser
spring.datasource.password = password
My application with datasource default settings run well.
this is my code:
spring.datasource.url = ${db.url}
spring.datasource.driver.class=oracle.jdbc.driver.OracleDriver
spring.datasource.username = dbUser
spring.datasource.password = dbPassword
Main class
#SpringBootConfiguration
public class IdsFeApplication implements ApplicationRunner{
private static final String FEC_CODEX = "A";
#Autowired
private static ConfigInfoDB infoDb;
#Autowired
private Login fec;
public static void main(String[] args) throws InterruptedException {
SpringApplication bootApp = new SpringApplication(IdsFeApplication.class);
bootApp.setBannerMode(Banner.Mode.OFF);
bootApp.setLogStartupInfo(false);
ConfigurableApplicationContext context = bootApp.run(args);
ConfigInfoDB db=context.getBean(ConfigInfoDB.class);
db.dbInfo();
}
#Override
public void run(ApplicationArguments args) throws Exception {
// TODO Auto-generated method stub
fec.token(FEC_CODEX);
}
}
Change your top annotation from #SpringBootConfiguration to #SpringBootApplication.
#SpringBootApplication in reality is a shortcut for #configuration, #EnableAutoConfiguration and #ComponentScan.
https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-using-springbootapplication-annotation.html
#EnableAutoConfiguration does a lot of the magic behind the scenes of configuring your application based on what dependencies are included and what information it finds in the environment.

How to programmatically tell `Spring Boot` to load configuration files from `custom location` when doing JUNIT Test

How to programmatically tell Spring Boot to load configuration yaml files from custom location when doing JUNIT Test.
In program, I could use properties of SpringApplicationBuilder to specify my custom yaml file .
#Configuration
#SpringBootApplication
#ComponentScan
public class SampleWebApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = new SpringApplicationBuilder(SampleWebApplication.class)
.properties("spring.config.name:application,conf",
"spring.config.location=classpath:/viaenvironment.yaml")
.build().run(args);
ConfigurableEnvironment environment = applicationContext.getEnvironment();
System.out.println(environment.getProperty("app.name"));
}
}
When doing JUNIT Test, how should I configure it?
I'm using spring boot 1.5.1.
Please use this option to set the spring.config.location through #TestPropertySource:
#TestPropertySource(properties = { "spring.config.location = classpath:<path-to-your-yml-file>" }

Unable to load external properties in Spring Boot

I have a very basic spring boot command line app into which I am trying to load properties from an application.yml file that is present inside my project. The project is built using gradle and I am using groovy as the language.
Now wherever I place the application.yml file, I can't seem to be able to assign its values to the configuration properties bean. The files are as below
application.yml
my:
name: "some name"
servers:
- dev.bar.com
- foo.bar.com
Config.groovy
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.context.annotation.Configuration
#Configuration
#ConfigurationProperties(prefix = "my")
public class Config {
private List<String> servers = new ArrayList<String>();
private String name
public List<String> getServers() {
return this.servers;
}
public String getName() {
return this.name
}
}
Worker.groovy The Command line runner
#Component
class Worker implements CommandLineRunner {
#Autowired
Config config
#Override
public void run(String... args) throws Exception {
println "Running a test app"
println config.name
println config.getServers()
}
}
Directory Structure
app-name
-build.gradle
-src
-main
-groovy
-config
-application.yml
-com
-company
-app
Worker.groovy
Config.groovy
Application.groovy
I also tried renaming application.yml to application.properties as well as adding it under the com.company.app project, but the worker class's run method always prints the property as null. I believe I may have missed something very basic, but can't seem to find what it has.
Let me know if I need to provide any additional details.
application.yml should go under src/main/resources/config.
Resources are processed (copied) from src/main/resources directory.
By default the groovy plugin ignores other than groovy classes in src/main/groovy.

Spring Boot WS application cannot load external property

In my Spring-Boot Web Service application, I want to load a property named appName with value defined in application.properties.
#Endpoint
public class RasEndpoint {
private static final String NAMESPACE_URI = "http://www.mycompany.com/schema/ras/ras-request/V1";
#Value("${appName}")
private String appName;
#PayloadRoot(namespace = NAMESPACE_URI, localPart = "getProductRequest")
#ResponsePayload
public GetProductResponse getProduct(#RequestPayload GetProductRequest request) {
System.out.println("appName: " + appName);
GetProductResponse response = generateStubbedOkResponse();
return response;
}
application.properties has the following entry
appName=ras-otc
I get the application started via the main Application class as shown below
#Configuration
#ComponentScan
#EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
However, when I run the app, I get the following error
Caused by: java.lang.IllegalArgumentException: Could not resolve
placeholder 'appName' in string value "${appName}"
Do you guys know what I'm doing wrong?
Appreciate any help.
As Dave mentioned in the comment above, the properties file was not loaded into the classpath.
The properties file was located in /src/main/resources folder, which was added to source, under build path in Eclipse IDE, however had an exclusion rule applied which prevented the properties file from being loaded into the classpath. By removing the exclusion, I was able to load the properties correctly.

How to externalize application.properties to an external filesystem location in Spring Boot?

#ComponentScan
#EnableAutoConfiguration
#PropertySource(value = { "file:/Users/Documents/workspace/application.properties" })
public class Application extends SpringBootServletInitializer{
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
}
In this case it gives while deploying:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.jdbc.core.JdbcTemplate] found for dependency:
Not able to find the correct way to externalize the application properties file
I tried autowiring environment variable which is correctly loaded but then I need to manually define all the beans
#Bean
public JdbcTemplate dataSource() {
String driverClassName = env
.getProperty("spring.datasource.driverClassName");
String dsUrl = env.getProperty("spring.datasource.url");
String username = env.getProperty("spring.datasource.username");
String password = env.getProperty("spring.datasource.password");
//DataSource dataSource = new SimpleDriverDataSource(new driverClassName, dsUrl, username, password);
JdbcTemplate jdbc = new JdbcTemplate(dataSource);
return jdbc;
}
This deploys without throwing error but not responding.
If you're deploying a WAR to Tomcat, then you need to define a context XML as described here: https://tomcat.apache.org/tomcat-7.0-doc/config/context.html#Defining_a_context
For example, you would typically define $CATALINA_BASE/conf/Catalina/localhost/my-app.xml if you have http://localhost:8080/my-app/.
The file would then look like this:
<Context docBase='path/to/my-app/my-app.war'>
<Environment name='app_config_dir' value='path/to/my-app/' type='java.lang.String'/>
</Context>
In your code, implement ApplicationContextAware and override setApplicationContext. Here is an example:
public class Setup implements ApplicationContextAware {
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
log.info("Set application context. App Config Property: {}",applicationContext.getEnvironment().getProperty("app_config_dir"));
}
}
You can now load the properties file from app_config_dir.
There is no need to define it by using #PropertySource annotation. You should just use spring.config.location property to set your application.properties location. That property can be set up for example in command line:
java -jar myapp.jar --spring.config.location=/Users/Documents/workspace/
You can define an environment variable called SPRING_CONFIG_LOCATION and give it a value that can be a folder (which should end in /) or a file. In any case the location should pe prefixed with file::
SPRING_CONFIG_LOCATION = file:C:/workspace/application.properties
or
SPRING_CONFIG_LOCATION = file:C:/workspace/
More about this here.
You can use #PropertySource too because it is useful when you are deploying application as war file to tomcat.
#PropertySource is not working because you are missing #Configuration annotation. As per the Spring-Boot documentation, #PropertySource annotations should be present on your #Configuration classes.
Following works
#Configuration
#ComponentScan
#EnableAutoConfiguration
#PropertySource(value = { "file:/Users/Documents/workspace/application.properties" })
public class Application extends SpringBootServletInitializer{
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
}
You can also load multiple properties file. For ex:
#PropertySource(value = {"classpath:application.properties", "file:/Users/overriding.propertis"}, ignoreResourceNotFound = true)
Note that the order of the declared files is important. If the same key is defined in two or more files, the value associated with the key in the last declared file will override any previous value(s).

Resources