title: Stopping Tomcat Doesn't Delete Derby db.lck
body: <p>(Edit: I've added a bounty to the question. I found a workaround (posted as an answer below), but I'm hoping somebody can explain why the workaround was necessary in the first place.)</p>
  
  <p>I have a Spring webapp that connects to a Derby database during development. This works fine the first time I run the webapp, but in subsequent runs it fails during startup with the "Another instance of Derby may have already booted the database" SQLException.</p>
  
  <p>I understand that this is because the connection to Derby isn't being closed when I shutdown Tomcat, even though I would expect Spring to handle that automatically. So my question is, how do I disconnect from Derby correctly? Not only during manually stopping Tomcat, but also during hot deploying of a new .war file?</p>
  
  <p>I'd like to avoid using a Derby server, and I'm also using annotations instead of XML configuration. Here was my original PersistConfig class:</p>
  
  <pre><code>package com.example.spring.config;
  
  import java.beans.PropertyVetoException;
  import java.sql.DriverManager;
  import java.sql.SQLException;
  import java.util.Properties;
  
  import javax.sql.DataSource;
  
  import org.apache.derby.jdbc.EmbeddedDataSource;
  import org.hibernate.SessionFactory;
  import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.ComponentScan;
  import org.springframework.context.annotation.Configuration;
  import org.springframework.jdbc.datasource.SimpleDriverDataSource;
  import org.springframework.jdbc.datasource.embedded.ConnectionProperties;
  import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
  import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseConfigurer;
  import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
  import org.springframework.orm.hibernate4.HibernateExceptionTranslator;
  import org.springframework.orm.hibernate4.HibernateTransactionManager;
  import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
  import org.springframework.orm.jpa.JpaVendorAdapter;
  import org.springframework.orm.jpa.vendor.Database;
  import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
  import org.springframework.transaction.annotation.EnableTransactionManagement;
  
  @Configuration
  @ComponentScan({"com.example.spring.dao.jpa"})
  @EnableTransactionManagement // &lt;-- enable @Transactional annotations for spring @Component and stereotypes
  public class PersistConfig{
  
  
      @Bean
      public HibernateExceptionTranslator exceptionTranslator() {
          return new HibernateExceptionTranslator();
      }
  
      @Bean
      public LocalSessionFactoryBean localSessionFactoryBean(DataSource dataSource, JpaVendorAdapter vendorAdapter) {
          LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
          localSessionFactoryBean.setDataSource(dataSource);
          localSessionFactoryBean.setPackagesToScan("com.example.one", "com.example.two");
  
          Properties properties = new Properties();
          properties.putAll(vendorAdapter.getJpaPropertyMap());
          localSessionFactoryBean.setHibernateProperties(properties);
  
          return localSessionFactoryBean;
      }
  
      @Bean
      public HibernateTransactionManager hibernateTransactionManager(SessionFactory sessionFactory) {
          HibernateTransactionManager hibernateTransactionManager = new HibernateTransactionManager(sessionFactory);
  
          return hibernateTransactionManager;
      }
  
      @Configuration
      public static class DevelopmentConfig{
          @Bean
          public DataSource dataSource() throws SQLException, PropertyVetoException {
  
  
  
              DataSource dataSource = new SimpleDriverDataSource(new org.apache.derby.jdbc.EmbeddedDriver(), "jdbc:derby:C:\\Users\\Kevin\\Desktop\\DerbyDB", "", "");
  
              System.out.println("RETURNING DATASOURCE");
  
              return dataSource;
  
          }
  
          @Bean
          JpaVendorAdapter vendorAdapter() {
              HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
  
              vendorAdapter.setDatabase(Database.DERBY);
              vendorAdapter.setDatabasePlatform("org.hibernate.dialect.DerbyDialect");
              vendorAdapter.setGenerateDdl(true);
              vendorAdapter.setShowSql(true);
  
              vendorAdapter.getJpaPropertyMap().put("hibernate.hbm2ddl.auto", "update");
              vendorAdapter.getJpaPropertyMap().put("hbm2ddl.auto", "update");
  
              return vendorAdapter;
          }
      }
  }
  </code></pre>
  
  <p>I tried adding a shutdown hook to the whole JVM using Runtime.addShutdownHook() where I manually disconnect from the Derby database, but that is seemingly never fired.</p>
  
  <p>I was then told to look into the EmbeddedDatabaseConfigurer interface to add a Spring shutdown callback where I manually close the database connection, and this is what I came up with:</p>
  
  <pre><code>package com.example.spring.config;
  
  import java.beans.PropertyVetoException;
  import java.sql.DriverManager;
  import java.sql.SQLException;
  import java.util.Properties;
  
  import javax.sql.DataSource;
  
  import org.apache.derby.jdbc.EmbeddedDataSource;
  import org.hibernate.SessionFactory;
  import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.ComponentScan;
  import org.springframework.context.annotation.Configuration;
  import org.springframework.jdbc.datasource.SimpleDriverDataSource;
  import org.springframework.jdbc.datasource.embedded.ConnectionProperties;
  import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
  import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseConfigurer;
  import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
  import org.springframework.orm.hibernate4.HibernateExceptionTranslator;
  import org.springframework.orm.hibernate4.HibernateTransactionManager;
  import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
  import org.springframework.orm.jpa.JpaVendorAdapter;
  import org.springframework.orm.jpa.vendor.Database;
  import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
  import org.springframework.transaction.annotation.EnableTransactionManagement;
  
  @Configuration
  @ComponentScan({"com.example.spring.dao.jpa"})
  @EnableTransactionManagement // &lt;-- enable @Transactional annotations for spring @Component and stereotypes
  public class PersistConfig implements EmbeddedDatabaseConfigurer {
  
  
      @Bean
      public HibernateExceptionTranslator exceptionTranslator() {
          return new HibernateExceptionTranslator();
      }
  
      @Bean
      public LocalSessionFactoryBean localSessionFactoryBean(DataSource dataSource, JpaVendorAdapter vendorAdapter) {
          LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
          localSessionFactoryBean.setDataSource(dataSource);
          localSessionFactoryBean.setPackagesToScan("com.example.one", "com.example.two");
  
          Properties properties = new Properties();
          properties.putAll(vendorAdapter.getJpaPropertyMap());
          localSessionFactoryBean.setHibernateProperties(properties);
  
          return localSessionFactoryBean;
      }
  
      @Bean
      public HibernateTransactionManager hibernateTransactionManager(SessionFactory sessionFactory) {
          HibernateTransactionManager hibernateTransactionManager = new HibernateTransactionManager(sessionFactory);
  
          return hibernateTransactionManager;
      }
  
      @Configuration
      public static class DevelopmentConfig{
          @Bean
          public DataSource dataSource() throws SQLException, PropertyVetoException {
  
  
  
              DataSource dataSource = new SimpleDriverDataSource(new org.apache.derby.jdbc.EmbeddedDriver(), "jdbc:derby:C:\\Users\\Kevin\\Desktop\\DerbyDB", "", "");
  
              System.out.println("RETURNING DATASOURCE");
  
              return dataSource;
  
          }
  
          @Bean
          JpaVendorAdapter vendorAdapter() {
              HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
  
              vendorAdapter.setDatabase(Database.DERBY);
              vendorAdapter.setDatabasePlatform("org.hibernate.dialect.DerbyDialect");
              vendorAdapter.setGenerateDdl(true);
              vendorAdapter.setShowSql(true);
  
              vendorAdapter.getJpaPropertyMap().put("hibernate.hbm2ddl.auto", "update");
              vendorAdapter.getJpaPropertyMap().put("hbm2ddl.auto", "update");
  
              return vendorAdapter;
          }       
      }
  
      @Override
      public void configureConnectionProperties(ConnectionProperties properties, String databaseName) {
  
          System.out.println("CONFIGURE");
  
          properties.setDriverClass(org.apache.derby.jdbc.EmbeddedDriver.class);
          properties.setUrl("jdbc:derby:C:\\Users\\Kevin\\Desktop\\DerbyDB");
      }
  
      @Override
      public void shutdown(DataSource ds, String databaseName) {
  
          System.out.println("SHUTTING DOWN");
  
          try {
              DriverManager.getConnection("jdbc:derby:C:\\Users\\Kevin\\Desktop\\DerbyDB;shutdown=true");
          } 
          catch (SQLException e) {
              e.printStackTrace();
          }
      }
  
  }
  </code></pre>
  
  <p>However, neither the configureConnectionProperties() function nor the shutdown() function seem to be called. I obviously don't know what I'm doing, so any pointers are greatly appreciated.</p>