Quercus

Drupal on Glassfish with clean urls using Url Rewrite Filter

You have a Glassfish server.

You are a Drupal developer.

You want to run Drupal in Glassfish. More importantly, you want to have it use clean urls because without that capability, all of your urls look like this: /index.php?foo/bar/baz. Which sucks, of course.

Let's set aside for the moment the desirability of running PHP in a Java application container for the moment1, and jump right to the meat of this geeky post. Here's how I got some of the clean url functionality you'd normally get from Apache's mod_rewrite, or using either mod_rewrite or Lua in lighttpd.

I'm assuming you've already got Glassfish installed, so from there:

  1. Get a copy of Quercus, Caucho's Java implementation of PHP 5. I downloaded the version 3.2.1 .war file.
  2. Unzip the .war:2
    jar -xvf quercus-3.2.1.war

  3. Get a copy of Url Rewrite Filter. I used version 3.2.0 (beta), but 2.6 should work also.
    > cd quercus-3.2.1
    > wget http://urlrewritefilter.googlecode.com/files/urlrewritefilter-3.2.0-src.zip
    > unzip urlrewritefilter-3.2.0-src.zip
  4. Get Drupal. I used the latest 6.x version.:
    > cd ../
    > wget http://ftp.drupal.org/files/projects/drupal-6.10.tar.gz
    > tar zxvf drupal-6.10.tar.gz
     
    Copy Drupal files to the quercus docroot
    > cp -r drupal-6.10/* quercus-3.2.1/
  5. Configure Url Rewrite Filter. This is where it gets a little sketchy. Drupal comes prepackaged with a .htaccess file, which sets up the mod_rewrite rules for Apache:
    # Rewrite current-style URLs of the form 'index.php?q=x'.
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

    Unfortunately, Url Rewrite Filter doesn't support the REQUEST_FILENAME directive (yet). So I've put in some hacks to at least get clean urls working. I don't pretend that this is production-ready, but it gets it working for basic testing. If anyone has input, I'd welcome it. Anyway, in the WEB-INF/web.xml file, the following directives need to be added:
    <filter>
      <filter-name>UrlRewriteFilter</filter-name>
      <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
    </filter>
    <filter-mapping>
      <filter-name>UrlRewriteFilter</filter-name>
      <url-pattern>/*</url-pattern>
    </filter-mapping>

    This should go before the <servlet></servlet> section.

    Next, create WEB-INF/urlrewrite.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE urlrewrite
    PUBLIC "-//tuckey.org//DTD UrlRewrite 2.6//EN"
    "http://tuckey.org/res/dtds/urlrewrite2.6.dtd">
    <urlrewrite>
      <rule>
        <note>
          Prevent rewriting of specific files. Definitely not
          the best way to do this.
        </note>
        <from>^/(.*)(css|js|png|jpg|gif)$</from>
        <to>/$1$2</to>
      </rule>
      <rule>
        <note>
          Prevent rewriting of files in the files directory
        </note>
        <from>^/(.*)/files/(.*)$</from>
        <to>/$1/files/$2</to>
      </rule>
      <rule>
        <note>
          Do the Drupaly stuff
        </note>
        <from>^/(.*)$</from>
        <to>/index.php?q=$1</to>
      </rule>
    </urlrewrite>
  6. Re-zip your directory back into a .war file to deploy onto the app server:
    >jar -cvf quercus-3.2.1.war quercus-3.2.1/*
  7. Deploy to Glassfish through the admin console, or from the auto-deploy directory. Note that you should set your context-root to / to run Drupal at the root of the app server.
  8. Oh yeah, you'll probably want to connect to a database too, right? In the admin panel, go to Resources > JDBC > Connection Pools and create a new Connection Pool. Let's call it mysqlpool.

    Set Datasource Classname to com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource.

    Plug in the following Additional Parameters for your Drupal DB:

    password
    user
    databaseName
    portNumber
    serverName

That should be about it.

1: There are a couple of reasons I think this is interesting. First, Caucho claims that Quercus should run PHP apps as least as fast as Apache + APC, and I've seen numbers of 24-56% faster for the same complex app. Second, you can use Java functions natively from within PHP. Working in an environment with a lot of Java code, that's potentially appealing, especially for complex scientific functions I don't really want to re-implement in PHP. Third, the ability to deploy a .war file containing the whole Drupal docroot is also interesting.

2: I expect that most Drupal developers aren't using IDEs like Eclipse or NetBeans, so I'm just using command-line tools here.