Search code examples
javamysqlspringhibernatestartup

Test database availability on server startup


I'm developing a Spring webapp that uses Hibernate. Currently, if my MySQL database is not available (for example simply not launched), the server starts up normally, and an exception get thrown the first time an Hibernate query gets triggered.

Is there any way to rather check the database availability at server startup?

Here is my current applicationContext:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close"
    p:driverClassName="${jdbc.driver}"
    p:url="${jdbc.url}"
    p:username="${jdbc.user}"
    p:password="${jdbc.password}"
    p:maxActive="${dbcp.maxActive}"
    p:maxIdle="${dbcp.maxIdle}"
    p:maxWait="${dbcp.maxWait}" />

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"
    p:dataSource-ref="dataSource"
    p:packagesToScan="com.myapp.data.domain">
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
            <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
            <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
            <prop key="hibernate.generate_statistics">${hibernate.generate_statistics}</prop>
        </props>
    </property>
</bean>

<bean id="hibernateTransactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"
    p:sessionFactory-ref="sessionFactory" />

<tx:annotation-driven transaction-manager="hibernateTransactionManager" />

Solution

  • You can create a simple bean that validates the dataSource in a method that is invoked after all properties are set. This is possible with the @PostConstruct annotation or by implementing InitializingBean. With annotations this might look like this:

    @Compontent
    public class DataSourceValdationBean {
    
      private DataSource dataSource;
    
      @Autowire
      public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
      }
    
      @PostConstruct
      public void validateDataSource() {
        try {
           Connection c = dataSource.getConnection();
           Statement s = c.createStatement();
           s.excuteQuery("SELECT 1");  // you have to change this depending on your DBMS
        } catch (SQLException | SQLTimeoutException e) {
           // log error and throw exception
        }
      }
    
    }