I'm trying to learn how to read properties file using spring. After an internet searching I found that I can use @value
and @PropertySource
annotations to achieve that. I created a project which has the following structure and classes codes:
Structure of the project:
AppConfigMongoDB.java implementation:
package com.mongodb.properties;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
@PropertySource("classpath:config/config.properties")
public class AppConfigMongoDB {
@Value("#{mongodb.url}")
private String mongodbUrl;
@Value("#{mongodb.db}")
private String defaultDb;
public String getMongoDb()
{
return defaultDb;
}
public String getMongoDbUrl()
{
return mongodbUrl;
}
}
SpringConfiguration.java implementation:
package com.mongodb.properties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringConfiguration {
@Bean
public AppConfigMongoDB getAppConfigMongoDB(){
return new AppConfigMongoDB();
}
}
Main.java
package com.mongodb.properties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfiguration.class);
AppConfigMongoDB mongo = applicationContext.getBean(AppConfigMongoDB.class);
System.out.println("db= "+mongo.getMongoDb());
System.out.println("URL= "+mongo.getMongoDbUrl());
}
}
The properties file that I'm reading from called config.properties, it contains the following lines:
mongodb.url=1.2.3.4
mongodb.db=dataBase
I tested this small project and I got a stack trace that contains the following exception:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'getAppConfigMongoDB': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.lang.String com.mongodb.properties.AppConfigMongoDB.mongodbUrl; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Property or field 'mongodb' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public?
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1202)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)
at com.mongodb.properties.Main.main(Main.java:9)
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Property or field 'mongodb' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public?
at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:226)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:93)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:81)
at org.springframework.expression.spel.ast.CompoundExpression.getValueRef(CompoundExpression.java:51)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:87)
at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:120)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:242)
at org.springframework.context.expression.StandardBeanExpressionResolver.evaluate(StandardBeanExpressionResolver.java:161)
... 18 more
Is it a problem of Spring calling beans? Or maybe is it a problem of properties file path or something else?
Spring @PropertySource annotation is used to provide properties file to Spring Environment. This annotation is used with @Configuration classes.
To see all properties in your Spring Boot application, enable the Actuator endpoint called env . This enables an HTTP endpoint which shows all the properties of your application's environment.
I can see several issues in the code.
1) Your place holders for values should be in the form ${mogodb.url}
, not #{mongodb.url}
. The "#" has a different meaning (See Spring Expressions).
2) You are going to need a PropertySourcesPlaceholderConfigurer
bean to do the injection of the values
3) Sooner or later you are going to have a number of Beans floating around, and in I would use @ComponentScan
to allow the context to know these without you having to mention them one by one
4) If you use ComponentScan
to get the beans, you are going to have to provide AppConfigMongoDB
bean once
I end up with these classes after doing all that:
Main.java
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfiguration.class);
AppConfigMongoDB mongo = applicationContext.getBean(AppConfigMongoDB.class);
System.out.println("db= "+mongo.getMongoDb());
System.out.println("URL= "+mongo.getMongoDbUrl());
}
}
SpringConfiguration.java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
@Configuration
@ComponentScan
public class SpringConfiguration {
@Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
return new PropertySourcesPlaceholderConfigurer();
}
}
AppConfigMongoDB.java
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource("classpath:config/config.properties")
public class AppConfigMongoDB {
@Value("${mongodb.url}")
private String mongodbUrl;
@Value("${mongodb.db}")
private String defaultDb;
public String getMongoDb() {
return defaultDb;
}
public String getMongoDbUrl() {
return mongodbUrl;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With