Brief description
In a netbeans project, if I tell Netbeans that a specific jar file is to be made available on the compile-time classpath as a library, then, I understand that Netbeans would also make that jar file available on the run-time classpath. But this classpath lib "propagation" seems to work only in a non-modular project, and doesn't seem to be happening in the case of a Modular project (in Netbeans 11).
My experiment
I've created 3 simple, experimental projects, called ProjectA
, ProjectB
, ProjectC
, in Netbeans 11. The IDE, as well as the 3 projects, are configured to run on Open Jdk12
.
ProjectA
ProjectA
is non-modular, and just defines pkg1.MyClassA
ProjectB
ProjectB
is also non-modular, and defines pkg2.MyClassB
which imports and extends pkg1.MyClassA
. In ProjectB
's Properties==>Libraries==>Compile, I have specified ProjectA/dist/ProjectA.jar
file as a required classpath library. In ProjectB
's Run options (ProjectB Properties==>Libraries==>Run) I have not specified this jar dependence. At runtime, MyClassA
will be needed, because the main()
method of MyClassB
instantiates MyClassB
which extends MyClassA
.
ProjectC
ProjectC
is Modular (created with Netbeans option NewProject==>JavaWithAnd==>JavaModularProject). It defines mod.world/pkg3.MyClassC
, which has a main()
method that instantiates pkg1.MyClassA
. In ProjectC
's Properties==>Libraries==>Compile, I have specified ProjectA/dist/ProjectA.jar file as a required classpath library, just as I did for ProjectB
's dependence on ProjectA.jar
. Also, I did not specify any jar dependence in ProjectC
's Properties==>Libraries==>Run, just as in the case of ProjectB
's properties. Also, I have specified --add-reads mod.world=ALL-UNNAMED
in ProjectC
's compiler option as well as a runtime JVM option, to enable the explicit module of ProjectC
to access the unnamed module of ProjectA.jar
, at both compile-time and runtime.
The Compile on save
option is turned off for all the 3 projects.
What I expected
I expected to be able to successfully compile and run all the 3 Projects.
What I actually saw
ProjectA
compiled successfully.
ProjectB
also compiled and ran successfully.
ProjectC
compiled successfully, but failed at runtime with NoClassDefFoundError
for not finding pkg1.MyClassA
. This runtime error goes away if, in ProjectC
's Properties==>Libraries==>Run, I specify ProjectA.jar
as a required classpath library (as I had specified in ProjectC
Properties==>Libraries==>Compile).
My Questions
- The Netbeans dialog window at Project Properties==>Library, says
"Compile-time libraries are propagated to all library categories"
. I understand that this was the reason why I was able to successfully run ProjectB, even though I had not specified any jar-file dependency at runtime for ProjectB, upon ProjectA.jar. So, why doesn't the same propagation happen in the case of ProjectC? Is it somehow because of ProjectC being a modular application? (Even if so, why?). Or is this a bug in Netbeans 11? (I did google for this before posting here).
- What if, on some occasion, I wanted to stop Netbeans from propagating a compile-time library to run-time or to test-time? Is there a way to do that? For both modular and non-modular projects?
Here's the complete code
Code for ProjectA
package pkg1;
public class MyClassA {
public MyClassA(){
System.out.println ("Inside constructor MyClassA()");
}
}
Code for ProjectB
package pkg2;
import pkg1.MyClassA;
public class MyClassB {
public MyClassB() {
new MyClassA();
System.out.println ("Inside constructor MyClassB()");
}
public static void main(String[] args) {
System.out.println ("Inside main() of MyClassB");
new MyClassB();
}
}
Code for ProjectC
Code in module-info.java
module mod.world {
exports pkg3;
}
Code in MyClassC.java
package pkg3;
import pkg1.MyClassA;
public class MyClassC {
public static void main(String[] args) {
new MyClassA();
System.out.println ("Inside main() method of MyClassC");
}
}