How can the Spring Environment be injected properly in one method but not another?

chrisjleu picture chrisjleu · Jan 22, 2013 · Viewed 9.1k times · Source

neo4jDatabase() is fine but environment is always null in graphDatabaseService()... how/why?

@Configuration
@PropertySource("classpath:/neo4j.properties")
@EnableNeo4jRepositories("reservation.repository.neo4j")
public class Neo4jConfig extends Neo4jConfiguration {

    @Inject
    Environment environment;

    @Bean(initMethod = "setupDb")
    public Neo4jDatabase neo4jDatabase() {
        // Environment fine here...
        return new Neo4jDatabase(this.environment.getProperty("data.file.path"));
    }

    @Bean(destroyMethod = "shutdown")
    public GraphDatabaseService graphDatabaseService() {
        if (environment == null) {
            // Always gets here for some reason...why?
            return new EmbeddedGraphDatabase("/Temp/neo4j/database");
        } else {
            return new EmbeddedGraphDatabase(this.environment.getProperty("database.path"));
        }
    }
}

Versions: Spring 3.2.0.RELEASE, spring-data-neo4j 2.1.0.RELEASE.

Answer

Matt Wielbut picture Matt Wielbut · Jun 5, 2013

In case anyone else is having the same issue - the following worked for me:

@Configuration
@PropertySource("classpath:neo4j.properties")
@EnableNeo4jRepositories(basePackages = "com.mydomain.neo4j.repo")
public class Neo4jConfig 
{
    @Autowired
    Environment environment;

    @Bean(name="graphDatabaseService", destroyMethod = "shutdown")
    public GraphDatabaseService getGraphDatabaseService() 
    {
        // any custom graph db initialization
        return new EmbeddedGraphDatabase(this.environment.getProperty("database.path"));
    }
}

NOTE: I am NOT extending Neo4jConfiguration. It just tuns into a spaghetti of Autowired dependencies with the Environment member variable never set by the time it's needed for the initialization of the graphDatabaseService. You can get it to work using a @PostConstruct but you end up with a bunch of NotInTransactionException's. I didn't have time to dig into why - instead, in your main AppConfig class, you simply import your custom Neo4j configuration AS WELL AS the base abstract Neo4j configuration class. Essentially, you're doing in code what the XML configuration would do.

@Configuration
@Import({Neo4jConfig.class, Neo4jConfiguration.class})
@ComponentScan(basePackages = {"com.mydomain"}, excludeFilters = @Filter({Controller.class, Configuration.class}))
public class MainConfig
{
    // any other configuration you have
}