15 December 2007

How to set up a Derby server as a Tomcat application

What is Derby?

Derby is a 100% pure Java database engine. Its main strength is that it's embeddable, so if you have a standalone application that could benefit from keeping persistent data in a database but you don't want to have to set up a separate database server just to support it, Derby may be the answer. In the embedded mode your application starts Derby during initialization and shuts it down during termination. In the meantime it can work with database tables using SQL statements through a JDBC driver in the usual way.

Why this article?

Derby can also run as a network server, like any other database. Not only that, you can install it as a web application in a server such as Tomcat so that your database server is available whenever your web server is. In fact, the Derby distribution includes a WAR file that you can deploy that makes this very easy.

The problem is that Derby's documentation seems to concentrate on the embedded mode of operation and it's not easy to find information about setting it up as a Tomcat application without quite a bit of digging. Since I've been through this particular loop I decided to write this, partially as a reference for myself in case I need to do it again, and also for others needing to do the same thing.

This article describes the setup with Tomcat 6 running on Windows (XP Pro, specifically). Unix/Linux setup is similar and it shouldn't be a problem for anyone familiar with those systems to adapt the steps as required.

Download and unpack the distribution

Derby is distributed as a .zip or .tar.gz archive. There are a couple of different downloads available depending on whether you just want the executable JAR files or the full package including documents and sample code. Download the appropriate one then simply unpack it into a convenient place. I used the 'bin' distribution which includes everything.

The archive unpacks such that everything is inside one directory (the current version puts itself into 'db-derby-10.3.2.1-bin' for example, for the 'bin' distribution). This is Derby's 'home' directory, which we'll need to know in a moment.

Setting the environment and Java system properties

Derby only really needs one environment setting: DERBY_HOME should be set to the path of the home directory as noted above. On a Windows system use 'Control Panel-> System' then open the Advanced tab. You can add the new environment setting as a System or User value in the dialog there. 'System' is probably better, especially if you run Tomcat as a service.

You may also want to add %DERBY_HOME%\bin to your PATH setting; this isn't required but it makes it easier to run the Derby command-line tools.

One Java system property really needs to be set, too: derby.system.home identifies a directory where Derby will keep all its databases. Without this, when you run Derby under Tomcat it will default to '.', which equates to the Tomcat installation directory - the place where it keeps its conf and WebApps directories. This is almost certainly not a good idea (imagine what might happen if an application tries to create a database called 'conf').

I created a "DerbyData" directory to hold all my databases. Setting the derby.system.home property is a little bit of a problem, but I found a solution that works fine; Tomcat 5 and 6 include a "Monitor" program that you can run, at least on Windows. You can use this to set up the system properties (run the monitor, right-click on the system tray icon that appears, then open the 'Configure' option and click the 'Java' tab). Add -Dderby.system.home=your-database-directory to the system properties and click OK. Tomcat doesn't need to be running to do this.

Deploying derby.war

Start Tomcat (if it's already running you should probably shut it down and restart). Start your browser, find the Tomcat Manager page and log in.

Deploy the Derby WAR file in the usual way. You'll find the WAR file (derby.war) in Derby's lib directory.

You should now be able to hit the Derby service in your browser - it'll be at /derby/derbynet. This starts the database running, and if everything's ok you'll see a status page.

Modifying Derby's web.xml

We're not quite done yet. With the default installation you have to hit the Derby URL as above to start the database running every time you restart Tomcat. What's happening is that the database is started by the servlet's init() method, and that isn't happening until Tomcat gets a request. This probably isn't what you want, especially if you're planning to create other web applications that use the service. You probably want the thing to come up on its own.

You'll find Derby's web.xml file under your Tomcat installation at WebApps/derby/WEB-INF/web.xml. Open the file in a text editor and add the following tag inside the <servlet> tag:

<load-on-startup>0</load-on-startup>


This will cause Tomcat to call the servlet's initialization during startup instead of waiting for a request.

Save your text change and restart Tomcat.

Testing

After restarting Tomcat you should see a 'derby.log' file appear in your database directory. It may take a few seconds for this to happen, so give it time - if it hasn't shown up after, say, a minute, you may want to check your Tomcat logs to see if anything bad happened. Also, check your Tomcat directory to make sure the log file didn't show up there - if it did, it means that the derby.system.home setting hasn't taken for some reason, in which case you should go back and check for misspellings, etc.

If the log file appears in the right place, that probably means everything's ok so far. You can test the installation using Derby's ij command-line tool. Open a command window and do this (this assumes that you set the PATH environment as suggested earlier):

> ij
ij version 10.3
> connect 'jdbc:derby://localhost/testdata;create=true';
> exit;
>


This tells ij to open a connection to the database named 'testdata', creating it if it doesn't exist (which it shouldn't, at this point).

