Spring Boot #Autowired Environment throws NullPointerException - java

I have a simple SpringBoot application in which i am using the Environment.class to access the properties under application.properties file. The Environment bean works when it is accessed in the main method of the Application.class
#Configuration
#EnableAutoConfiguration
#ComponentScan(basePackages = "com.cisco.sdp.cdx.consumers")
public class StreamingConsumerApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(StreamingConsumerApplication.class, args);
Environment env = context.getBean(Environment.class);
StreamingConsumerFactory factory = context.getBean(StreamingConsumerFactory.class);
StreamingConsumer streamingConsumer = factory.createStreamingConsumer(StreamType.valueOf(env.getRequiredProperty("streaming.application.type")));
streamingConsumer.consume();
}
}
When the same is used in a different class it throws NullPointerException. I tried annotating the class with #Configuration,#Component,#Repository,#Service annotations but did not work.
I tried #Autowired as well as #Resource annotations. But, it didn't work.
#Component
public class InventoryStreamingConsumer implements StreamingConsumer {
#Autowired
private Environment env;
#Autowired
private JavaSparkSessionSingleton sparksession;
#Autowired
private StreamingContext _CONTEXT;
private final Map<String, String> kafkaParams = new HashMap<String, String>();
#Override
public void consume() {
if(env == null) {
System.out.println("ENV is NULL");
}
System.out.println(env.getRequiredProperty("kafka.brokerlist"));
kafkaParams.put("metadata.broker.list", env.getRequiredProperty("kafka.brokerlist"));
Set<String> topics = Collections.singleton(env.getRequiredProperty("kafka.topic"));
// Unrelated code.
}
I tried following the answers provided in the below questions
Spring Boot - Environment #Autowired throws NullPointerException
Autowired Environment is null
I am looking for suggestions on solving the issue.

The #Configuration annotation is misused here for InventoryStreamingConsumer. Try #Component, #Repository or #Service.
UPDATE
Another misuse is
StreamingConsumer streamingConsumer = factory.createStreamingConsumer(StreamType.valueOf(env.getRequiredProperty("streaming.application.type")));
#Autowired or #Resource can only work in bean created by Spring. the streamingConsumer created by your StreamingConsumerFactory factory cannot use #Autowired for injection of its properties.
You should create an #Configuration class, to tell Spring to create streamingConsumer from your factory. Like this
#Configuration
public class ConsumerCreator {
#Autowired
StreamingConsumerFactory factory;
#Bean
public StreamingConsumer streamingConsumer() {
return factory.createStreamingConsumer(StreamType.valueOf(env.getRequiredProperty("streaming.application.type")));
}
}
And use no annotation for InventoryStreamingConsumer, meanwhile use
StreamingConsumer streamingConsumer = context.getBean(StreamingConsumer.class);
in your StreamingConsumerApplication.main() method instead to retrieve streamingConsumer

First, please annotate the main class with only #SpringBootApplication
#SpringBootApplication
public class StreamingConsumerApplication {
}
#ComponentScan is required if your packages are not within the same structure as main class with main class being outside the sub-package and inside parent package with every other class in the same or some sub-package of parent package.
Second, Please create a Configuration class and annotate it with #Configuration separately and define a #Bean there for StreamingConsumer streamingConsumer and than it can be #Autowired or injected in the InventoryStreamingConsumer class.
Third, where is the #Bean for JavaSparkSessionSingleton defined? Are you sure it can be AutoConfigured for injection
Fourth, InventoryStreamingConsumer can be a #Component, injecting Environment with #Autowiring will work once the above things are sorted.
Also, recommending to change your class to this for the sake depending on how consume() method is used.
#Component
public class InventoryStreamingConsumer implements StreamingConsumer {
private final Environment env;
private final JavaSparkSessionSingleton sparksession;
private final StreamingContext _CONTEXT;
private final Map<String, String> kafkaParams = new HashMap<String, String>();
#Autowired
public InventoryStreamingConsumer(Environment env, JavaSparkSessionSingleton sparkSession, StreamingContext context) {
this.env = env;
this.sparksession = sparkSession;
this._CONTEXT = context;
}
#Override
public void consume() {
if(env == null) {
System.out.println("ENV is NULL");
}
System.out.println(env.getRequiredProperty("kafka.brokerlist"));
kafkaParams.put("metadata.broker.list", env.getRequiredProperty("kafka.brokerlist"));
Set<String> topics = Collections.singleton(env.getRequiredProperty("kafka.topic"));
// Unrelated code.
}

I have similar issue but read the properties from different file and different location like common/jdbc.properties. I solved this issue by doing this:
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.env.Environment;
#Configuration
#PropertySource(value = {"classpath:common/jdbc.properties"})
public class ExternalConfig implements EnvironmentAware {
private Environment environment;
public void setEnvironment(Environment environment) {
this.environment = environment;
}
#Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
return new PropertySourcesPlaceholderConfigurer();
}
public String getJdbcUrl() {
return environment.getProperty("jdbc.url");
}
}

Try adding
#PropertySource("classpath:application.properties")
on InventoryStreamingConsumer class
This is how am using it
#Configuration
#ComponentScan({ "com.spring.config" })
#EnableTransactionManagement
#PropertySource("classpath:application.properties")
public class HibernateConfiguration {
private static final String PROPERTY_NAME_DATABASE_DRIVER = "db.driver";
private static final String PROPERTY_NAME_DATABASE_PASSWORD = "db.password";
private static final String PROPERTY_NAME_DATABASE_URL = "db.url";
private static final String PROPERTY_NAME_DATABASE_USERNAME = "db.username";
private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";
#Autowired
private Environment env;
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
dataSource.setUrl(env.getRequiredProperty(PROPERTY_NAME_DATABASE_URL));
dataSource.setUsername(env.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME));
dataSource.setPassword(env.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));
return dataSource;
}

Related

#Autowire Not Setting DAO

I have the following Spring Java configuration set up:
#Configuration
public class FooConfig {
#Autowired
private IReferenceDataDAO referenceDataDAO;
#Bean
public IReferenceDataService getReferenceDataService() {
return new ReferenceDataServiceImpl(referenceDataDAO);
}
}
I am trying to reference the ReferenceDataService bean in another configuration class using the #Autowire property:
#Configuration
public class BarConfig {
#Autowired
private IRuleService ruleService;
#Autowired
private IReferenceDataService referenceDataService;
}
Here is the config that defines the IReferenceDataDAO:
#Configuration
public class FooBarConfig {
#Bean
public IReferenceDataDAO getReferenceDataDAO() {
return new ReferenceDataDAOImpl(getStaticData(), getMapper());
}
}
Here is the ReferenceDataServiceImpl:
public class ReferenceDataServiceImpl implements IReferenceDataService {
private IReferenceDataDAO dao;
public ReferenceDataServiceImpl(IReferenceDataDAO dao) {
this.dao = dao;
}
The above configs are imported in a master config class:
#Configuration
#Import({
FoosAppConfig.class,
BarAppConfig.class,
FooBarAppConfig.class,
})
I am noticing that this configuration leads to the referenceDAO in the ReferenceDataServiceImpl being set to null. What am I doing wrong? Shouldn't that #Autowire annotation ensure that my bean is fully configured before setting it?
BarConfig needs to import FooConfig
#Import({ FooConfig.class })
Try this:
#Configuration
#Import({ FooConfig.class })
public class BarConfig {
#Autowired
private IRuleService ruleService;
#Autowired
private IReferenceDataService referenceDataService;
}
This allows BarConfig to get access to the IReferenceDataService bean.

spring-boot properties not #Autowired

