April 18, 2010

Groovy Goodness: Configuring Grape to Use Classloader

Groovy has Grape to define dependencies which are necessary for our code to be downloaded by Ivy. This way we don't have to distribute third-party libraries with our code, but we only have to define the dependencies in our code. We can define these dependencies with the @Grab annotations. If we want to define multiple @Grab annotation we can group them together within a @Grapes annotation.

By default the dependencies are available in the same classloader as our Groovy script or application. But sometimes this is not enough. For example if we have a script with a dependency on a SQL database driver and in our code java.sql.DriverManager.getConnection() is used we want our driver class to be on the system classloader. That is because the DriverManager class only can 'see' classes in the system classloader and not other classloaders. A possible exception we get is java.sql.SQLException: No suitable driver found.

To support this scenario we add the @GrabConfig annotation and define that the dependency is part of the system classloader. And we are ready to use the dependency in our script.

 @GrabConfig(systemClassLoader = true)
import org.slf4j.*
import groovy.sql.*

def logger = LoggerFactory.getLogger('sql')

logger.info 'Initialize SQL'

def username = args[0]  // First argument passed to script.
def password = args[1]  // Second argument passed to script is password.
def sql = Sql.newInstance('jdbc:mysql://localhost/test', username, password, 'com.mysql.jdbc.Driver')

logger.info "Got myself a SQL connection: $sql"