Now check your database directory - there should be a subdirectory called 'testdata' if all went well. You can delete it manually, although I'd recommend shutting Derby down first - either shut down Tomcat or hit the Derby URL as above and click the Stop button.

Congratulations! You now have a database server that will be available whenever Tomcat is running.

Labels: ,

Ginger 1.3 adds better handling of HTTP request methods

No plans for more changes in the near future

I realized after some thought that up until now Ginger was written with a bad assumption in the back of my mind - the assumption that it would only ever have to deal with GET and POST requests. This is not a good assumption, because there are six other types of request that it may have to deal with depending on how your servlet mappings are set up in the deployment descriptor.

HttpServlet is designed to identify the request type for you and takes default actions for the ones you don't explicitly set up to handle in a subclass, but for several reasons Ginger couldn't subclass from that. In fact, Ginger isn't a subclass at all, really - it just implements the Servlet interface directly.

So, in Ginger 1.3 I've added a mechanism to give you control over which HTTP request methods will be handled. By default, it will deal with GET, POST, HEAD, OPTIONS and TRACE. If it receives a request with a type not in that set, it'll respond with a 405 error. That means that by default your subclass servlet won't have to worry about CONNECT, DELETE and PUT requests.

You can change the set in your servletInit(), to define the set of requests you want your servlet to accept. Note though that Ginger itself will handle OPTIONS and TRACE requests in a way you can't override; it will automatically create responses and never calls any command methods for these requests. Also, by default it handles HEAD requests by running your configured commands in the normal way and rendering output from your templates, but the rendered data is only used to generate the character count for the response header - it isn't sent back to the client. (A nice benefit of the code change that makes this work is that Ginger now buffers the output internally for GET and POST responses; this makes it possible to set the response length, which in turn makes it possible for the servlet container to use a persistent connection, which in turn improves response times.) It is possible for your command methods to modify their behaviour for HEAD requests, but doing that really isn't recommended.

Another fairly big change I've made is to deprecate the Context class and replace it with a new class called Dynamic which is otherwise identical. The reason for this is that the name 'Context' is used in several packages all related to web applications - it's used in JNDI, servlet containers use the name to refer to a web application (Tomcat does, anyway), Velocity uses it to mean something completely different again, and there are probably other places too. That means you may have to fully-qualify com.codexombie.bohemia.ginger.Context in every command method that also accesses a JNDI context, for example. That's messy and error-prone, which is why I decided to make the change. Dynamic is so named because it's intended to hold dynamic data for the template merge (among other things) and I couldn't think of a better name that wasn't already in common use. Existing code can still use the old Context class but you'll get deprecation warnings, and in any case I don't intend to leave the deprecated code in place forever - it'll be removed entirely in a future release.

On the subject of future releases, I'm not planning to make any more changes for a while; the 1.3 release is the fourth in just a few weeks, which is a bit rushed. Unless I find that there's a major problem that needs fixing, there won't be any new releases for at least a couple of months (and even then, the only change may be to remove that deprecated code I mentioned).

The new release is, of course, available for download at the usual place.

Labels:

07 December 2007

Ginger 1.2

Adds basic JSP support

I've added very basic support for JSPs to Ginger through the addition of a new template processor. It's not intended to be a replacement for Velocity and doesn't indicate a shift in that direction - it's just to provide some level of support in case JSP is necessary for one or two pages in an application, and for some reason Velocity won't do what's needed. Check it out in the usual place.

I have no plans for further releases in the near future - I'm hoping it's stable enough to stand without more changes for a while to come.

Labels: