Archive for March, 2009

Tomcat ROOT.war deployment

If you wish to avoid having to deploy a web application explicitly named as ROOT.war – so that you use the default context URL “/” without having to resort to web server URL rewrites – it’s possible to do this and still maintain your application war files original name.

I thought it was worth writing about our approach to this as the Tomcat documentation isn’t particularly clear on how to achieve this.

As some background information, I work for a large FTSE100 company where a team other than the Development Team are responsible for the deployment of the application, and handing them a file called ROOT.war is a little unclear and could potentially lead to misunderstandings.

It’s possible to have the application context file point to a .war file outside of the Tomcat/webapps directory. Tomcat will then explode your war file, whatever it’s name, into the Tomcat/webapps/ROOT directory. Tomcat infers from the name of the context file that web application should be deployed as the default, accessible as root context “/”, without any need for web server URL rewrites.

<Context docBase="/<external_build_dir>/<application_name>.war" />

where <external_build_dir> can be any directory outside of Tomcat, for example your application build directory, and <application_name> can be the proper full name of your application.

If you are using Apache Ant deployment scripts, you can also make good use of a couple of features to automate this whilst maintaining naming clarity. We have a simple application context file <application_name>.xml:

<Context docBase="@DEPLOY_FILE@" />

and the associated application deployment script copies this file to the Tomcat conf directory, renaming it as ROOT.xml as so:

<copy file="${ant.project.name}.xml" tofile="${tomcat}/conf/Catalina/localhost/ROOT.xml">
  <filterset>
    <filter token="DEPLOY_FILE" value="${project.name}.war"/>
  </filterset>
</copy>

As you can see it’s also using Ant’s filter task with a token to express the location of the application war file, pointing back at the build directory.

Of course, you can still use an Apache HTTP web server RewriteRule to serve your application from “/”, but this would apply to every request served:

RewriteRule /<application_name>/(.*) /$1

BOOTNOTE: Thanks to pid-2 for pointing out my initial mistake in this post.

There’s no need to set the path attribute of the context xml file, in fact Tomcat specifically states that you should not do this. The fact that you have a context file called ROOT.xml is enough for Tomcat to infer that you wish to deploy the web application as the root “/”.

Tags: , ,

Saturday, March 21st, 2009 Tomcat 2 Comments

Primary Keys vs GUIDs

Just thought I would post some code having read Savvy Duck’s comments about the above. Although the project I refer to below was greenfield and didn’t require any kind of database migration, I never encountered any of the performance problems mentioned in some of the related articles.

We were using an Oracle 10g database however, and I’ll report an update if I see any issues with my latest project which is on MySQL and seems to have a bit of a history in this department. But it really was never an issue in any way that we recognized.

The likelihood of a primary key clash was calculated as 1 in 2.27 x 10exp32 for every one million records.

Anyway, the code. We were mapping to Java using Hibernate (avoiding the primary key problem mentioned here) like so:

public abstract class BasePersistentObject implements Serializable
{
    // will be overrriden with data read from database
    @Id
    private String id = UUID.createUUID();
}

I can provide the above UUID code if anyone wants to have a play with this implementation.

Instead of using the standard auto-increment Sequence then, the primary key was implemented with the following function:

/**
 * Returns a UID string.
 *
 * This is string based on a randomly generated bit sequence just like in the app server.
 */
CREATE OR REPLACE FUNCTION f_get_uid RETURN VARCHAR2 IS
BEGIN
	RETURN UTL_RAW.CAST_TO_VARCHAR2(
	           UTL_RAW.TRANSLATE( DBMS_CRYPTO.RANDOMBYTES(24),
	                              uid_util.uid_from_set,
	                              uid_util.uid_to_set ) );
END;
/

-- defines two constants used by f_get_uid() to generate UID strings;
CREATE OR REPLACE PACKAGE uid_util
IS
	uid_from_set CONSTANT RAW(256) := UTL_RAW.XRANGE(hextoraw('00'), hextoraw('FF'));
	uid_to_set   CONSTANT RAW(256) := UTL_RAW.CONCAT(
		UTL_RAW.CONCAT(
			UTL_RAW.XRANGE(UTL_RAW.CAST_TO_RAW('A'), UTL_RAW.CAST_TO_RAW('Z')),
			UTL_RAW.XRANGE(UTL_RAW.CAST_TO_RAW('a'), UTL_RAW.CAST_TO_RAW('z')),
			UTL_RAW.XRANGE(UTL_RAW.CAST_TO_RAW('0'), UTL_RAW.CAST_TO_RAW('9')),
			UTL_RAW.CAST_TO_RAW('-'),
			UTL_RAW.CAST_TO_RAW('_')
		),
		UTL_RAW.CONCAT(
			UTL_RAW.XRANGE(UTL_RAW.CAST_TO_RAW('A'), UTL_RAW.CAST_TO_RAW('Z')),
			UTL_RAW.XRANGE(UTL_RAW.CAST_TO_RAW('a'), UTL_RAW.CAST_TO_RAW('z')),
			UTL_RAW.XRANGE(UTL_RAW.CAST_TO_RAW('0'), UTL_RAW.CAST_TO_RAW('9')),
			UTL_RAW.CAST_TO_RAW('-'),
			UTL_RAW.CAST_TO_RAW('_')
		),
		UTL_RAW.CONCAT(
			UTL_RAW.XRANGE(UTL_RAW.CAST_TO_RAW('A'), UTL_RAW.CAST_TO_RAW('Z')),
			UTL_RAW.XRANGE(UTL_RAW.CAST_TO_RAW('a'), UTL_RAW.CAST_TO_RAW('z')),
			UTL_RAW.XRANGE(UTL_RAW.CAST_TO_RAW('0'), UTL_RAW.CAST_TO_RAW('9')),
			UTL_RAW.CAST_TO_RAW('-'),
			UTL_RAW.CAST_TO_RAW('_')
		),
		UTL_RAW.CONCAT(
			UTL_RAW.XRANGE(UTL_RAW.CAST_TO_RAW('A'), UTL_RAW.CAST_TO_RAW('Z')),
			UTL_RAW.XRANGE(UTL_RAW.CAST_TO_RAW('a'), UTL_RAW.CAST_TO_RAW('z')),
			UTL_RAW.XRANGE(UTL_RAW.CAST_TO_RAW('0'), UTL_RAW.CAST_TO_RAW('9')),
			UTL_RAW.CAST_TO_RAW('-'),
			UTL_RAW.CAST_TO_RAW('_')
		)
	);
END;
/
Sunday, March 1st, 2009 Database 1 Comment

Agile CTO