11

스프링 부트 0.5.0.M5을 사용하는 프로젝트 설정이 있습니다.스프링 부트 - 환경 @Autowired가 NullPointerException을 던졌습니다.

구성 파일 중 하나에서 @Autowire Environment을 시도하고 있는데 그 중 하나가 NullPointerException과 함께 실패합니다. 여기

는 지금까지이 작업은 다음과 같습니다

Application.java를 내가 @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; 
    } 
} 

내가로드하려고 노력하고 있어요

@EnableAutoConfiguration 
@Configuration 
@ComponentScan 
public class Application { 

    public static void main(String[] args) { 
     SpringApplication.run(Application.class, args); 
    } 
} 

JpaConfig.java 특성 파일에 구성된 데이터베이스 특성. 그러나 Environment은 삽입되지 않으며 코드는 NullPointerException으로 실패합니다. XML 파일에 구성이 없습니다. 특성에 대해

내가 PropertySourcesPlaceholderConfigurer 이런 식으로 구성한 파일 :

내가 @Autowired, @Resource@Inject 교환 시도했지만 아무것도 지금까지 근무하지 않았다
@Configuration 
@PropertySource("classpath:database.properties") 
public class PropertyConfig { 
    @Bean 
    public static PropertySourcesPlaceholderConfigurer propertyPlaceHolderConfigurer() { 
     return new PropertySourcesPlaceholderConfigurer(); 
    } 
} 

. 어떤 도움을 주시면 감사하겠습니다. 감사.

+0

당신이 스택 추적을 보여줄 수 일을? 또한 '환경'을 제공하는 것은 무엇입니까? '@ Bean'으로 표시된 것을 리턴하는 메소드가있는 클래스가 필요하다고 생각합니다. 또한'@ Value'를 사용하여 환경을 가져 와서 그 속성을 얻지 않고 속성을 설정할 수도 있습니다. – CodeChimp

+0

@Value로 시도했지만 작동하지 않았습니다. 변수가 설정되지 않았으므로 스택 추적은 NullPointerException입니다. 감사. – imme

답변

4

스프링 및 EntityManagerFactory에 대한 수명주기 문제가 있다고 생각합니다 (4.0.0.RC1에서 수정 됨) - @Configuration 클래스가 일찍 인스턴스화되는 경우 자격이 없을 수 있습니다. autowiring. 이 경우 로그 출력에서 ​​알 수 있습니다. 그냥 관심 밖으로

, 당신은 @EnableAutoConfiguration를 사용하는 경우 기능이 (당신만큼 @ComponentScan 당신의 저장소가 정의되는 패키지) 상자 밖으로 이미 presetn 귀하의 JpaConfigPropertyConfig에 의해 제공되는 것을 알고 계십니까? 예를 들어 JPA sample in Spring Boot을 참조하십시오.

+0

매우 초기에 호출됩니다.이 경우 속성을 읽고 설정하기위한 코드를 작성해야합니까? hsqldb를 사용하는 예를 살펴 보았습니다. MySQL을 사용하고 있는데, DataSource에 연결 URL, 사용자 이름 등을 제공해야한다고 생각합니다. 회신에 시간을내어 주셔서 감사합니다. – imme

+0

스프링 부트는'DataSource' 설정을 외부화하기위한 규칙이 있습니다 ([여기에있는 예제] (https://github.com/spring-projects/spring-xd/blob/master/spring-xd-dirt/src/main/resources/). application.yml # L31)), 그렇게 할 필요는 없습니다. 내가 당신이라면 MySQL을 시험해보기 전에 H2 또는 HSQLDB와 함께 작업하게 할 것입니다. –

+0

쿨하고 매력적입니다 (MySQL 사용)! 감사 데이브! – imme

16

특정 문제는 해결되지만,의 경우 autowiring이 너무 늦은 경우에 대비하여 을 얻는 방법은 Environment입니다.

트릭은 org.springframework.context.EnvironmentAware을 구현하는 것입니다. 그런 다음 Spring은 환경을 setEnvironment() 메소드로 전달합니다. 이것은 Spring 3.1 이후로 작동합니다.

예 :

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

} 

@Autowire 또는 @Value로 우아한 아니지만, 어떤 상황에서 해결 방법으로 작동합니다.

+2

Configuration으로 주석 처리 된 클래스에 두 개의 Bean 메소드가있는 이상한 상황이있었습니다. 하나의 메소드는 DataSource를 만들고, 다른 하나는 Autowired Environment 필드의 값을 기반으로 배치 한 속성 파일에서 초기화 한 PropertySourcesPlaceholderConfigurer입니다. 그게 괜찮 았어 (환경 구성자가 초기화되기 전에 초기화되었습니다). Environment 필드와 함께 속성 메소드를 다른 클래스로 옮기고 환경 설정자를 초기화 할 때 환경 변수가 null이되었다. setEnvironment()를 사용하면이 문제를 해결할 수 있습니다. 감사! –

+1

감사합니다. – JamesC

0

스프링 배치에도 동일한 문제가있었습니다. 구성 클래스가 일찍 인스턴스화 되었기 때문에 작성자는 환경 클래스를 자동으로 호출 할 수 없습니다. 그래서 환경을 인스턴스화하는 일종의 Singleton (옛날 방식)을 만들었고 매번이 환경에 액세스 할 수있었습니다.

내가이 구현 한 :

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

}

그리고 그것은

관련 문제