Spiral Arm Logo

Richard's technical notes

Monday, April 30, 2007

Container Services

You don't need to use all of Java EE to build an enterprise application. Partly because of that I've always been nervous of big EE application servers such as JBoss, Glassfish, OC4J, WebLogic, WebSphere, and instead I've preferred mixing and matching open source libraries and stand-alone components. Or maybe I just don't need the features, or I've not run into scalability or transaction control that containers help manage, or maybe I'm not convinced on the benefits of a "single solution". So although I have ended up using them for some projects, I'm not sold on the need and I've never really thought they make life easier.

But lately I've started to come round to handing some responsibilities off to containers. One responsibility is web user authentication (a.k.a. login). It's a great example of saving time and improving quality, by leaving those aspects to tried-and-tested implementations provided by the application server. Unfortunately, form based authentication in the EE spec isn't flexible enough. Most people I know end up rolling their own solutions, which is a shame. Maybe it'll be usable one day...

There is one good example I've found where you can leave something to the container. If you have an application to deploy, and you want to deploy it on a test machine and a production machine, it's very convenient to leave the database configuration to the container. That is: you build you application (say, a WAR file) and then you can drop it into a container on a QA machine and it'll pick up the connection settings for the QA database; drop it into the live environment and it'll pick up the live database settings. The configuration is in the container (once), not the application (each build), and so Mr Cock-Up is less likely to visit.

Here's how you do it with Tomcat 5.5 and Hibernate 3.0.x:
  1. Copy your JDBC driver and your connection pool into $TOMCAT/common/lib/ e.g., mysql-connector-java-3.0.14-production-bin.jar and c3p0-0.9.0.4.jar for example.

  2. In Tomcat's server.xml, in the <GlobalNamingResources> section add:

    <Resource name="jdbc/MYPROJECT-database"
    description="My Project Database Connection"
    driverClass="com.mysql.jdbc.Driver"
    maxPoolSize="25"
    minPoolSize="2"
    acquireIncrement="1"
    auth="Container"
    maxStatements="50"
    idleConnectionTestPeriod="3600"
    testConnectionOnCheckin="true"
    automaticTestTable="connection_test"
    maxIdleTime="21600"
    factory="org.apache.naming.factory.BeanFactory"
    type="com.mchange.v2.c3p0.ComboPooledDataSource"
    jdbcUrl="jdbc:mysql://localhost:3306/MYPROJECT?useUnicode=true&
    amp;characterEncoding=UTF-8&autoReconnect=true"
    user="myproj" password="trustno1" />

    Adjust parameters to taste. What's going on here, is that the Apache BeanFactory is creating an instance of ComboPooledDataSource and then trying to call setX methods
    on the instance from the attributes in this XML snippet. So check the API for your connection pool implementation to see what you can set.

  3. Create the webapp/META-INF/context.xml (or similar) with this content:

    <Context>
    <ResourceLink name="jdbc/MYPROJECT-database"
    global="jdbc/MYPROJECT-database"
    type="javax.sql.DataSource" />
    <Context>


    That tells Tomcat that this web application wants to access a global Tomcat resource called jdbc/MYPROJECT-database.
    When Tomcat deploys the WAR this file is copied to TOMCAT/conf/Catalina/localhost/YOUR-WAR-NAME.xml.

  4. If you're using Hibernate, modify the config file to ask the container for the connection:

    <property name="dialect">
    org.hibernate.dialect.MySQLDialect
    </property>
    <property name="hibernate.connection.datasource">
    java:comp/env/jdbc/MYPROJECT-database
    </property>

    ...ensuring that all the other database connection stuff (username etc) are removed.

That's it. Then when you run, if Hibernate needs a connection it asks Tomcat for jdbc/MYPROJECT-database and Tomcat gives back whatever the instance is set up to provide. Looks like it's doable in Jetty too.

Thursday, April 05, 2007

Microformats

Last night's Sussex Geek dinner featured Glenn Jones with a presentation on Microformats. I learned a lot in a short space of time.

My previous impression of microformats was that it was a kludgy way to piggyback contact and event details into HTML—clever and useful, admittedly, but a kludge nonetheless. But I was totally wrong. I recommend grabbing the PDF presentation and taking a look for yourself, but it turns out the attributes used to mark-up XHTML with contact details and the like are, for want of a better word, legitimate. For example, using the class attribute to identify a name of a person is fine: the XHTML spec describes class as good for pretty much any use: "The class attribute can be used for different purposes in XHTML, for instance as a style sheet selector (when an author wishes to assign style information to a set of elements), and for general purpose processing by user agents." Ah, so it's not just for CSS. Ok.

Adding to that are a couple more appealing features: the specs are short, look pretty straightforward to start using, and are based on existing standards such as vcard. The details are over at microformats.org. I'll add "hReview-ifying book write-ups" to my to do list...one day....

For me the most interesting part of the talk was idea of designing URLs so they look like API calls. The example given was along the lines of: http://somesite/tag/creative can be thought of as somesite.tags.getList("creative"). That works for me, and is probably a good rule of thumb for designing URLs. The tricky part comes with queries: how to incorporate do ANDs, ORs, ranges, etc. One option might be to use a builder pattern, such as /tags/creative/startingWith/c interpreted as tags.getList("creative").startingWith("c"). Another option would be convention where by the order of the elements of the URL have a meaning and you just need to know it. The example there would be http://traintimes.org.uk/brighton/london/08:30 means "list trains from Brighton to London, leaving Brighton at 08:30". Stuff to ponder.

Indeed, the evening left me with plenty of stuff to ponder: How does this relate to RSS? How does this tie up with RESTful web services. Stuff to ponder is a good sign, BTW.

Now we all need to go play with the Operator plugin for Firefox.

UPDATE: 19 April 2007, via Jeremy's twitterings, Picoformats look interesting.


Disclaimer: Glenn Jones is the Creative Director at Madgex, which is
Jane's new employer.