2013-10-18 24 views
11

Ich habe ein Projekt-Setup mit Spring Boot 0.5.0.M5.Spring Boot - Umgebung @Autowired wirft NullPointerException

In einer der Konfigurationsdateien versuche ich @Autowire Environment, aber das schlägt mit einem NullPointerException.

Hier ist, was ich bisher:

Application.java

JpaConfig.java wo ich @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; 
    } 
} 

Ich lade ich versuche, ich versuche zu die Datenbankeigenschaften, die in einer Eigenschaftendatei konfiguriert sind. Die Environment wird jedoch nicht injiziert und der Code schlägt mit NullPointerException fehl. Ich habe keine Konfiguration in XML-Dateien.

Für die Eigenschaftendatei I PropertySourcesPlaceholderConfigurer so konfiguriert haben:

@Configuration 
@PropertySource("classpath:database.properties") 
public class PropertyConfig { 
    @Bean 
    public static PropertySourcesPlaceholderConfigurer propertyPlaceHolderConfigurer() { 
     return new PropertySourcesPlaceholderConfigurer(); 
    } 
} 

ich @Autowired Swapping haben versucht, @Resource und @Inject aber nichts hat bisher funktioniert. Würde mich über jede Hilfe freuen. Vielen Dank.

+0

Können Sie den Stack-Trace zeigen? Gibt es irgendetwas, das die "Umgebung" bereitstellt? Ich denke, dass Sie eine Klasse brauchen, die eine Methode hat, die eine zurückgibt, die mit '@ Bean' markiert ist. Sie können auch '@ Value' verwenden, um Ihre Eigenschaften festzulegen, anstatt eine Umgebung zu erhalten und sie auf diese Weise zu erhalten. – CodeChimp

+0

Ich habe es mit @Value versucht, hat nicht funktioniert. Die Stack-Ablaufverfolgung ist nur NullPointerException, da die Variablen nicht festgelegt wurden. Vielen Dank. – imme

Antwort

4

Ich glaube, es gab einige Lebenszyklusprobleme mit Spring und der EntityManagerFactory, und Sie könnten diese (in 4.0.0.RC1 behoben) fallen - wenn Ihre @Configuration Klasse super früh instanziiert wird, ist es möglicherweise nicht geeignet für Autofahren. Sie können wahrscheinlich von der Protokollausgabe unterscheiden, wenn das der Fall ist.

Nur aus Interesse, wissen Sie, dass die Funktionalität von Ihren JpaConfig zur Verfügung gestellt und PropertyConfig ist bereits aus dem Kasten heraus PRESETN wenn Sie @EnableAutoConfiguration (solange Sie @ComponentScan dass Paket, in dem Sie Ihre Repositories definiert sind) verwenden? Ein Beispiel finden Sie in der JPA sample in Spring Boot.

+0

Es wird sehr früh aufgerufen, müsste ich Code zum Lesen schreiben und die Eigenschaften in diesem Fall festlegen? Ich habe einen Blick auf das Beispiel hsqldb genommen. Ich bin auf MySQL, ich glaube, ich müsste die DataSource mit der Verbindungs-URL, Benutzername und so weiter bereitstellen. Vielen Dank für die Zeit zu nehmen, um zu antworten. – imme

+0

Spring Boot hat einige Konventionen für die Externalisierung der 'DataSource'-Konfiguration ([Beispiel hier] (https://github.com/spring-projects/spring-xd/blob/master/spring-xd-dirt/src/main/resources/ application.yml # L31)), so dass Sie nichts davon tun müssen. Wenn ich Sie wäre, würde ich es mit H2 oder HSQLDB arbeiten, bevor Sie das MySQL versuchen. –

+0

Cool, funktioniert wie ein Zauber (mit MySQL)! Danke Dave! – imme

16

Obwohl Ihr spezifisches Problem gelöst ist, erhalten Sie hier , um Environment zu bekommen, falls das Autodiring von Spring zu spät passiert.

Der Trick ist zu implementieren org.springframework.context.EnvironmentAware; Spring übergibt dann die Umgebung an die Methode setEnvironment(). Dies funktioniert seit Frühling 3.1.

Ein Beispiel:

@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"); 
     // ... 
    } 

} 

Das ist nicht so elegant wie @Autowire oder @Value, aber es funktioniert in einigen Situationen als Abhilfe.

+2

Ich hatte eine seltsame Situation, wo eine Klasse, die mit Konfiguration versehen wurde, zwei Bean-Methoden hatte. Eine Methode erstellte eine DataSource und die andere eine PropertySourcesPlaceholderConfigurer, die ich aus Eigenschaftendateien initialisierte, die ich basierend auf Werten im Feld "Autoverarbeitete Umgebung" gefunden hatte. Das hat gut funktioniert (Umgebung wurde initialisiert, bevor der Konfigurator initialisiert wurde). Ich beschloss, die Eigenschaftsmethode zusammen mit dem Feld "Umgebung" in eine andere Klasse zu verschieben, und nachdem ich das getan hatte, war "Environment" null, als die Konfigurations-Bean initialisiert wurde. Die Verwendung von setEnvironment() hat dies umgangen. Vielen Dank! –

+1

danke das hat gut funktioniert – JamesC

0

Ich hatte das gleiche Problem auf Spring Batch. Writer können die Environment-Klasse nicht automatisch ansteuern, da die Konfigurationsklasse früher instanziiert wurde. Also habe ich eine Art Singleton (alte Art) erstellt, um die Umgebung zu instanziieren und ich konnte jedes Mal darauf zugreifen.

ich diese Implementierung tat

@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; 
} 

}

Und es funktioniert