Monday, November 11, 2013

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.:

public @interface Schedule { ... }

@Schedule(dayOfWeek="Fri", hour="23")
public void doPeriodicCleanup() { ... }

This is well described here:

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:

public class DefaultDataSourceConfig implements DataSourceConfig {

    private Environment env;

    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        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:

@PropertySources(value = {@PropertySource("classpath:/")})
public class DefaultDataSourceConfig implements DataSourceConfig {

    private Environment env;


And that's it! After this change my application started and I could see it is working just fine!

EDIT: See:


  1. Thanks for this. Looks like this was fixed in RC2 that was just released.