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.