0
votes

EDIT 1:

I'm currently calling this from a Main class like so:

public class Main
{
    public static void main(String[] args)
    {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringAppConfig.class);
        DataSource dSource = ctx.getBean(DataSource.class);
        System.out.println(dSource.getClass().toString());

        if (dSource instanceof Log4jdbcProxyDataSource)
        {
            Log4jdbcProxyDataSource log4jdbcProxyDataSource = (Log4jdbcProxyDataSource) dSource;
            Object lf = log4jdbcProxyDataSource.getLogFormatter();
            System.out.println(lf.getClass().toString());
        }

        System.exit(0);
}

}

Original:

Code follows after explanation:

I have a Spring application with a JavaConfig, call it the primary app, that imports another Spring JavaConfig class from a library. This imported JavaConfig is supposed to wrap any DataSource created in the primary app with an Aspect, which has an autowired LogDelegator.

As long as the primary app contains only a DataSource, everything works. But as soon as I add an EntityManager to the primary app, I get a nested IllegalArgumentException saying that the LogDelegator is null.

Primary App's Config:

@Configuration
@Import(MonitoringConfig.class)
public class SpringAppConfig
{
   @Bean
   public DataSource dataSource()
   {
      EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
      EmbeddedDatabase db = builder.setType(EmbeddedDatabaseType.H2).build();
      return db;        
   }
}

Imported Library Config:

@Configuration
@EnableSpringConfigured
public class MonitoringConfig extends WebMvcConfigurerAdapter
{
   @Bean
   public LogDelegator logDelegator()
   {
      return new LogDelegator();
   }

   @Bean
   public ConfigurationAspect configurationAspect()
   {
      return Aspects.aspectOf(ConfigurationAspect.class);
   }
}

The Aspect:

@Configurable
public aspect ConfigurationAspect
{
   @Autowired
   LogDelegator logDelegator;

   Object around() : execution(public DataSource (@Configuration *).*(..)) {

   Object ret = proceed();
   if (ret instanceof DataSource) {
      Log4jdbcProxyDataSource dataSource = new Log4jdbcProxyDataSource((DataSource) ret);
      dataSource.setLogFormatter(logDelegator);
      return dataSource;
   } else {
      return ret;
   }

}

This code works great until I add the following,

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory()
{
    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    vendorAdapter.setGenerateDdl(true);
    vendorAdapter.setDatabase(Database.H2);
    vendorAdapter.setShowSql(true);

    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
    factory.setDataSource(dataSource());
    factory.setJpaVendorAdapter(vendorAdapter);

    return factory;
}


@Bean
public EntityManager entityManager()
{
    return entityManagerFactory().getObject().createEntityManager();
}

@Bean
public PlatformTransactionManager transactionManager()
{
    JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
    jpaTransactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
    return jpaTransactionManager;
}

and then I get: java.lang.reflect.InvocationTargetException at java.lang.Thread.run(Thread.java:722) Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class SpringAppConfig: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [publ ic org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean com.fl.sas.configurable.config.SpringAppConfig.entityManagerFactory()] threw exception; ne sted exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class SpringAppConfig: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public javax.sql.DataSource SpringAppConfig.dataSource()] threw exception; nested exception is java.lang.IllegalArgumentException: log4j dbc: logDelegator cannot be null.

Can anyone help?

1
Can you specify to which Config class did you add the entitymanager? MonitoringConfig or SpringAppConfig. Also, how are these config classes being loaded? who's bootstraping the application context? - Akshay
Sure. The EntityManager and other code was added to SpringAppConfig. In this simple example, a Main class is bootstrapping the applicationcontext, although if I ever get it working it will be in a Spring MVC app. - cuttcards
Seems aspect is created after call datasource(). try settings a @Depends(value="configurationAspect") on datasource() - Luca Basso Ricci
That does it. Add the answer and I'll give the credit. - cuttcards

1 Answers

0
votes

I needed to add @Depends(value="configurationAspect") on dataSource()

Luca Basso Ricci answered the question. If he ever adds the answer, I'll give him the credit. :)