How to embed HSQLDB to file with Spring in WebApp

I have a webApp with Spring and it works correctly when I use HSQLDB in server mode, but in file mode it only skips the unit test. This is my data source:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="driverClassName" value="org.hsqldb.jdbcDriver" />

     <property name="url" value="jdbc:hsqldb:hsql://localhost/images" />
    <property name="username" value="sa" />
    <property name="password" value="" />
</bean>

      

I just change this line

   <property name="url" value="jdbc:hsqldb:hsql://localhost/images" />    
   ( -- Server mode)

      

for this

     <property name="url" value="jdbc:hsqldb:file:data/images" />      
     (-- In file)

      

And it just passes the unit test and doesn't work in the web app.

I suppose in file mode when I run the webapp HSQLDB does not find the database file.

I've already tried to put database data in webapp root and inside web-inf and it doesn't work.

+2


source to share


3 answers


It's good if you put the database in a jar like this:

<property name="url" value="jdbc:hsqldb:res:/data/images" />

      

You can use it read-only if you try to insert or modify the database if it fails.

One solution is to put the listener in web.xml, so when the application starts, it will be initialized with the root path of the web application.

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>maf</display-name>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>


     <!--This is to get root of the aplication-->

    <listener>
        <listener-class>
   org.atoms.HsqlDatabaseListener
        </listener-class>
    </listener>


       <!--Este listener se encarga de inicializar todo el contenedor de Spring y mantener una variable en el
  ServletContext que apunta a dicho contenedor -->

    <listener>
        <listener-class>
   org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>




</web-app>

      

Listener:



package org.atoms;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;


/**
 *
 * @author atomsfat
 */
public class HsqlDatabaseListener implements ServletContextListener {

    private ServletContext context = null;

    public void contextInitialized(ServletContextEvent event) {
        context = event.getServletContext();

        String prefix = event.getServletContext().getRealPath("/");

        System.out.println("database root " + prefix);
        com.atoms.HsqlDatabasePathResolver.getInstance(prefix);


    }

    public void contextDestroyed(ServletContextEvent event) {
        context = event.getServletContext();

    }

      

Another class:

package com.atoms;


/**
 *
 * @author atomsfat
 */
public class HsqlDatabasePathResolver {


    private static HsqlDatabasePathResolver instance ;
    private static String applicationPath = "";

    private HsqlDatabasePathResolver() {
    }

      /** Get Instance.
   */
    static public synchronized HsqlDatabasePathResolver getInstance(String applicationPath) {

        if (instance == null) {

            HsqlDatabasePathResolver.applicationPath =
                    HsqlDatabasePathResolver.normalizePath(applicationPath);
            instance = new HsqlDatabasePathResolver();



            System.out.println("Inizalizando path : " + HsqlDatabasePathResolver.applicationPath);

        }
        return instance;
    }

    public  String getApplicationPath() {
        return applicationPath;
    }



      public  String getUrlDatabase(String urlDatabase) {


         return HsqlDatabasePathResolver.replaceAll(urlDatabase,"{apppath}", applicationPath);
    }


      /**

         *
         * replace the "\" character by "/" and remove relative paths
         *
         * @param path
         * @return
         */
        public static String normalizePath(String path) {
            if (path == null) {
                return null;
            }
            String normalized = path;
            if (normalized.equals("/.")) {
                return "/";
            }
            if (normalized.indexOf('\\') >= 0) {
                normalized = normalized.replace('\\', '/');
            }
            if (!normalized.startsWith("/") && normalized.indexOf(':') < 0) {
                normalized = "/" + normalized;
            }
            do {
                int index = normalized.indexOf("//");
                if (index < 0) {
                    break;
                }
                normalized = normalized.substring(0, index) + normalized.substring(index + 1);
            } while (true);
            do {
                int index = normalized.indexOf("/./");
                if (index < 0) {
                    break;
                }
                normalized = normalized.substring(0, index) + normalized.substring(index + 2);
            } while (true);
            do {
                int index = normalized.indexOf("/../");
                if (index >= 0) {
                    if (index == 0) {
                        return null;
                    }
                    int index2 = normalized.lastIndexOf('/', index - 1);
                    normalized = normalized.substring(0, index2) + normalized.substring(index + 3);
                } else {
                    return normalized;
                }
            } while (true);
        }




