2010-07-16 14 views
5

Estoy tratando de utilizar las anotaciones @Configuration para conectar mi aplicación pero sigo obteniendo una NullPointerException en uno de los inicializadores porque el bean al que se refiere todavía no se ha inicializado (creo). Intenté especificar en el web.xml solo la clase de configuración 'raíz' y también intenté hacer un escaneo de paquetes y ninguno de los dos parece funcionar.¿Cómo me aseguro de que las configuraciones dependientes se inicialicen con la anotación Spring @Configuration?

Disculpa por el gran volcado de código. Traté de producir un conjunto de clases mucho más simple para reproducir el problema, pero por supuesto, cuando lo hice, todo funcionó bien. Aquí están mis clases (importaciones): elididas

DataSourceConfig.java:

@Configuration 
public class DataSourceConfig { 

    public DataSourceConfig() { 
     System.err.println("DataSourceConfig constructed..."); 
    } 

    @Bean 
    public DataSource dataSource() { 
     BasicDataSource bean = new BasicDataSource(); 
     bean.setDriverClassName("com.mysql.jdbc.Driver"); 
     bean.setUrl("jdbc:mysql://localhost:3306/observation"); 
     bean.setUsername("observation"); 
     bean.setPassword("*******"); 
     bean.setInitialSize(1); 
     bean.setMaxActive(5); 
     bean.setTestOnBorrow(true); 
     System.err.println("dataSource bean initialized: " + bean.toString()); 
     return bean; 
    } 
} 

HibernateConfig.java

@Configuration 
@Import(DataSourceConfig.class) 
public class HibernateConfig { 

    public HibernateConfig() { 
     System.err.println("HibernateConfig constructing..."); 
    } 

    @Autowired 
    private DataSourceConfig dataSourceConfig; 

    @Bean 
    protected NamingStrategy namingStrategy() { 
     return new ImprovedNamingStrategy(); 
    } 

    private AnnotationSessionFactoryBean sessionFactoryBean = null; 

    @Bean 
    @DependsOn("dataSourceConfig") 
    public AnnotationSessionFactoryBean sessionFactory() { 
     if (sessionFactoryBean == null) { 
      sessionFactoryBean = new AnnotationSessionFactoryBean(); 
NPE Here--> sessionFactoryBean.setDataSource(dataSourceConfig.dataSource()); 
      sessionFactoryBean.setSchemaUpdate(true); 
      sessionFactoryBean.setNamingStrategy(namingStrategy()); 
      sessionFactoryBean.setPackagesToScan(new String[] { 
        "com.newco.observations.domain", 
        "com.newco.observations.domain.*" }); 
      Properties props = new Properties(); 
      props.setProperty("hibernate.default_schema", "observation"); 
      props.setProperty("hibernate.dialect", 
        "org.hibernate.dialect.MySQLDialect"); 
      props.setProperty("hibernate.show_sql", "true"); 
      sessionFactoryBean.setHibernateProperties(props); 
      System.err.println("sessionFactory initialized"); 
     } 
     return sessionFactoryBean; 
    } 

    @Bean 
    @DependsOn("dataSourceConfig") 
    public JdbcTemplate jdbcTemplate() { 
     return new JdbcTemplate(dataSourceConfig.dataSource()); 
    } 

    @Bean 
    @DependsOn("sessionFactory") 
    public ResourceTransactionManager txManager() { 
     HibernateTransactionManager bean = new HibernateTransactionManager(); 
     bean.setSessionFactory((SessionFactory) sessionFactory().getObject()); 
     return bean; 
    } 

    @Bean 
    @DependsOn("sessionFactory") 
    public HibernateTemplate hibernateTemplate() { 
     return new HibernateTemplate((SessionFactory) sessionFactory() 
       .getObject()); 
    } 
} 

DaoConfig.java:

@Configuration 
@Import(HibernateConfig.class) 
public class DaoConfig { 

    public DaoConfig() 
    { 
     System.err.println("DaoConfig constructing..."); 
    } 

    private @Autowired HibernateConfig hibernateConfig; 

    @Bean 
    @DependsOn("hibernateTemplate") 
    public PhenomenonGroupDao phenomenonGroupDao() 
    { 
     PhenomenonGroupDaoImpl bean = new PhenomenonGroupDaoImpl(); 
     bean.setHibernateTemplate(hibernateConfig.hibernateTemplate()); 
     return bean; 
    } 

    @Bean 
    @DependsOn("hibernateTemplate") 
    public PhenomenonDao phenomenonDao() 
    { 
     PhenomenonDaoImpl bean = new PhenomenonDaoImpl(); 
     bean.setHibernateTemplate(hibernateConfig.hibernateTemplate()); 
     return bean; 
    } 