I am trying to get a Spring-boot application going and I am not sure what I am doing wrong here. I have a application.properties file at src/main/resources & src/test/resources. I have an #Bean for my ConfigurationSettings so that I can use them throughout my application:
#Component
public class ConfigurationSettings {
private String product;
private String version;
private String copyright;
private String appName;
private String appDescription;
...
// getters and setters
}
Here is how I kick the application off:
#Configuration
#EnableJpaRepositories
#EnableAutoConfiguration
#EnableConfigurationProperties
#PropertySources(value = {#PropertySource("classpath:application.properties")})
#ComponentScan(basePackages = "com.product")
#EnableScheduling
public class OFAC {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run( OFAC.class, args );
}
And here is my configuration class:
#Configuration
#ComponentScan(basePackages = {"com.product"})
#PropertySources(value = {#PropertySource("classpath:application.properties")})
public class OFAConfiguration {
#Autowired
private Environment env;
#Bean
public ConfigurationSettings configurationSettings() {
ConfigurationSettings configurationSettings = new ConfigurationSettings();
configurationSettings.setAppDescription( env.getRequiredProperty("app.description" ) );
configurationSettings.setAppName( env.getRequiredProperty( "app.name" ) );
configurationSettings.setServerPort( env.getRequiredProperty( "server.port" ) );
return configurationSettings;
}
I am trying to use it in a controller:
#RestController
public class AboutController {
#Autowired
private ConfigurationSettings configurationSettings;
#RequestMapping(value = "/about", method = RequestMethod.GET)
public About index() {
String product = configurationSettings.getProduct();
String version = configurationSettings.getVersion();
String copyright = configurationSettings.getCopyright();
return new About( product, version, copyright );
}
}
However, when step thru this, all the values of ConfigurationSettings are null. I do have a test that successfully loads the values:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {OFAConfiguration.class})
public class OFAConfigurationTest {
#Autowired
private Environment environment;
#Autowired
private ConfigurationSettings configurationSettings;
#Test
public void testConfigurationLoads() {
assertNotNull(environment);
Assert.assertNotNull(configurationSettings);
}
#Test
public void testConfigurationSettingValues() {
assertEquals("Product Name", configurationSettings.getProduct());
assertEquals("0.0.1", configurationSettings.getVersion());
assertEquals("2014 Product", configurationSettings.getCopyright());
}
Can anyone see why the ConfigurationSettings are not being populated in my Controller?
Your configuration leads to 2 instances of the ConfigurationSettings class and probably one instance overrides the other.
The 'ConfigurationSettings' has the #Component annotation as you are scanning for components (#ComponentScan) this will lead to an instance. You also have a #Bean annotated method which also leads to an instance. The latter is overridden with the first.
In short remove the #Component annotation as that isn't needed because you already have a factory method for this class.
public class ConfigurationSettings { ... }
You should also remove the #PropertySource annotations as Spring-Boot will already load the application.properties for you.
Finally you should not use the #ContextConfiguration annotation on your test class but the #SpringApplicationConfiguration and pass in your application class (not your configuration class!).
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes=OFAC.class)
public class OFAConfigurationTest {
#Autowired
private Environment environment;
#Autowired
private ConfigurationSettings configurationSettings;
#Test
public void testConfigurationLoads() {
assertNotNull(environment);
assertNotNull(configurationSettings);
}
#Test
public void testConfigurationSettingValues() {
assertEquals("Product Name", configurationSettings.getProduct());
assertEquals("0.0.1", configurationSettings.getVersion());
assertEquals("2014 Product", configurationSettings.getCopyright());
}
This will fix your runtime configuration problems and will let your test use the power of Spring Boot to configure your application.

Spring Boot - Environment #Autowired throws NullPointerException

I have a project setup using Spring Boot 0.5.0.M5.
In one of the configuration files I am trying to #Autowire Environment but that fails with a NullPointerException.
Here's what I have so far:
Application.java
#EnableAutoConfiguration
#Configuration
#ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
JpaConfig.java where I am trying to #Autowire Environment
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(basePackages = "com.ui.persistence.repository")
public class JpaConfig {
private static final String DATABASE_DRIVER = "db.driver";
private static final String DATABASE_PASSWORD = "db.password";
private static final String DATABASE_URL = "db.url";
private static final String DATABASE_USERNAME = "db.username";
private static final String HIBERNATE_DIALECT = "hibernate.dialect";
private static final String HIBERNATE_SHOW_SQL = "hibernate.show_sql";
private static final String ENTITYMANAGER_PACKAGES_TO_SCAN
= "entitymanager.packages.to.scan";
#Autowired
private Environment env;
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty(DATABASE_DRIVER));
dataSource.setUrl(env.getProperty(DATABASE_URL));
dataSource.setUsername(env.getProperty(DATABASE_USERNAME));
dataSource.setPassword(env.getProperty(DATABASE_PASSWORD));
return dataSource;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean
= new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource());
entityManagerFactoryBean.setPersistenceProviderClass(
HibernatePersistence.class);
entityManagerFactoryBean.setPackagesToScan(
env.getProperty(ENTITYMANAGER_PACKAGES_TO_SCAN));
entityManagerFactoryBean.setJpaProperties(hibernateProperties());
return entityManagerFactoryBean;
}
}
I am trying to load the database properties configured in a properties file. However, the Environment is not injected and the code fails with NullPointerException. I do not have any configuration in XML files.
For the properties file I have configured PropertySourcesPlaceholderConfigurer this way:
#Configuration
#PropertySource("classpath:database.properties")
public class PropertyConfig {
#Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceHolderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
I have tried swapping #Autowired, #Resource and #Inject but nothing has worked so far. Would appreciate any help. Thanks.
Though your specific problem is solved, here's how to get Environment in case Spring's autowiring happens too late.
The trick is to implement org.springframework.context.EnvironmentAware; Spring then passes environment to setEnvironment() method.
This works since Spring 3.1.
An example:
#Configuration
#PropertySource("classpath:myProperties.properties")
public class MyConfiguration implements EnvironmentAware {
private Environment environment;
#Override
public void setEnvironment(final Environment environment) {
this.environment = environment;
}
public void myMethod() {
final String myPropertyValue = environment.getProperty("myProperty");
// ...
}
}
This is not as elegant as #Autowired or #Value, but it works as workaround in some situations.
I believe there were some lifecycle issues with Spring and the EntityManagerFactory, and you might have fallen foul of those (fixed in 4.0.0.RC1) - if your #Configuration class gets instantiated super early, it might not be eligible for autowiring. You can probably tell from the log output if that is the case.
Just out of interest, did you know that the functionality provided by your JpaConfig and PropertyConfig is already presetn out of the box if you use #EnableAutoConfiguration (as long as you #ComponentScan that package where your repositories are defined)? See the JPA sample in Spring Boot for an example.
I had the same problem on Spring Batch. Writers cannot autowire Environment class because Configuration class was instantiated earlier.
So I created a sort of Singleton (old manner) to instantiate Environment and I could access to it every time.
I did this implementation :
#Configuration
#PropertySource(value = { "classpath:kid-batch.properties" }, ignoreResourceNotFound = false)
public class BatchConfiguration implements EnvironmentAware {
private static Environment env;
public static String getProperty(String key) {
return env.getProperty(key);
}
#Override
public void setEnvironment(Environment env) {
BatchConfiguration.env = env;
}
}
And it works
I was having the similar issue to read properties from my application.properties file in spring boot application. I have struggled a lot to figure out the problem and make it work. Finally I have done. Here is my Constants class which will read properties values from properties file. I hope it will help to someone.
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.env.Environment;
#Configuration
#PropertySource("classpath:application.properties")
public class Constants implements EnvironmentAware {
static Environment environment;
#Override
public void setEnvironment(Environment environment) {
Constants.environment = environment;
}
#Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
return new PropertySourcesPlaceholderConfigurer();
}
public static String getActiveMQHost() {
System.out.println(environment.getProperty("spring.activemq.broker-host"));
return environment.getProperty("spring.activemq.broker-host");
}
public static String getActiveMQPort() {
System.out.println(environment.getProperty("spring.activemq.broker-port"));
return environment.getProperty("spring.activemq.broker-port");
}
public static String getActiveMQUser() {
System.out.println(environment.getProperty("spring.activemq.user"));
return environment.getProperty("spring.activemq.user");
}
public static String getActiveMQPassword() {
System.out.println(environment.getProperty("spring.activemq.password"));
return environment.getProperty("spring.activemq.password");
}
}
These are the property key's declared in my application.properties,
spring.activemq.broker-host
spring.activemq.broker-port
spring.activemq.user
spring.activemq.password