        public static String replaceAll(String str, String match, String replace) {
            if (match == null || match.length() == 0) {
                return str;
            }
            if (replace == null) {
                replace = "";
            }
            if(match.equals(replace))return str;
            StringBuffer ret=new StringBuffer();
            int i = str.indexOf(match);
            int y = 0;
            while (i >= 0)
            {
                //System.out.println("i:"+i+" y:"+y);
                ret.append(str.substring(y, i));
                ret.append(replace);
                //str = str.substring(y, i) + replace + str.substring(i + match.length());
                y = i + match.length();
                i = str.indexOf(match,y);
            }
            ret.append(str.substring(y));
            return ret.toString();
        }



}

      

And this configuration I am using in spring:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
     xmlns:jee="http://www.springframework.org/schema/jee"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
               http://www.springframework.org/schema/context
               http://www.springframework.org/schema/context/spring-context-2.5.xsd
               http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">

     <!-- La definición del Datasource -->
        <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" lazy-init="true"
      destroy-method="close">
            <property name="driverClassName" value="org.hsqldb.jdbcDriver" />

          <property name="url">
               <ref bean="dataBaseUrl"/>
           </property>

            <property name="username" value="sa" />
            <property name="password" value="" />
        </bean>

     <!-- La definición del Factory de Session con Anotaciones -->
        <bean id="sessionFactory"
      class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" lazy-init="false">
            <property name="dataSource" ref="dataSource" />
            <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.dialect">
         org.hibernate.dialect.HSQLDialect
                    </prop>
                    <prop key="hibernate.show_sql">true</prop>
                    <prop key="hibernate.format_sql">true</prop>
                </props>
            </property>
            <property name="mappingResources">
                <list>
                    <value>Atoms.hbm.xml</value>
                </list>

            </property>
        </bean>
     <!--HibernaTemplate-->
        <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
            <property name="sessionFactory">
                <ref bean="sessionFactory" />
            </property>
        </bean>
     <!-- Definición de los DAO`s -->

        <bean id="ipBlancaDao" class="org.atoms.impl.AtomsDaoHibernateImpl">
            <property name="hibernateTemplate" ref="hibernateTemplate" />
        </bean>


        <!--If your are not running in Web this will initialize with the directory from    the  process was started note that this classes is a singleton so if you are running in web the listener already have initialize the class with the path of the class-->


        <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>


     <bean id="hsqlDatabasePathResolver" class="com.atoms.HsqlDatabasePathResolver" factory-method="getInstance" lazy-init="false">
            <constructor-arg>
                <value>${user.dir}</value>
            </constructor-arg>
        </bean>

   <!--This bean just replace {apppath} whit the absolute path-->

        <bean id="dataBaseUrl" class="java.lang.String" factory-bean="hsqlDatabasePathResolver" lazy-init="false"
                      factory-method="getUrlDatabase">
            <constructor-arg>
                <value>jdbc:hsqldb:mem:{apppath}/WEB-INF/data/maf</value>
            </constructor-arg>

        </bean>  
    </beans>

      

And yes this work, but a mess, I think the solution is a listener, with it you can get the path to appWeb. if someone can make it simple please post an answer.

+2


source


I found the answer here:

http://coding.derkeiler.com/Archive/Java/comp.lang.java.databases/2003-11/0096.html

I am putting data internally in a jar on my persistenceLayerWithData.jar project.

Then I set this propety to datasource:



<property name="url" value="jdbc:hsqldb:res:/data/images" />

      

And I added the jar to web-inf / lib and make war (all with maven) and deploy to tomcat and it works and also I deploy it to websphere 7 and also works.

But when I run whit mvn jetty: run it I don't believe that when I run whit maven jetty, it doesn't put the jar in the claspath.

+1


source


You must use an absolute file path. When you launch your web application, your "current" (or "working") directory is most likely bin

your application server folder. So when you give a relative path for the HSQLDB url, it tries to download that file from there, not somewhere relative to your webapp root.

0


source







All Articles