    @Bean 
    @DependsOn("hibernateTemplate") 
    public DiscretePhenomenonDao discretePhenomenonDao() 
    { 
     DiscretePhenomenonDaoImpl bean = new DiscretePhenomenonDaoImpl(); 
     bean.setHibernateTemplate(hibernateConfig.hibernateTemplate()); 
     return bean; 
    } 


} 

Se puede ver desde las anotaciones System.err.println y @DependsOn una especie de sacudida sobre t que estoy haciendo

puedo proporcionar el registro completo si es útil, pero aquí es lo que creo que son las líneas relevantes (con un poco de formato para que sea más fácil de leer (tal vez)):

  • 208 [Thread-0 ] INFO org.springframework.context.annotation.ConfigurationClassEnhancer
  • Mejorado con éxito com.bjk.observation.server.config.DaoConfig; nombre de la clase mejorada es: com.bjk.observation.server.config.DaoConfig $$ $$ EnhancerByCGLIB 96e1956
  • 229 [thread-0] Información org.springframework.beans.factory.support.DefaultListableBeanFactory
  • únicos-crear instancias de Pre en org.springframework.beans.factory.support.DefaultLista[email protected]: definición de beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalAutowiredAnnotationProcessor, org.springframework.context.annotation.internalRequiredAnnotationProcessor, org. springframework.context.annotation.internalCommonAnnotationProcessor, org.springframework.context.annotation.internalPersistenceAnnotationProcessor, daoConfig, com.bjk.observation.server.config.DataSourceConfig # 0, dataSource, com.bjk.observation.server.config.HibernateConfig # 0, nombres trategy, sessionFactory, jdbcTemplate, txManager, hibernateTemplate, phenomenonGroupDao, phenomenonDao, discretePhenomenonDao]; raíz de la jerarquía de la fábrica DaoConfig la construcción ...
  • 252 [thread-0] Información org.springframework.beans.factory.support.DefaultListableBeanFactory
  • únicos destruyendo en org.s[email protected]185572a: granos que definen [org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalAutowiredAnnotationProcessor, org.springframework.context.annotation.internalRequiredAnnotationProcessor, org.springframework.context.annotation.internalCommonAnnotationProcessor, org.springframework.context.annotation .internalPersistenceAnnotationProcessor, daoConfig, com.bjk.observation.server.config.DataSourceConfig # 0, dataSource, com.bjk.observation.server.config.HibernateConfig # 0, namingStrategy, sessionFactory, jdbcTemplate, txManager , hibernateTemplate, phenomenonGroupDao, phenomenonDao, discretePhenomenonDao]; raíz de la jerarquía de fábrica
  • 253 [Thread-0] ERROR org.springframework.web.context.ContextLoader
  • Error al inicializar el contexto org.springframework.beans.factory.BeanCreationException: error al crear bean con el nombre 'daoConfig': error en la inyección de dependencias con autoenlace; la excepción anidada es org.springframework.beans.factory.BeanCreationException: no se pudo autocablear el campo: privado com.bjk.observation.server.config.HibernateConfig com.bjk.observation.server.config.DaoConfig.hibernateConfig; La excepción anidada es org.springframework.beans.factory.BeanCreationException: Error al crear bean con el nombre 'com.bjk.observation.server.config.HibernateConfig # 0': Error de instanciación del bean; La excepción anidada es org.springframework.beans.BeanInstantiationException: No se pudo crear una instancia de la clase bean [com.bjk.observation.server.config.HibernateConfig]: Constructor lanzó una excepción; la excepción jerarquizada es java.lang.NullPointerException

Respuesta

2

El problema, creo que es aquí:

@Autowired 
private DataSourceConfig dataSourceConfig; 

No se supone cablear explícitamente a sí mismo con otras clases @Configuration -annotated, sino más bien los frijoles que ellos producen. Spring resolverá las cañerías por ti.

Así reemplazar el campo anterior con la más simple:

@Autowired 
private DataSource dataSource; 

primavera obtendrá los DataSource de DataSourceConfig y transparente inyectarlo en el campo.

Del mismo modo, sustituir

@Autowired 
private HibernateConfig hibernateConfig; 

con

@Autowired 
private HibernateTemplate hibernateTemplate; 

Se dará cuenta de que el estilo @Configuration no se siente tan bien cuando se trabaja con los granos de fábrica como AnnotationSessionFactoryBean, ya que a menudo hay que llamar getObject() en él usted mismo. A veces, es más natural usar la configuración XML y mezclarla con el estilo de configuración de Java.

+3

No sé por qué eso ayudaría exactamente porque se supone que las clases marcadas con @Configuration son beans en sí mismas. No obstante, probé como sugirió y, aunque mi registro de errores es diferente, todavía tiene que ver con que los beans no se inicialicen en el orden correcto. (El depurador lo confirma). Considero que @Configuration no es tan agradable para los beans de fábrica y, de hecho, me he encontrado con una configuración xml fiable, pero aún me gustaría entender cómo se supone que funciona. – jhericks

Cuestiones relacionadas