2013-10-18 13 views
11

Ho una configurazione di progetto utilizzando Spring Boot 0.5.0.M5.Avvio a molla - Ambiente @Autowired genera NullPointerException

In uno dei file di configurazione sto provando a @Autowire Environment ma non riesce con uno NullPointerException.

Ecco quello che ho finora:

Application.java

JpaConfig.java dove sto cercando di @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; 
    } 
} 

sto cercando di caricare le proprietà del database configurate in un file di proprietà. Tuttavia, lo Environment non viene iniettato e il codice ha esito negativo con NullPointerException. Non ho alcuna configurazione nei file XML.

Per le proprietà del file Ho configurato PropertySourcesPlaceholderConfigurer questo modo:

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

ho provato scambiando @Autowired, @Resource e @Inject, ma niente ha funzionato finora. Gradirei qualsiasi aiuto. Grazie.

+0

si può mostrare la traccia dello stack? Inoltre, c'è qualcosa che fornisce l'ambiente? Penso che tu abbia bisogno di una classe che abbia un metodo che renda uno contrassegnato con '@ Bean'. Inoltre, potresti essere in grado di usare '@ Value' per impostare le proprietà invece di ottenere un ambiente e ottenerle in questo modo. – CodeChimp

+0

Ho provato con @Value, non ha funzionato. La traccia dello stack è solo NullPointerException perché le variabili non sono state impostate. Grazie. – imme

risposta

4

Credo che ci siano stati alcuni problemi relativi al ciclo di vita con Spring e EntityManagerFactory, e potresti essere caduto in fallo (corretto in 4.0.0.RC1) - se la tua classe @Configuration viene istanziata molto presto, potrebbe non essere idonea per autowiring. Probabilmente puoi dirlo dall'output del registro, se così fosse.

solo per interesse, lo sapevate che la funzionalità fornito dal JpaConfig e PropertyConfig è già presetn fuori dalla scatola, se si utilizza @EnableAutoConfiguration (purché si @ComponentScan quel pacchetto in cui sono definiti i repository)? Vedere lo JPA sample in Spring Boot per un esempio.

+0

Viene chiamato molto presto, avrei bisogno di scrivere codice per leggere e impostare le proprietà in questo caso? Ho dato un'occhiata all'esempio che usa hsqldb. Sono su MySQL, credo che avrei bisogno di fornire DataSource con l'URL di connessione, Username e così via. Grazie per aver preso il tempo di rispondere. – imme

+0

Spring Boot ha alcune convenzioni per esternalizzare la configurazione 'DataSource' ([esempio qui] (https://github.com/spring-projects/spring-xd/blob/master/spring-xd-dirt/src/main/resources/ application.yml # L31)), quindi non è necessario eseguire alcuna operazione. Se fossi in te, lo farei funzionare con H2 o HSQLDB prima di provare MySQL. –

+0

Cool, funziona come un incantesimo (usando MySQL)! Grazie Dave! – imme

16

Anche se il problema specifico è risolto, , ecco come ottenere Environment nel caso in cui l'autowiring di Spring avvenga troppo tardi.

Il trucco è implementare org.springframework.context.EnvironmentAware; La molla passa quindi l'ambiente al metodo setEnvironment(). Funziona dalla primavera 3.1.

Un esempio:

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

} 

Questo non è elegante come @Autowire o @Value, ma funziona come soluzione in alcune situazioni.

+2

Ho avuto una strana situazione in cui una classe annotata con Configuration aveva due metodi Bean. Un metodo ha creato un DataSource e l'altro un PropertySourcesPlaceholderConfigurer che ho inizializzato dai file delle proprietà che ho localizzato in base ai valori nel campo Ambiente Autowired. Funzionava bene (l'ambiente è stato inizializzato prima che il configuratore fosse inizializzato). Ho deciso di spostare il metodo delle proprietà in un'altra classe insieme al campo Ambiente e, una volta eseguita l'operazione, Ambiente era nullo quando il bean del configuratore è stato inizializzato. L'utilizzo di setEnvironment() ha funzionato su questo. Grazie! –

+1

grazie a questo ha funzionato bene – JamesC

0

Ho avuto lo stesso problema su Spring Batch. I writer non possono autorizzare la classe Environment in quanto la classe Configuration è stata creata in precedenza. Così ho creato una sorta di Singleton (vecchio modo) per creare un'istanza di Ambiente e potevo accedervi ogni volta.

ho fatto questa implementazione:

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

}

E funziona

Problemi correlati