When TestNG invokes Class.getResourceAsStream() on an external module, it is returning null.
Per Resources visibility with java9 modules when a user wants to access /resources/someResource.xml in a library that contains module-info.java, the module must opens resources unconditionally.
Fair enough. But what happens if a user wants to access /META-INF/resources/someResource.xml in such a library? What opens instruction is necessary in this case?
UPDATE:
The bug report was filed against version 7.5 of TestNG. I just noticed that if we look at the source code of that version we see it is trying to load /META-INF/resources/webjars/jquery/3.5.1/jquery.min.js.
From my testing, opening the package is only necessary when the file is in the same package as a class in the module. In that case, you need to open the package of the class in the same module.
So, assume you have a project like the following:
|-A
| |-module-info.java
| |-a
| |-A.java
| |-x
| |-X
|-B
|-module-info.java
|-b
|-B.java
and A/module-info.java:
module a {
exports a;
}
as well as B/module-info.java:
module b {
requires a;
}
then compile it with the following commands:
cd A
javac module-info.java a\A.java
cd ..
cd B
javac --module-path ..\A module-info.java b\B.java
cd ..
The content of class A is irrelevant here (it just needs to exist and have a class/interface/enum/record/whatever declaration with the correct name).
We then let B read the file a/x/X from module A:
package b;
import java.io.*;
import a.A;
public class B{
public static void main(String[] args) throws Exception{
try(BufferedReader br = new BufferedReader(new InputStreamReader(A.class.getClassLoader().getResourceAsStream("a/x/X")))){
System.out.println(br.readLine());
}
}
}
When running it with
java --module-path A;B -m b/b.B
it displays the first line of a/x/X.
However, we cannot access files in the same directory as the A.class file:
package b;
import java.io.*;
import a.A;
public class B{
public static void main(String[] args) throws Exception{
try(BufferedReader br = new BufferedReader(new InputStreamReader(A.class.getResourceAsStream("A.java")))){
System.out.println(br.readLine());
}
}
}
If we now add opens a in A/module-info.java (and recompile the module with the above command), the resource can be read.
If we want to read /META-INF/a/A.txt or similar (in the A module), no opens statement is required as there is no class in the same package.