简体   繁体   中英

Spring: run code before a persistence context is loaded

I have spring based multimodule application. And in my DAO module the DB (embedded derby) is started and created by the class the implements ApplicationListener.

Problem that in the logs the huge stacktrace from Spring which say that there is no db(couldn't get connection).

Still, my application works without any problems. This stacktrace appeared before the ApplicationListener invoked and the db is created. Actually, I see it only when I am starting the application the first time on the machine, because the db created only this time, than it just used.

So my question is whow to avoid this exception in logs? Maybe there is spring or hibenate setup not connect to the db before the application context fully loaded? Or invoke the code that creates db by some other listener?

I suppose you are fetching some data from database from inside spring beans that are being created. Perhaps thru @PostConstruct or other way. Remember that until spring context is fully loaded some beans can have injected uninitialized beans.

So do not use DB, do not call any DAOs until you are sure that spring context is fully initialized.

To do such initial calls to DAOs try such patter that guarantees spring context completness:

@Component
public class SpringContextMonitor implements ApplicationListener<ApplicationEvent> {

  @Autowired
  private SomeDao dao;

  ...

  @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ContextRefreshedEvent) {
            onStart((ContextRefreshedEvent) event);
        }
    }

  private void onStart(ContextRefreshedEvent event) {

    // do your initialization here
    dao.getSomething();
    dao2.getSomething();
    ...

  }

  ...
}

The onStart method in above example is place where you are sure that all beans are fully initialized

Well here is the way I do : the ROOT context contains the datasource, the dao, the service and the transaction manager. In XML config, the declaration of the database is :

<bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"
      p:url="jdbc:derby:/path/to/database;create=TRUE" 
      p:username="user" p:password="pwd"
      p:driverClassName="org.apache.derby.jdbc.EmbeddedDriver"/>

it can then be used to declare a session factory for hibernate and an associated DAO as :

<bean class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"
      id="sessionFactory" p:dataSource-ref="datasource">
    <!-- hibernate config -->
    ...
</bean>
<bean class="org.springframework.orm.hibernate4.HibernateTransactionManager"
      name="transactionManager" p:sessionFactory-ref="sessionFactory"/>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="myDao" class="... .myDaoImpl" p:sessionFactory-ref="sessionFactory" .../>

That way all is created by spring, that ensures that the creation order is correct. Of course the same is possible in Java config with the same logic.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM