HOW-TO: Using @PropertySource annotation in Spring 4 with Java 7
Today I migrated one of my projects, that I am currently working on, to Spring 4.0. Since it is a really simple web application I use to learn and demo Spring features, I only needed to update the POM file of my project and change the Spring version. I deployed the project to Tomcat 7 server and apparently the application did not start. I saw this message in IntelliJ console: Failed to load bean class: pl.codeleak.t.config.RootConfig; nested exception is org.springframework.core.NestedIOException: Unable to collect imports; nested exception is java.lang.ClassNotFoundException: java.lang.annotation.Repeatable
. What the …?
java.lang.annotation.Repeatable annotation that is the meta annotation used to mark your annotations for multiple usage in Java 8 (but I am using Java 7 in the project). E.g.:
@Repeatable(Schedules.class) public @interface Schedule { ... } @Schedule(dayOfMonth="last") @Schedule(dayOfWeek="Fri", hour="23") public void doPeriodicCleanup() { ... }
This is well described here: http://docs.oracle.com/javase/tutorial/java/annotations/repeating.html.
Spring 4 utilizes this feature in its @PropertySource annotation. To remind you, @PropertySource annotation provides a mechanism for adding a source of name/value property pairs to Spring’s Environment and it is used in conjunction with @Configuration classes. As you probably already know, I am using this feature in my own configuration:
@Configuration @PropertySource("classpath:/datasource.properties") public class DefaultDataSourceConfig implements DataSourceConfig { @Autowired private Environment env; @Override @Bean public DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName(env.getRequiredProperty("dataSource.driverClassName")); dataSource.setUrl(env.getRequiredProperty("dataSource.url")); dataSource.setUsername(env.getRequiredProperty("dataSource.username")); dataSource.setPassword(env.getRequiredProperty("dataSource.password")); return dataSource; } }
The first think I thought, that Spring is not compatible with Java below 8 anymore. Impossible. While doing GitHub lookup I found a brand new @PropertySources annotation that is a container of @PropertySource annotations. And that was my solution for Java compatibility issue: using @PropertySources annotation on my configuration class like this:
@Configuration @PropertySources(value = {@PropertySource("classpath:/datasource.properties")}) public class DefaultDataSourceConfig implements DataSourceConfig { @Autowired private Environment env; }
And that’s it! After this change my application started and I could see it is working just fine!
EDIT: See: https://jira.springsource.org/browse/SPR-11086