views:

235

answers:

5

Quick personal background: I was hired a few months ago as the sole .NET developer (C#) by a company whose other devs are all php devs. A week into the job I was told they wanted to switch to Java instead of doing .NET. Not an ideal situation, but I'm trying to make it work.

I don't think I understand the relation between a project's library and the class path. I am using NetBeans 6.7.1 for development. My current project is to create an application that will update multiple merchant sources (eBay, Amazon, etc). I created a Class Library project that handles scheduling of these updates. We'll call it Update.

I am in the process of creating Class Library projects for the various sources (e.g. eBay). I added the ebay project to the Update project as a Library. In the IDE there is a box that says "Build Projects on Classpath" which is checked.

Finally, right now I have a little console app that has the Update project referenced as a Library (so the ebay project is now 2 libraries deep) in the same manner. It works with code in the Update project.

This works OK until I get to instantiating a class (from the Update project via the console app) that is in the ebay project. At that point I get a

Exception in thread "main"
java.lang.NoClassDefFoundError

which is

 Caused by: java.lang.ClassNotFoundException
  at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
  at java.security.AccessController.doPrivileged(Native Method)
  at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
  at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
  at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
  at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
  at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)

These projects all build fine but this runtime exception is killing me. I don't know if I really understand what adding a Library to a project does and if there is something more I need to do to make the class accessible. I'm used to being able to add a reference to a DLL and being good to go. I don't understand why I don't get any compiler errors or build errors but I get run time errors about accessibility. I'm guessing the classpath is a missing piece that I don't understand too well, although I suppose it's possible this problem has to do with something else entirely.

+2  A: 

In Java, unlike C#, you need to explicitly add the class paths to project. I use eclipse and I had to do this get some of the referenced jars loaded.

Krishna Kumar
+3  A: 

I highly recommend picking up Core Java, volumes 1 and 2. They are must reads for Java developers that want to understand the internals of the language such as the ClassLoader. At the very least, read up on class loading.

To answer your question, the Update project should be generating .class files or jar. You need to have the location of either the class files or the jar in your classpath for the project that you are referencing them from. Depending on your IDE, having a reference to the project might only give you access to the source, for compiling.

Chris Lacasse
+2  A: 

You need to separate Java concepts from IDE-specific concepts. I recommend going through a simple java tutorial using a text editor and command shell before jumping into NetBeans.

Library and Project are NetBeans specific terms. I'm not a NetBeans user, so I won't try to guess what they are although I have some guesses, but I will say that their configuration will most likely affect compile-time environment.

A Classpath is a core java concept. You must provide the paths to all your classes (or jars that contain those classes) to the java command at runtime in order for it to be able to load those classes. (You also need to do the same to the javac command at compile-time for the classes that you're referencing but not compiling at the moment).

Any time you see java.lang.ClassNotFoundException, it means that some class that was present on the classpath when you compiled your code is missing from the classpath when you launched the runtime.

ykaganovich
+1  A: 

The solution I have come up with for now:

I expected the references from nested libraries to "bubble up". This apparently doesn't work for classpaths. My structure was basically:

A has reference to B has reference to C

When I ran A it worked fine until it got to something in C. What I did was give A a direct reference to C by adding it as a library to the project. From some quick Google searches it looks like this pretty much IS how you add a classpath to a project in NetBeans.

It seems a bit messy to me and maybe there is a better way to do that, but it has fixed my problems for now. Thanks to everyone who answered - while no one precisely solved my particular problem (you guys got me about 95% of the way there though) they verified my thoughts and enabled me to figure out that last little bit to get it going.

Ryan Elkins
+1  A: 
Exception in thread "main"
java.lang.NoClassDefFoundError

The classname is missing in the error message, but let's suppose that it is the class itself for which you wanted to execute the main method. In that case it just means that Java cannot find the particular class in the runtime classpath.

To fix this you need to cd to the root of the package where the class is located in and then re-execute the java command as follows:

java -cp . com.example.MainClass

Here the -cp argument specifies the classpath. It has only a value of . which means that the current working directory should be taken into the classpath (which is usually the default case, but better safe than nothing).

Alternatively you can specify its full path in the -cp argument, so that you can execute it from everywhere, e.g.:

java -cp /path/to/package/root com.example.MainClass

Another alternative which is most seen in tutorials for starters but is usually not been used by professionals is defining an %CLASSPATH% environment variable wherein you put exactly that value what you'd like to use in the -cp argument. Then the java command will lookup it (as long as you do not use one of the -cp, -classpath or -jar arguments).

If typing the long commands get bored you can use a batch or shell file for this so that you can manage it easily.

If you for instance have a JAR file or another root package folder with classes which you'd like to use in your program, then you need to append them to the classpath. When on Windows, the separator is the semicolon ; and when on Linux the separator is :. Further on when a path contains spaces, you need to quote the particular path. Here's a Windows example:

java -cp .;/path/to/package/root;"/spacy path/to/file.jar" com.example.MainClass

Hope this helps.

BalusC
Thanks for the post. It turns out it had to do with referential issues in NetBeans (see my own answer to this question). I made the (incorrect) assumption that a project was self contained - that if it had all the references set up for itself that anything that used that project could just reference the project itself - without needing to reference all the pieces the referenced project was also using.
Ryan Elkins