Search code examples
javahibernatedatabase-connectionhsqldb

DB lock acquisition failure with Jersey and Hibernate


I have problem with setting up my project on remote server running linux. It works fine locally on Windows.

My app is running on Jersey, Hibernate and file HSQLDB. I'm using maven tomcat plugin to develop it locally and deploy to my remote VPS. Locally I'm using mvn tomcat7:run, to deploy I'm using mvn tomcat7:redeploy.

Here is my hibernate config:

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- Database connection settings -->
        <property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
        <property name="connection.url">jdbc:hsqldb:file:data/HDB</property>
        <property name="connection.username">sa</property>
        <property name="connection.password"></property>

        <!-- JDBC connection pool (use the built-in) -->
        <property name="connection.pool_size">1</property>

        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.HSQLDialect</property>

        <!-- Enable Hibernate's automatic session context management -->
        <property name="current_session_context_class">thread</property>
        <property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>

        <property name="show_sql">true</property>

        <property name="hbm2ddl.auto">update</property>

        <mapping class="com.example.MyClass" />
    </session-factory>
</hibernate-configuration>

It works like charm locally, at startup it creates data folder in project root and stores DB files there, works great. However when I deploy it to remote server Tomcat throws this exception:

Caused by: org.hsqldb.HsqlException: Database lock acquisition failure: lockFile: org.hsqldb.persist.LockFile@803b3767[file =/data/HDB.lck, exists=false, locked=false, valid=false, ] method: openRAF reason: java.io.FileNotFoundException: /data/HDB.lck (No such file or directory)
        at org.hsqldb.error.Error.error(Unknown Source)
        at org.hsqldb.error.Error.error(Unknown Source)
        at org.hsqldb.persist.LockFile.newLockFileLock(Unknown Source)
        at org.hsqldb.persist.Logger.acquireLock(Unknown Source)
        at org.hsqldb.persist.Logger.open(Unknown Source)
        at org.hsqldb.Database.reopen(Unknown Source)
        at org.hsqldb.Database.open(Unknown Source)
        at org.hsqldb.DatabaseManager.getDatabase(Unknown Source)
        at org.hsqldb.DatabaseManager.newSession(Unknown Source)
        ... 74 more

Which wont let my app start. It creates data folder in myapp/WEB-INF/lib and puts HDB files there, however it looks like it cannot connect to database. Note that file =/data/HDB.lck which means absolute path - is it the reason of this error? Why Tomcat on Linux adds this slash before path? How to get rid of it? Why the same works on Windows?

Additionally web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">
    <display-name>My server</display-name>

    <filter>
        <filter-name>jersey</filter-name>
        <filter-class>com.sun.jersey.spi.container.servlet.ServletContainer</filter-class>

        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>com.example.rest</param-value>
        </init-param>

        <init-param>
            <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
            <param-value>true</param-value>
        </init-param>

    </filter>

    <filter-mapping>
        <filter-name>jersey</filter-name>
        <url-pattern>/api/*</url-pattern>
    </filter-mapping>

    <listener>
        <listener-class>com.example.HibernateListener</listener-class>
    </listener>

    <welcome-file-list>
        <welcome-file>gui.html</welcome-file>
    </welcome-file-list>
</web-app>

Also HibernateListener as it's referenced - it's used to setup database connection right after deployment:

public class HibernateListener implements ServletContextListener {

    public void contextInitialized(ServletContextEvent event) {
        Db.getSessionFactory();
    }

    public void contextDestroyed(ServletContextEvent event) {
        Db.getSessionFactory().close();
    }
}

Solution

  • It looks like the folder is read-only.

    You can use a variable that is defined in Tomcat properties as part of the db path in order to specify a different folder. For example

      <property name="connection.url">jdbc:hsqldb:file:${mydbpath}/data/HDB</property>