Reputation: 19546
An overview of the problem: I have a CSVFile
class in a Utils
project that uses openCSV's CSVReader
internally to load csv files.
Now I create a new project called MyTester
and added Utils
onto its classpath with the intention of using the CSVFile
to work with csv files.
This is how it looks so far
MyTester
src
Tester.java
Utils
src
CSVFile.java
lib
opencsv.jar
Instantiating a CSVFile and passing in a file path will have it simply load the csv file:
import au.com.bytecode.opencsv.CSVReader;
public class CSVFile {
public CSVFile(String filename) {
CSVReader reader = new CSVReader( ... );
// read CSV file
}
}
This works fine.
So now I want to load a csv file in a separate project. I use the CSVFile
as that is its purpose.
import CSVFile;
class Tester {
public static void main(String[] args) {
CSVFile reader = new CSVFile("test.csv");
}
}
When I run Tester
, I get a ClassNotFoundException
while looking for CSVReader
. The top of the stacktrace points to the line in the CSVFile
constructor, so at least my code is doing what I expect it to do.
I am familiar with classpath related issues where I forget to add a required jar, so when I added the required jar to MyTester
project, it works as expected.
But I don't understand why I need to do this.
If I'm using a class or method defined in a 3rd party library, I should not have to know anything about its implementation. However in this example, my Tester
class needs opencsv.jar
, which doesn't make sense to me. What could be causing the problem?
Upvotes: 0
Views: 44
Reputation: 13961
If I'm using a class or method defined in a 3rd party library, I should not have to know anything about its implementation.
This is true when compiling code using a third-party library (in most cases) - if my project A depends on B.jar, which is provided by a project that in turn has a dependency on C.jar, then I don't usually need C.jar on my classpath to compile project A.
At runtime it's a different story. The first time some code in my project A accesses a method in a class from B.jar, the JVM will load they bytecode for that class from B.jar, initialize the class, and proceed to execute the method in question. Similarly, if during the course of executing the method from project B, there is a method call to a class defined in C.jar, the JVM will load that bytecode as well. So, C.jar needs to be on your classpath at runtime, but not necessarily at compile-time.
This is why tools such as Maven are so popular - they handle transitive project dependencies and automatically set up your classpath for you, based on a declarative description of your project's dependencies.
Upvotes: 1