I need to load a property from a .yml file, which contains the path to a folder where the application can read files from.
I'm using the following code to inject the property:
#Value("${files.upload.baseDir}")
private String pathToFileFolder;
The .yml file for development is located under src/main/resources/config/application.yml, im running the application with the following command in production, to override the development settings:
java -jar app.jar --spring.config.location=/path/to/application-production.yml
The Spring Boot documentation says:
SpringApplication will load properties from application.properties files in the following locations and add them to the Spring Environment:
A /config subdirectory of the current directory.
The current directory
A classpath /config package
The classpath root
As well as:
You can also use YAML ('.yml') files as an alternative to '.properties'.
The .yml file contains:
{...}
files:
upload:
baseDir: /Users/Thomas/Code/IdeaProjects/project1/files
{...}
And my Application class is annotated with:
#SpringBootApplication
#EnableCaching
When I run the application, i get an exception:
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'files.upload.baseDir' in string value "${files.upload.baseDir}"
Do I have to use the YamlPropertySourceLoader class or add a special annotation to enable the support for .yml in Spring Boot?
Edit:
The .yml file contains some other properties, which get successfully loaded by Spring Boot like dataSource.XXXor hibernate.XXX.
For example: application.yml
key:
name: description here
Your Class:
#Value("${key.name}")
private String abc;
M. Deinum is right, the setup i've provided is working - the yml file was indented wrong, so the property couldn't be found.
I found the above wasn't working for me, because I tried to access the variable in a constructor. But at construction, the value is not injected yet.
Eventually I got it to work using this workaround: https://mrhaki.blogspot.com/2015/04/spring-sweets-using-value-for.html
Maybe this is helpful to others.
For me a duplicate key in the property file caused this...
I used same key unknowingly in large yml file.
key:
key1: value
key2: value
key:
key3: value
In yml properties file :
xxxx:
page:
rowSize: 1000
Create your Yaml properties config class :
#Configuration
#EnableConfigurationProperties
#ConfigurationProperties(prefix = "xxxx")
public class YmlPropertiesConfig {
private Page page;
public Page getPage() {
return page;
}
public void setPage(Page page) {
this.page = page;
}
public class Page {
private Integer rowSize;
public Integer getRowSize() {
return rowSize;
}
public void setRowSize(Integer rowSize) {
this.rowSize = rowSize;
}
}
}
Finally get it and use it :
public class XXXXController {
#Autowired
private YmlPropertiesConfig ymlProperties;
public String getIt(){
Integer pageRowSize = ymlProperties.getPage().getRowSize();
}
}
I've got that issue Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder cause I've set test spring boot profile in properties.yaml.
Spring can't find properties for test profile when run app with no profile.
So remove spring boot profile from properties or yaml or run app with enabled profile.
Configuration file example is below:
#Configuration
public class AppConfig {
#Value("${prop.foo}")
private String foo;
#Value("${prop.bar}")
private String bar;
#Bean
BeanExample beanExample() {
return new BeanExample(foo, bar);
}
}
For those who have problems with a #RestController, I do it as follows:
#Autowired
#Value("${google.recaptcha}")
private String keyRecaptcha;
My properties file was mistakenly named applcation.properties as it was auto-generated by the Spring initializer. But I added the properties there in the .yml format and they were not retrieved with the same error.
When I renamed the file to application.yml, it started working.
Related
I want to set both property file (myproperty.properties) and log file location (myLogFile.log) through my own environment variable name (MYENV for example).
property file name must be different from spring boot application.properties name and log file has its own name also.
Do not want to use spring.config.name and spring.config.location.
MYENV will be set to "/locationFiles" value for example. myproperty.properties file location is "/locationFiles/config"
and myLogFile.log file location is "/locationFiles/log".
I know that I can use the following code snippet for reading my environment variable.
But How do I use propertiesLocation below to read the properties data in a simple Spring boot way?
I do not know how to define a corresponding java configuration class as It seems that configuration ppties file path cannot be set in a variable.
import org.springframework.core.env.Environment;
public class MyClass {
#Autowired
private Environment env;
String propertiesLocation;
private void propertyLocation() {
this.propertiesLocation = env.getProperty("MYENV")+"/config/";
}
}
The following code snippet does not match with what I want to do as I cannot
write something like that : #PropertySource(env.getProperty("MYENV")+"/config/")
#SpringBootApplication
#PropertySource("classpath:myproperty.properties")
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
I saw Environment Specific application.properties file in Spring Boot application but I does not match exactly with what I've described above.
As I want to define my own environment variable name and file names.
And I'm also looking for another way than using java -jar -Dspring.config.location=<path-to-file> myBootProject.jar as defined in Spring boot how to read properties file outside jar.
I want to know if there is an alternative way to this method.
I have this configurations which needs to be used for a spring boot application.
server.port=8085
server.servlet.context-path=/authserver
#data source
spring.jpa.hibernate.ddl-auto=none
spring.datasource.url=<url>
spring.datasource.username=<username>
spring.datasource.password=<password>
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
By default spring-boot picks up up the application.properties file located in src/main/resources/
I want to alter this path and direct spring boot to different application.properties file
I can achieve this using
java -jar app.jar --spring.config.location=classpath:/another-location.properties
Is there any any alternative solution I can achieve this without passing args through command line?
I was using this
#PropertySource("file:C:\Users\test\.test\test.properties")
#ConfigurationProperties(prefix = "spring")
public class Configuration {
private String ddlAuto;
private String url;
private String username;
private String password;
private String driverClassName;
}
in my Main class
#SpringBootApplication
#EnableConfigurationProperties(Configuration.class)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
There after I tried executing the app commenting out all datasource properties in application.properties under src/main/resources/
But it keeps giving me the error mentioned bellow and application fails to start
I was referring this tutorial : https://www.mkyong.com/spring-boot/spring-boot-configurationproperties-example/
but as it's mentioned I get this error when i start the spring boot application
***************************
APPLICATION FAILED TO START
***************************
Description:
Binding to target org.springframework.boot.context.properties.bind.BindException:
Any help on this would be appreciated
The recommended way to have externalized properties is to use the spring.config.location system property, by starting your application like so:
java -jar -Dspring.config.location=/path/to/my/file.properties app.jar
The reason for this is that you don't add coupling between your code and your filesystem hierarchy.
Before Spring Boot 2.0 this property is additive, meaning that it will complement the default locations. After Spring Boot 2.0, spring.config.location replaces the default locations (e.g. classpath src/main/resources/application.properties). To keep the additive behaviour after 2.0, use spring.config.additional-location instead.
Please see here for official documentation on this matter.
I am able to make it work properly on Spring Boot 2.1.2.RELEASE. This is what I have done:
I have a test.properties in my /tmp folder with the following content:
test.myprop=hello
I also have the usual property file in the resources folder:
myprop=world
I have created a class for the custom property file:
#Configuration
#PropertySource("file:/tmp/test.properties")
#ConfigurationProperties(prefix = "test")
public class TestConfig {
private String myprop;
public String getMyprop() {
return myprop;
}
public void setMyprop(String myprop) {
this.myprop = myprop;
}
}
And then in my main class I have enabled to configuration properties:
#EnableConfigurationProperties(TestConfig.class)
#SpringBootApplication
public class MyApp {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
}
Now I have this test controller:
#RestController
public class TestController {
#Value("${test.myprop}")
private String externalisedProp;
#Value("${myprop}")
private String prop;
#GetMapping("test")
public void test() {
System.out.println("externalised: " + externalisedProp);
System.out.println("not externalised" + prop);
}
}
Which, once called, is properly printing:
externalised: hello
not externalised: world
My TestConfig class is in the same package as the MyApp main class.
What I have done is very similar, almost identical, to your solution, are you sure your path is correct? Also, I can see that the content of your property file is not matching what you have in your config class, the prefix is different. Maybe that is the problem?
Edit:
I have tried to remove the #Configuration annotation from my property class (which you do not have as well) and it is not able to pick up the externalised properties anymore. The error is different though but you should try to add it.
I have multiple projects in which I am trying to read application.properties file from one particular project. There's one web application which I am deploying on tomcat. I want to use application.properties from another project.
I tried to import appconfig.java from that project to webAppconfig.java.
application.properties file in 1st project src/main/resources/application.properties contains driver=org.postgresql.Driver
1st project : Appconfig.java
#Configuration
#PropertySource("classpath:application.properties")
public class Appconfig{
#Value("${driver}")
private String test;
}
2nd project : WebAppconfig.java
#Import(Appconfig.java)
public class WebAppconfig{
}
I was expecting test=org.postgresql.Driver
but I am getting exception as key "driver" not found.
If I change application.properties to something.properties, it works.
I tried following ways:
a)
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
b) tried changing in build path as included, excluded as shown in image
c)I tried autowiring environment as well.but is didn't work..
I debugged environment variable ..under property sources.it shows{spring.application.name="project 2 name"}
Situation
I have a fat .jar of a Spring boot application. I've externalized my configuration with an application.properties file. This file is in the same folder as the .jar, and I'm starting the .jar from the command line from within the same folder (with the command "java -jar $jarFileName").
Then an exception is thrown:
nested exception is org.springframework.beans.TypeMismatchException:
Failed to convert value of type 'java.lang.String' to required type 'int'; nested exception is
java.lang.NumberFormatException: For input string: "${elasticsearch.port}"
As you can see, instead of reading the value from the properties file, it just sets the string as the text in the #Value annotation, which looks like this:
#Value("${elasticsearch.port}")
private int elkPort;
The class this happens in is annotated with #Component.
According to Spring docs: externalized configuration, spring should read an application.properties file outside of the jar.
When the same application.properties file is placed in src/main/resources it works fine, so the configuration file seems correct.
Any ideas why it won't load the external configuration file?
EDIT 1
I've also tried running it with --spring.config.location=file:application.properties and --spring.config.location=file:/full/path/to/application.properties but with the same result as above.
EDIT 2: classpath attempt
Also tried classpath instead of file, the same as the commands above but file replaced with classpath.
Lastly tried without either, so just --spring.config.location=/path/to/file; again both with relative and full path to the application.properties. All attempts gave the same result/exception.
EDIT 3
My annotated application:
#SpringBootApplication
public class ApplicationName {
public static void main(String[] args) {
SpringApplication.run(ApplicationName.class, args);
}
}
EDIT 4
Tried adding a PropertySourcesPlaceholderConfigurer as follows:
#Configuration
public class PropertyConfig {
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
And then for each #Value I added a default value; it still only resolves to the default values instead of to the application.properties values.
Alright after quite some struggles, I've found the solution. I was close with PropertySourcesPlaceholderConfigurer but not quite there yet; this is the full class now:
#Configuration
public class PropertyConfig {
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
final PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();
ppc.setIgnoreResourceNotFound(true);
final List<Resource> resources = new ArrayList<>();
resources.add(new FileSystemResource("relative/path/to/application.properties"));
ppc.setLocations(resources.toArray(new Resource[]{}));
return ppc;
}
}
EDIT
To demonstrate the issue, I've created a repository to show the problem, see here: https://github.com/Locitao/test-external-properties
As it says on mentioned page, you should specify external config location
$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
Try without file keyword
--spring.config.location=/full/path/application.properties
I just took my application.properties out of an Eclipse Spring Boot project and it failed.
Then I put the file in a cfg folder in the root of the project and added program argument:
--spring.config.location=cfg/application.properties
and it worked again. Mayby if you try a relative path (no leading /) to the file (without the "file:") it will work.
In an application ther are multiple properties file for managing exception messages , alerts , and some others text these file like this :
- core-message.properties
- databaseException.properties
......
in Service layer maybe a database call occure and the database return a key that exist in one the properties files , and i want get the value and raise the exception messsage to user interface layer .
if i know that the key in wich properties file the code will be like this :
#Value("#{core['theExceptionKey']}")
public String excpetionMessage;
private void myMethod() {
throw new ExceptionClass(exceptionMessage);
}
i think spring can do that because when i use spring:message tag in jsp files spring does not know the key in witch file but it load the message correctly.
You can use Spring Environment abstraction for that.
First you need to add Property Source to your Java Configuration file
#Configuration
#PropertySource("classpath:/com/mypacakge/core-message.properties")
public class AppConfig {
Or if you have multiple properties files
#Configuration
#PropertySources({
#PropertySource("classpath:core-message.properties"),
#PropertySource("classpath:database.properties")
})
public class AppConfig {
Add PropertySourceConfigurer to to your Java Configuration file
#Bean
public static PropertySourcesPlaceholderConfigurer placeHolderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
Now let's say that in your core-message.properties you have the following data
message.name=Hello
You can retrieve this data in any bean by autowiring Environment abstraction and then calling env.getProperty()
#Autowired
Environment env;
public void m1(){
String message = env.getProperty("message.name")` // will return Hello
Environment object provides interface to configure property sources and resolve properties. It provides convenience to read from a variety of sources: properties files, system environment variable, JVM system properties, servlet context parameters, and so on, which is very useful. For example :
environment.getSystemProperties().put("message", "Hello");
System.getProperties().put("message", "Hello");
environment.getSystemProperties().get("message"); // retrieve property
environment.getPropertySources() // allows manipulation of Properties objects
Spring Reference Documentation - Environment
To get the value of the key programmatically you can use the following:
#Autowired
private Environment env;
...
String something = env.getProperty("property.key.something");