#Autowire not preperly injected with Spring #Bean configuration

I am practising on spring-social and it seems that the userConnectionRepository is not properly autowired in the following code when I do a "Run as Junit Test" in Eclipse. I get a Null pointer exception on the usersConnectionRepository when creating a new FacebookOffLine although breakpoints put in the #Bean java creation code shows that they seem to be properly created. Thanks in advance,
public class FacebookOffline {
private Facebook fb;
#Autowired
private UsersConnectionRepository usersConnectionRepository;
public FacebookOffline(User user) {
super();
ConnectionRepository cr = usersConnectionRepository.createConnectionRepository(user.getId());
fb = cr.getPrimaryConnection(Facebook.class).getApi();
}
}
Here is the test code :
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {
org.springframework.social.quickstart.config.MainConfig.class,
org.springframework.social.quickstart.config.SocialConfig.class })
public class FacebookOfflineTest {
#Test
public void test1() {
FacebookOffline essai = new FacebookOffline(new User("yves"));
And the Spring configuration classes adapted from Keith Donald Quick Start Sample :
#Configuration
#ComponentScan(basePackages = "org.springframework.social.quickstart", excludeFilters = { #Filter(Configuration.class) })
#PropertySource("classpath:org/springframework/social/quickstart/config/application.properties")
public class MainConfig {
#Bean
public DataSource datasource() {
DriverManagerDataSource toReturn = new DriverManagerDataSource("jdbc:mysql://localhost:3306/spring_social");
toReturn.setDriverClassName("com.mysql.jdbc.Driver");
toReturn.setUsername("spring");
toReturn.setPassword("spring");
return toReturn;
}
}
#Configuration
public class SocialConfig {
#Inject
private Environment environment;
#Inject
private DataSource dataSource;
#Bean
public ConnectionFactoryLocator connectionFactoryLocator() {
ConnectionFactoryRegistry registry = new ConnectionFactoryRegistry();
registry.addConnectionFactory(new FacebookConnectionFactory(environment
.getProperty("facebook.clientId"), environment
.getProperty("facebook.clientSecret")));
return registry;
}
#Bean
public UsersConnectionRepository usersConnectionRepository() {
JdbcUsersConnectionRepository repository = new JdbcUsersConnectionRepository(
dataSource, connectionFactoryLocator(), Encryptors.noOpText());
return repository;
}
}
Actually there are 2 problems here.
Spring cannot autowire beans it doesn't control (i.e. created with new)
Dependencies aren't available in the constructor (an object instance is needed before it can be injected)
The first one can be mitigated by letting spring manage an instance of FacebookOffline (or if you need multiple instances make the bean request or session scoped).
The second is a bit harder but can probaly solved by using a method annotated with #PostConstruct (or by implementing InitializingBean from spring).
You did
FacebookOffline essai = new FacebookOffline(new User("yves"));
That means, Spring isn't managing this essai instance and thus spring can't autowire any variables in the essai.
You'll have to create bean of FacebookOffline in SocialConfig.
Then you can have
/* ... */
public class FacebookOfflineTest {
#Autowired
ApplicationContext context;
#Test
public void test1() {
FacebookOffline essai = context.getBean(FacebookOffline.class);
OR
/* ... */
public class FacebookOfflineTest {
#Autowired
FacebookOffline essai;
#Test
public void test1() {
// You can use essai now
Also, you'll need to update FacebookOffline as Dependencies ain't available in constructor.
public class FacebookOffline {
private Facebook fb;
#Autowired
private UsersConnectionRepository usersConnectionRepository;
public FacebookOffline(User user) {
super();
}
#PostConstruct
void loadFacebook() {
ConnectionRepository cr = usersConnectionRepository.createConnectionRepository(user.getId());
fb = cr.getPrimaryConnection(Facebook.class).getApi();
}
}
Spring can't autowire fields on an instance you create via new since it doesn't know about it. Declare a bean of type FacebookOffline instead.

#Value annotation not being properly set

Here's my app:
public static void main( String[] args ) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);
//run the importer
final ImportNewOrders importer = (ImportNewOrders) ApplicationContextProvider.getApplicationContext().getBean("importNewOrders");
importer.run();
//importer.runInBackground();
}
Here's my config:
#Configuration
#ComponentScan(basePackages = {
"com.production"
})
#PropertySource(value = {
"classpath:/application.properties",
"classpath:/environment-${MY_ENVIRONMENT}.properties"
})
#EnableJpaRepositories("com.fettergroup.production.repositories")
#EnableTransactionManagement
public class Config {
.... skipping things that aren't relevant
#Bean
public ImportNewOrders importNewOrders() {
return new ImportNewOrders();
}
Here's my class...
#Component
public class ImportNewOrders implements Task {
private final static Logger logger = Logger.getLogger(ImportNewOrders.class.getName());
#Autowired
private OrderService orderService;
#Autowired
private ImportOrderRequest importOrderRequest;
#Value("${api.user}")
private String apiUser;
#Value("${api.password}")
private String apiPassword;
#Value("${api.orders.pingFrequency}")
private String pingFrequency;
And finally the application.properties:
# ------------------- Application settings -------------------
#Base URL to the API application
api.baseUrl=http://localhost:9998
#Unique token used to authenticate this vendor
api.vendor.token=asdf
#API credentials
api.user=myuser
api.password=mypassword
#How often to check for new orders; frequency is in seconds
api.orders.pingFrequency=60
This worked an hour or two ago, now it's decided it doesn't like these values. I'm at a loss as to why. Everything looks correct to me.
Update
#Configuration
#ComponentScan(basePackages = {
"com.production"
})
#PropertySource(value = {
"classpath:/application.properties",
"classpath:/environment-${MY_ENVIRONMENT}.properties"
})
#EnableJpaRepositories("com.production.repositories")
#EnableTransactionManagement
public class Config {
#Value("${db.url}")
private static String PROPERTY_DATABASE_URL;
#Bean
public DataSource dataSource() {
MysqlDataSource dataSource = new MysqlDataSource();
dataSource.setUrl(PROPERTY_DATABASE_URL); //is null
/*dataSource.setUser(environment.getRequiredProperty(PROPERTY_NAME_DATABASE_USER));
dataSource.setPassword(environment.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));*/
return dataSource;
}
#Bean
public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer () {
return new PropertySourcesPlaceholderConfigurer();
}
}
Your properties file is found by your #Configuration and is using it for your database properties within that class because of #PropertySource. But #Value fields and ${} evaluation need more than that.
From Javadoc for #PropertySource
In order to resolve ${...} placeholders in definitions or
#Value annotations using properties from a PropertySource, one must
register a PropertySourcesPlaceholderConfigurer. This happens
automatically when using in XML, but
must be explicitly registered using a static #Bean method when using
#Configuration classes. See the "Working with externalized values"
section of #Configuration Javadoc and "a note on
BeanFactoryPostProcessor-returning #Bean methods" of #Bean Javadoc for
details and examples.
So declare a
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer p = new PropertySourcesPlaceholderConfigurer();
p.setLocation(new ClassPathResource("your properties path"));
// other properties
return p;
}
in your config class, or as ach has aptly mentioned in the comments if you use #PropertySource your can omit setLocation altogether:
#Configuration
#PropertySource(value="classpath:your_file.properties")
public class MyConfiguration{
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer p = new PropertySourcesPlaceholderConfigurer();
return p;
}
}
You shouldn't need the environment when you have the PropertySourcesPlaceholderConfigurer
In most cases, however, application-level beans should not need to>
interact with the Environment directly but instead may have to have
${...} property values replaced by a property placeholder configurer
such as PropertySourcesPlaceholderConfigurer, which itself is
EnvironmentAware and as of Spring 3.1 is registered by default when
using < context:property-placeholder/>.

Categories

Resources