This article is based on Lift in Action, to be published on July 2011. It is being reproduced here by permission from Manning Publications. Manning publishes MEAP (Manning Early Access Program,) ebooks and pbooks. MEAPs are sold exclusively through Manning.com. All print book purchases include an ebook free of charge. When mobile formats become available all customers will be contacted and upgraded. Visit Manning.com for more information.
Connecting to a Database
Introduction
Because Lift runs in any servlet container, you have several options for getting a database connection—just as you would in a traditional Java application.
DataSource through Java Naming and Dictionary Interface (JNDI)
That’s one hell of a title but don’t worry—it’s far, far simpler than it sounds! JNDI is one of those technologies that has been kicking around in the Java ecosystem for a long time and has changed as the years have passed. These days, most people are familiar with using JNDI to get a DataSource object for their applications through a servlet or application container such as Jetty or Tomcat.
If you want to run your application from a DataSource supplied by your container, you only need to do one of two things. The first (and more traditional) option is to add a reference to your web.xml file as shown in listing 1. This sets up the JDBC reference so it can be located via JNDI.
Listing 1 DataSource wire-up in web.xml
<resource-ref> <res-ref-name>jdbc/liftinaction</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref>
The second and Lift-specific route is to add one line of code in your Lift Boot class, as shown in listing 2. This is my preferred option when using JNDI because it is more in keeping with the Lift idioms of Boot configuration.
Listing 2 JNDI wire-up in Boot
DefaultConnectionIdentifier.jndiName = "jdbc/liftinaction"
You will need to configure your container to actually provide this DataSource object. Unfortunately, this is very product specific so I won’t labor that here; check the online documentation for the container you’re using.
Application connection
If you would rather not use JNDI or you want a quick and easy way to set up your database connection, Lift provides a helpful wrapper around the Java DriverManager class. Listing 3 shows an example of the code you need to have in your Boot class.
Listing 3 DriverManager JDBC wire-up
import net.liftweb.mapper.{DB,DefaultConnectionIdentifier} #1 import net.liftweb.http.{LiftRules,S} #1 DB.defineConnectionManager(DefaultConnectionIdentifier, DBVendor) #2 LiftRules.unloadHooks.append( #3 () => DBVendor.closeAllConnections_!()) #3 S.addAround(DB.buildLoanWrapper) #4
As you can see, there is a little more going on here than in the JNDI example. For completeness I have included the import statements so that it is clear where the various types are held (#1). #2 defines a wire-up between the application-specific DBVendor (as defined in listing 4) and Lift‘s connection manager. #3 details what Lift should do when it’s shutting down in order to cleanly close any application database connections. #4 configures Lift‘s loan wrapper1 so that actions conducted on the DefaultConnectionIdentifier are transactional for the whole HTTP request cycle.
Listing 4 DBVendor definition
object DBVendor extends StandardDBVendor( Props.get("db.class").openOr("org.apache.derby.jdbc.EmbeddedDriver"), Props.get("db.url").openOr("jdbc:derby:lift_example;create=true"), Props.get("db.user"), Props.get("db.pass"))
Listing 4 demonstrates making an extension on the StandardDBVendor trait from Lift‘s Mapper. This handles connection pooling for you by using Apache Commons Pool so that everything is taken care of for you. This DBVendor pulls its connection string and credentials from a properties file. If the file and the key pair do not exist, it will failover onto using the in-memory Derby database.
JNDI OR APPLICATION CONNECTION?
Choosing between JNDI or application connection is something that causes a fair amount of debate among developers and infrastructure folks. Traditionally, getting DataSource objects through JNDI was seen as a preferred route because it negated hard-coding any kind of connection or drivers into your application. The value of this benefit, while still present for some people, has probably waned somewhat with most developers. If we were looking for a more tangible value, you would look to the honed connection pooling and distributed transactions. Some people find great value here, while others do not. With libraries like Apache Commons Pool, it’s fairly simple to implement robust connection pooling in your application directly. So there is no real answer—it depends where and what you are deploying as to which will work best. To that end, keep abreast of both approaches and see what works for you.
In the code for the tutorial online, you will see that both mechanisms are supported within the application. JNDI is actually my preferred route for deployment, but many Lift sites run perfectly well on application connections.
Summary
We have covered options for getting a database connection through JNDI. You can add a reference to the web.xml file or add one line of code in the Lift Boot class.