How to access files in /META-INF/resources when module-info.java is present?

184 Views Asked by At

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.

1

There are 1 best solutions below

2
dan1st might be happy again On BEST ANSWER

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.