2010-07-16 3 views
5

J'essaie d'utiliser les annotations @Configuration pour câbler mon application mais je continue d'obtenir une exception NullPointerException dans l'un des initialiseurs parce que le bean auquel il fait référence n'est pas encore initialisé (je pense). J'ai essayé de spécifier dans le web.xml juste la classe de config 'root' et j'ai aussi essayé de faire un scan de paquet et aucun ne semble fonctionner.Comment puis-je m'assurer que les configurations dépendantes sont initialisées avec l'annotation Spring @Configuration?

Désolé pour le vidage du gros code. J'ai essayé de produire un ensemble beaucoup plus simple de classes pour reproduire le problème, mais bien sûr, quand j'ai fait ça, tout a bien fonctionné. Voici mes classes (importations élidés):

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


} 

Vous pouvez voir les annotations System.err.println et @DependsOn une sorte de fla chapeau que je fais.

Je peux fournir le journal complet si elle est utile, mais voici ce que je pense sont les lignes pertinentes (avec un peu de mise en forme pour le rendre plus lisible (peut-être)):

  • 208 [Discussion-0 ] INFO org.springframework.context.annotation.ConfigurationClassEnhancer
  • Amélioré avec succès com.bjk.observation.server.config.DaoConfig; amélioré nom de classe est: com.bjk.observation.server.config.DaoConfig $$ $$ EnhancerByCGLIB 96e1956
  • 229 [Fil-0] INFO org.springframework.beans.factory.support.DefaultListableBeanFactory
  • singletons Pré-instanciation dans org.s[email protected]185572a: définition 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.serveur.config.DataSourceConfig # 0, dataSource, com.bjk.observation.server.config.HibernateConfig # 0, NamingS trategy, sessionFactory, jdbcTemplate, txManager, hibernateTemplate, phénomèneGroupDao, phenomenonDao, discretePhenomenonDao]; racine de la hiérarchie de l'usine DaoConfig construction ...
  • 252 [Fil-0] INFO org.springframework.beans.factory.support.DefaultListableBeanFactory
  • Destroying singletons dans org.s[email protected]185572a: définition des 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, source de données, com.bjk.observation.server.config.HibernateConfig # 0, namingStrategy, sessionFactory, jdbcTemplate, txManager , hibernateTemplate, phénomèneGroupDao, phénomèneDao, discretPhenomenonDao]; racine de la hiérarchie d'usine
  • 253 [Thread-0] ERREUR org.springframework.web.context.ContextLoader
  • Échec de l'initialisation du contexte org.springframework.beans.factory.BeanCreationException: Erreur lors de la création du bean avec le nom 'daoConfig': échec de l'injection des dépendances autogérées; l'exception imbriquée est org.springframework.beans.factory.BeanCreationException: Impossible d'autofaire le champ: private com.bjk.observation.server.config.HibernateConfig com.bjk.observation.server.config.DaoConfig.hibernateConfig; l'exception imbriquée est org.springframework.beans.factory.BeanCreationException: Erreur lors de la création du bean avec le nom 'com.bjk.observation.server.config.HibernateConfig # 0': l'instanciation du bean a échoué; l'exception imbriquée est org.springframework.beans.BeanInstantiationException: Impossible d'instancier la classe bean [com.bjk.observation.server.config.HibernateConfig]: le constructeur a levé l'exception; exception imbriquée est java.lang.NullPointerException

Répondre

2

Le problème, je crois est ici:

@Autowired 
private DataSourceConfig dataSourceConfig; 

Vous n'êtes pas censé vous câbler explicitement avec d'autres @Configuration cours -annotated, mais plutôt les haricots ils produisent. Le printemps triera la plomberie pour vous.

donc le champ remplacer ci-dessus avec le plus simple:

@Autowired 
private DataSource dataSource; 

printemps va chercher la DataSource de DataSourceConfig et injecter de manière transparente dans le champ.

De même, remplacez

@Autowired 
private HibernateConfig hibernateConfig; 

avec

@Autowired 
private HibernateTemplate hibernateTemplate; 

Vous remarquerez que le style @Configuration ne se sent pas aussi agréable lorsque l'on travaille avec des haricots d'usine comme AnnotationSessionFactoryBean, puisque vous avez souvent appeler getObject() sur vous-même. Parfois, il est plus naturel d'utiliser la config XML et de la mélanger avec le style java config.

+3

Je ne sais pas pourquoi cela aiderait exactement parce que les classes marquées avec @Configuration sont censées être des haricots dans leur propre droit. Néanmoins, j'ai essayé comme vous l'avez suggéré et même si mon journal des erreurs est différent, cela a toujours à voir avec les beans qui ne sont pas initialisés dans le bon ordre. (Débogueur le confirme.) Je prends note que @Configuration n'est pas aussi bien pour les beans factory et en fait, je suis tombé sur une vieille configuration xml fiable, mais je voudrais quand même comprendre comment ça fonctionne _supposed_. – jhericks

Questions connexes