« JavaOne! | Main | Python development... »

EZ rollin HSQLDB

I'm messing around with HSQLDB because I need to create an easy-to-install demo-only version of Roller. I want to bundle everything needed to run Roller and make it drop-dead simple to try Roller on your own machine. All that you, the potential Roller user, will have to do is to unzip the distribution file and run a startup script.

To make this work I need Roller, a database, and a Web app server, all bundled together into one downloadable file. That is easy to do: I start with a Tomcat distribution and drop Roller into the webapps directory. When Tomcat starts, Roller will start. Roller won't function without a database, so I need to add the tiny pure-Java HSQLDB database to the mix. I need to get HSQLDB started before Roller starts. This part is not so easy: after looking at the HSQLDB docs I found that I have at least three options:

  1. Use the "in-memory" version of HSQLDB. With this approach, no HSQLDB starter is necessary. If you use a JDBC connect string of the form jdbc:hsqldb:filepath instead of the normal jdbc:hsqldb:hsql://host:port form, then HSQLDB will start itself inside your process (is that cool - or what!). The problem with this approach is that it requires the person who installs my demo to edit a file - they have to set the path to the HSQLDB, or I have to rely on an unreliable relative path. Another problem is that, in this mode, HSQLDB will not accept JDBC connections from other clients - such as the HSQLDB database manager.

  2. Add a ServletContextListener to Roller that starts the "standalone" server version of HSQLDB on it's own thread when my Web app starts, on contextInitialized(), and shuts down when my Web app stops, on contextDestroyed(). There are a couple of problems with this approach. First, I don't want to add anything to Roller. Second, I want the database to be available for other Web apps - like JSPWiki which I will include in the demo - to do authentication. Finally, after some experimentation I could not get HSQLDB starting ServletContextListener to start before the other parts of Roller that need a database connection.

  3. Add a LifecycleListener to the Tomcat server.xml to start the "standalone" server verion of HSQL on it's own thread when Tomcat starts. To enable this, I also add some -D startup parameters to catalina.sh to tell my listener where the database file is and what port to use.

Approach #3 seems to be the best option for the Roller Demo and it's working for me. Here is the code for the lifecycle listener that starts and stops HSQLDB:

import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;
import org.roller.util.HSQLDBUtility;

public class TomcatHSQLDBPlugin implements LifecycleListener {
   public void lifecycleEvent(LifecycleEvent event) {		
      if (event.getType().equals(Lifecycle.START_EVENT)) {
         HSQLDBUtility.start();
      }
      else if (event.getType().equals(Lifecycle.STOP_EVENT)) {
         HSQLDBUtility.stop();
      }
      else {
         System.out.println(getClass().getName()+": Not handling LifecycleEvent: "+event.getType());
      }
   }
}

To plug-in to the Tomcat startup and shutdown process, I had to do two things. First, I placed a jar with my TomcatHSQLDBPlugin and HSQLDBUtility classes in a jar in tomcat/server/lib. Second, I added the following XML to the tomcat/conf/server.xml file along side the listeners already in the file:

    <Listener className="org.roller.tomcat.TomcatHSQLDBPlugin" debug="0"/>

That's that. I've got this stuff working now. Next up: JSPWiki integration and then I'll make Roller-Demo available for download on SourceForge.

Comments:

You may not want to run your enterprise off it but HSQLDB is a very nice little database. I love the fact that it runs of just one jar.

Posted by Glen Stampoultzis on June 25, 2004 at 01:06 AM EDT #

Hi Dave, I've been trying to do something very similar today, unfortunately I couldn't find your HSQLDBUtility anywhere under the Roller CVS.. might have saved a little legwork. I used a slightly more generic context listener; it's a bit rough around the edges esp. the delay before creating the schema but by the book I've only today left to finish this project. Any ideas? glaring mistakes?

public class HSQLDBStartupListener implements ServletContextListener {
    static final String url = "/tmp/hsqldb";
    static final String port = "9001";

    public void contextInitialized(ServletContextEvent event) {
        Thread launchHsqldbThread = new Thread(new Runnable() {
            public void run() {
                String[] args = {"-database", url, "-port", port, "-no_system_exit"};
                org.hsqldb.Server.main(args);
            }
        });
        //thread.setDaemon(true);
        launchHsqldbThread.start();

        Thread initSchemaThread = new Thread(new Runnable() {
            public void run() {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace(System.err);
                }

                /* build our db schema if none exist.. yadda yadda */

            }
        });
        initSchemaThread.start();        
    }

    public void contextDestroyed(ServletContextEvent event) {
        try {
            Class.forName("org.hsqldb.jdbcDriver");
            Connection con = DriverManager.getConnection(url + ":" + port, "sa", "");
            String sql = "SHUTDOWN";
            Statement stmt = con.createStatement();
            stmt.executeUpdate(sql);
            stmt.close();
        } catch (ClassNotFoundException e) {
            e.printStackTrace(System.err);
        } catch (SQLException e) {
            e.printStackTrace(System.err);
        }
    }
}

- Richard

Posted by Richard Osbaldeston on June 25, 2004 at 04:19 PM EDT #

That is cool!! } Good stuff in Chinese.

Posted by Herman on July 05, 2004 at 12:55 PM EDT #

Uhm, I'm sorry for bugging you but I noticed that one can't leave comments to the most recent entry in my blog. Tried to report that to the Roller's JIRA issue tracker but couldn't enter the page due to a "Proxy Error". Just wanted to mention it :)

Posted by blackbird on July 06, 2004 at 06:51 PM EDT #

Post a Comment:
  • HTML Syntax: NOT allowed

« JavaOne! | Main | Python development... »

Welcome

This is just one entry in the weblog Blogging Roller. You may want to visit the main page of the weblog

Related entries

Below are the most recent entries in the category Roller, some may be related to this entry.