Setting CLASSPATH for directories and jars driving you crazy? I finally decided to do something about it.
The answer is some heavy-handed automation and convention. First, why bother trying to put files in the jre\lib\ext directory? Last I heard, there was some kind of security issue so it's prevented, maybe, in some cases. I don't want to have to know what those cases are.
Besides, you have to click down a bunch of directories to find jre\lib\ext, and at least on my system there always seems to end up being two of them, one for the JDK and one for the JRE, and half the time I put it in the wrong place. Too confusing, too much effort.
How about if all jar files just go in a directory called C:\jar? I don't think that will hurt anything, and it will be much easier to manage. Also, if you need to move your setup from your desktop to your laptop, all you have to do is copy that directory.
Well, almost. The other problem is that every time you add a new jar or a new directory to the CLASSPATH, you have to go in and set the environment variables on my computer, editing a really long line in a little tiny window. I'll be happy if I don't have to do that again.
Also, it's very easy to get incorrect and old, nonexistent elements in your CLASSPATH. I'd like that to be automatically fixed, as well.
Conveniently, Python is very good at all kinds of file and directory stuff. But even better, it has the _winreg module (as part of the standard Python distribution), which allows you to directly modify the registry.
The following program pulls your current CLASSPATH from the registry (so there are no problems if the CLASSPATH has been temporarily changed for one command window), removes duplicates and dead links, and then does one of three things:
If there are jar files in the current directory and you don't provide command-line arguments, all the jar files are added to your CLASSPATH.
If there are no jar files in the current directory, that directory is added to the CLASSPATH.
If you provide command-line arguments, those are assumed to be jar files and added to the classpath.
So if you put this program in your C:\jars directory, every time you throw in a new jar file you can just double-click it to add that jar to your CLASSPATH. Should make hand-installation a lot simpler!
Finally, this might be the ideal solution for beginners and classroom situations, where lots of time is lost struggling with silly CLASSPATH issues.
I got most of the information about how to do this by googling for it, but
this article was especially helpful.
SetClasspath.py by Bruce Eckel, 2006 www.MindView.net
Permission granted for free use and distribution as long as this notice is maintained.
Warning! This program modifies the Windows Registry! Use at your own risk.
With no arguments:
If there are jar files in the current directory, each one is added to the CLASSPATH.
If there are no jar files, the current directory is added to the CLASSPATH.
Each argument must be a jar file name. Each argument is added to the CLASSPATH.
Duplicate CLASSPATH entries and nonexistent paths are removed.
I recommend creating C:\jars directory, and adding this program to that directory.
Whenever you need to add a new jar, throw it in C:\jars and double-click this program.
That way, if you need the same set of jars on another machine, just copy the
directory and run this program.
It's also useful to create a batch/cmd file to run this program, and to place
that file in your Windows PATH. Then you can run the program from any directory.
The batch file might look like this:
python C:\jars\SetClassPath.py %1 %2 %3 %4 %5 %6 %7 %8 %9
If you're running Cygwin, you can make a shell file to do the same thing:
python C:/jars/SetClassPath.py $1 $2 $3 $4 $5 $6 $7 $8 $9
This program requires PythonWin, which you can find at:
from _winreg import *
import os, glob, sys
import win32gui, win32con # From PythonWin
path = r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
reg = ConnectRegistry(None, HKEY_LOCAL_MACHINE)
key = OpenKey(reg, path, 0, KEY_ALL_ACCESS)
i = 0
name, value, valueType = EnumValue(key, i)
if name == 'CLASSPATH':
i += 1
reg = ConnectRegistry(None, HKEY_LOCAL_MACHINE)
key = OpenKey(reg, path, 0, KEY_ALL_ACCESS)
SetValueEx(key, 'CLASSPATH', 0, REG_SZ, newPath)
win32gui.SendMessage(win32con.HWND_BROADCAST, win32con.WM_SETTINGCHANGE, 0, 'Environment')
# set prevents duplicates, 'if os.path.exists(p)' prunes nonexistent paths:
pathparts = set([p for p in getClassPath().split(os.pathsep) if os.path.exists(p)])
if len(sys.argv) > 1:
for arg in sys.argv[1:]:
if not arg.endswith(".jar"):
print "Arguments must be jar file names: problem with [" + arg + "]"
if not os.path.exists(arg):
print arg, "does not exist in this directory"
jars = glob.glob("*.jar")
for jar in jars:
result = list(pathparts)
newClasspath = os.pathsep.join(result) + os.pathsep
If there's a Linuxphile among you who would like to add a Linux (and presumably OSX would work for free) option to the above program, I'd love to incorporate that.
1) Having a system-wide classpath is a sure way to screw up your development efforts. If you only run one java app or work on one java project on your computer, that's great, but that's not the norm. Each project/app should maintain it's own classpath.
2) Most developers and app writers automate this using ant and java itself to build the classpath at runtime, or they use a startup script to build the runtime classpath (a lesser option, IMO). Rather than use python to munge the CLASSPATH, let java do it for itself. it's more robust and more usable and fewer steps (ie, no setting system classpath, no running a separate script, etc).
3) If you're writing a book and have 30 chapters and 30 tiny little micro java projects, I would think one ant script could be made that would do 95% of the work and then a separate ant script for each chapter could import it and finish off the remaining 5%. You could possibly even make do with only a properties file for each chapter.
In short, I think you have python on the brain - it's better than having perl on the brain, but it seems to have caused similar symptoms (ie, string-munging as the solution to all problems).
> Instead of all those complicated rules, why not just add a > commandline argument like: 'jd' (jar directory) that > identifies a directory where all jars should be added to > the classpath. > > One thing I have done in the past when working with > hibernate and Jython (too many jars to keep strack of) is > this simple command to get a classpath from the hibernate > lib directory: > > ls [hibernate-lib] | regex -x "\S+" "\$0:" > cp.txt
Why don't the java tools have a parameter to add directories with jar files in them instead of having to add each Jar file individually? It drives me nuts each time I download a library (jar) and put them in c:\app1libs or c:\app2libs that I have to start fiddling with the classpath stuff. I understand the desire of some in the Java crowd to over-engineer everything but should I really need to install and configure an IDE or Ant just to include a few libraries?
> Why don't the java tools have a parameter to add > directories with jar files in them instead of having to > add each Jar file individually?
That's my question too.
> It drives me nuts each > time I download a library (jar) and put them in > c:\app1libs or c:\app2libs that I have to start fiddling > with the classpath stuff. I understand the desire of some > in the Java crowd to over-engineer everything but should I > really need to install and configure an IDE or Ant just to > include a few libraries?
I've worked with some tools that have done this in the past. It shouldn't be too hard to write a shell script that takes such arguments and converts them to an actual path and then passes it to the real Java app and then create an alias in unix or name the script java.bat and put it in the path in Windows.
BTW: One thing that Bruce's code doesn't deal with, though is that some (common) jar files end in .zip but you can always rename them to .jar.
> I understand the desire of some > in the Java crowd to over-engineer everything but should I > really need to install and configure an IDE or Ant just to > include a few libraries?
Yes, and replies of "just do (whatever the replier does)" don't help either. Maybe there are many tools like ant and eclipse that deal with classpath issues in their own way, but those don't help with the original Java least-common-denominator solution.
And they especially don't help when teaching new Java programmers, or when people are installing the code from my book and they need to initially set up their CLASSPATH so they can run javac.
My experience has been that setting the CLASSPATH in Windows is to be avoided. It's problematic for many reasons. I only use it when a tool I am using requires it. Wouldn't you expect that someone learning to program in Java would at least know how to update a small bat file that you provide?
Putting all your jars in a c:\jar directory is a good idea.
Using the global CLASSPATH environment variable is bad practise and should not be taught to Java beginners. The classpath should instead be specified using the -classpath attribute. This is no hassle in simple beginners programs, where the classpath is usually short (just add it to a one line shell script). If a project is large enough to require importing multiple third part libraries, it's probably time to get organised and use a proper IDE or an ANT script.
> Could there be issues similar to "DLL hell" in the old > time? > > 1. jar name confliction from different vendor. you could rename the jar file
> 2. new version jar with a different time, but forget to > remove the old one. this, too, can only happen do not manually maintain the jar list, which you have to do in large projects
Even then, however, there is "DLL hell"
3. Two libraries require different versions of JDOM, for example. This requires you to replace one of the libraries. I haven't run into this problem yet. Has anybody?
4. Some jars overlap. For example, two SAX implementations could both have the SAX API, but everything will work if you get the classpath order right. I've actually had this problem with the the SAX API in the JDK and in xerces.
> > I understand the desire of some > > in the Java crowd to over-engineer everything but should > I > > really need to install and configure an IDE or Ant just > to > > include a few libraries? > > Yes, and replies of "just do (whatever the replier does)" > don't help either. Maybe there are many tools like ant and > eclipse that deal with classpath issues in their own way, > but those don't help with the original Java > least-common-denominator solution.
But if you're teaching Java, you ought to teach these relatively standard java-centric ways of doing things rather than bringing in a brand new solution using python.
> > And they especially don't help when teaching new Java > programmers, or when people are installing the code from > my book and they need to initially set up their CLASSPATH > so they can run javac.
You should be providing shell scripts that will just run right on (at least) a windows or unix systems. That way, they can immediately run the examples. Later on, learning how to properly deal with CLASSPATH is essential to. Setting a Global CLASSPATH is a bad way to start out.