Friday, December 31, 2010

groovy: get your classpath right!

Here’s some basic, basic groovy code with a simple SQL query to retrieve some data from an oracle DB:
import groovy.sql.Sql
def sql = Sql.newInstance("jdbc:oracle:thin:@hostname:1521:testdb", "user", "pass", "oracle.jdbc.driver.OracleDriver")

def query = "select * from tablename where name='Beta 1'"

row = sql.firstRow(query)

println row

However, despite various attempts, I couldn’t even establish a DB connection because of this annoyingly persistent exception:
Caught: java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver
        at sql1.run(sql1.groovy:13)

So of course, I immediately googled the rather-descriptive error message, and quickly learnt that Groovy didn't know where to find the oracle jdbc driver. With a few more searches, I discovered that the missing driver was located inside a jar that was called something like “ojdbc14.jar” or something.

I found where the jar was on my file system:
”C:\Users\ambars\.m2\repository\com\oracle\ojdbc14\10.2.0.1.0” contained ojdbc14-10.2.0.1.0.jar that seemed like a good candidate for the jar containing the required oracle jdbc driver. Seemed like I’m making progress, good.

Now how could I tell Groovy/Java to search this path? I figured that I had to include the jar’s file-system path into my Java CLASSPATH, so that groovy would know where to find missing classes.

Okay, so I added “C:\Users\ambars\.m2\repository\com\oracle\ojdbc14\10.2.0.1.0” to my CLASSPATH environment variable, but that didn’t seem to work.

Still no good :-(

Hmmm, “groovy –h” indicates that I can specify a classpath on the command line with the –cp or –classpath parameters. So let’s try that:
$ groovy -classpath C:\Users\ambars\.m2\repository\com\oracle\ojdbc14\10.2.0.1.0  sql1.groovy
Caught: java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver
at sql1.run(sql1.groovy:2)

Dammit work already! :P

I realized that I must be missing something very basic. It had to be a total n00b Java/Groovy problem. C’mon it can’t really be so hard to specify a path can it?!?

So I started googling about setting the java CLASSPATH correctly and then I stumbled on why it wasn’t’ working for me:


JARs on the classpath
Java compiler and run-time can search for classes not only in separate files, but also in `JAR' archives. A JAR file can maintain its own directory structure, and Java follows exactly the same rules as for searching in ordinary directories. Specifically, `directory name = package name'. Because a JAR is itself a directory, to include a JAR file in the class search path, the path must reference the JAR itself, not the directory that contains the JAR. This is a very common error.

Suppose I have a JAR jarclasses.jar in directory /jarclasses. The Java compiler look for classes in this jar, we need to specify:

javac -classpath /jarclasses/jarclasses.jar
and not merely the directory jarclasses.

Thank you, http://www.roseindia.net/java/java-classpath.shtml, for saving me from a lot of frustration!
Voila! Finally it works!
$ groovy -classpath C:\Users\ambars\.m2\repository\com\oracle\ojdbc14\10.2.0.1.0\ojdbc14-10.2.0.1.0.jar sql1.groovy
[NAME:Summary, PATH:Snapshot, MAPPINGKEY:26, VERSION:v9]

It’s even easier with the CLASSPATH environment variable set correctly like this:
CLASSPATH=C:\Users\ambars\.m2\repository\com\oracle\ojdbc14\10.2.0.1.0\ojdbc14-10.2.0.1.0.jar;

Now I don’t even have to type the –classpath parameter out on the command line each time:
$ set | findstr CLASSPATH
CLASSPATH=C:\Users\ambars\.m2\repository\com\oracle\ojdbc14\10.2.0.1.0\ojdbc14-10.2.0.1.0.jar;C:\Program Files\Java\jre6\lib\ext\QTJava.zip;.

$ groovy sql1.groovy
[NAME:Summary, PATH:Snapshot, MAPPINGKEY:26, VERSION:v9]

Tuesday, December 28, 2010

windows: setting environment variables from the command line

The standard route is rather slow and painful, even on Win7:
“MyComputer | Properties | Advanced System Settings | Environment Variables”… that’s a lot of clicks just to get to the point where you can add/edit an environment variable.

Thankfully, there’s a much easier alternative via the command line.

But first, did you know where the environment variables are stored on the file system? Until now I thought they were in some system config file, but it turns out they're actually stored in the registry itself (which technically is a system config file).
  • The logged-in user’s env variables go here:
    HKEY_CURRENT_USER\Environment
  • The machine-wide env variables go here:
    HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
The setx utility lets you change env variables for either the user or machine. The good old set command let’s you add/edit env variables too, but there are a few major differences from setx:
  • setx will permanently change the value of an env variable. The changes made by set last only for the current session.
  • Changes made by setx are not immediately visible – that is, they are not available to the current session. However, set’s changes are immediately visible.
  • You can’t delete env variables with setx, like you can with set. For example:
    set someVar=
    will delete the environment variable ‘someVar’ for the current session, but you can’t do something like this with setx.

    Instead, you have to use the “reg” utility to delete environment variables (that may or may not have been created with setx):
    REG delete HKCU\Environment /V someVar
Okay, so do you create a permanent environment variable via setx? It’s pretty straightforward:
  • To set an env variable for the current user:
    SETX <Variable> <Value>
  • To set an env variable for the machine (i.e. globally):
    SETX <Variable> <Value> -m
Example:
setx  CLASSPATH  C:\Users\ambars\.m2\repository\com\oracle\ojdbc14\10.2.0.1.0\ojdbc14-10.2.0.1.0.jar;C:\Program Files\Java\jre6\lib\ext\QTJava.zip;.

source: http://ss64.com/nt/setx.html