I have an issue with connecting environment to my Spring project. In this class
@Configuration @ComponentScan(basePackages = "my.pack.offer.*") @PropertySource("classpath:OfferService.properties") public class PropertiesUtil { @Autowired private Environment environment; @Bean public String load(String propertyName) { return environment.getRequiredProperty(propertyName); } }
environment always is null.
The field annotated @Autowired is null because Spring doesn't know about the copy of MileageFeeCalculator that you created with new and didn't know to autowire it.
When @Autowired doesn't work. There are several reasons @Autowired might not work. When a new instance is created not by Spring but by for example manually calling a constructor, the instance of the class will not be registered in the Spring context and thus not available for dependency injection.
Using the HelloWorldService below as a bean in a Spring application would fail. As there is no @Autowired (or @Inject or @Resource ) on the field, Spring doesn't know it needs to inject a dependency into the field. So the field remains null .
Internal representation of a null bean instance, e.g. for a null value returned from FactoryBean. getObject() or from a factory method. Each such null bean is represented by a dedicated NullBean instance which are not equal to each other, uniquely differentiating each bean as returned from all variants of BeanFactory.
Autowiring happens later than load()
is called (for some reason).
A workaround is to implement EnvironmentAware
and rely on Spring calling setEnvironment()
method:
@Configuration @ComponentScan(basePackages = "my.pack.offer.*") @PropertySource("classpath:OfferService.properties") public class PropertiesUtil implements EnvironmentAware { private Environment environment; @Override public void setEnvironment(final Environment environment) { this.environment = environment; } @Bean public String load(String propertyName) { return environment.getRequiredProperty(propertyName); } }
Change @Autowired
for @Resource
(from javax.annotation) and make it public
e.g.:
@Configuration @PropertySource("classpath:database.properties") public class HibernateConfigurer { @Resource public Environment env; @Bean public DataSource dataSource() { BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName(env.getProperty("database.driverClassName")); dataSource.setUrl(env.getProperty("database.url")); dataSource.setUsername(env.getProperty("database.username")); dataSource.setPassword(env.getProperty("database.password")); dataSource.setValidationQuery(env.getProperty("database.validationQuery")); return dataSource; } }
And you must register your configurer class in WebApplicationInitializer this way
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); context.register(ApplicationConfigurer.class); //ApplicationConfigurer imports HibernateConfigurer
It's working for me! You may want to check a test project I made.
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