1

I have a project with several modules. In one module (A) I am trying to access the resources of another module (B). Module B is defined as a dependency in module A. I wrote some tests checking if I can access the files. When I run the tests in IntelliJ everything passes. When I run mvn test everything works. When I run mvn install or mvn package the same tests won't pass and the build fails.

In module A I am trying to access the resource as follows:

ClassOfModuleB.class.getResource("/fileOfModuleB").getFile()

I found some issues listed here: Java: How to read file from different module? and here: How to really read text file from classpath in Java

I tried out all combinations, however, every time the test passes in IntelliJ/mvn test and it won't pass in mvn install/mvn package.

Community
  • 1
  • 1
wjentner
  • 525
  • 1
  • 7
  • 16
  • 1
    Ha. You can't access a resource as a `File` but only as a `InputStream`. Your `.getFile()` there is the problem. – Tunaki Feb 20 '16 at 22:20
  • But why would it work in `mvn test`? – wjentner Feb 20 '16 at 22:28
  • 1
    That I have no idea. But I'm pretty sure that's your problem. – Tunaki Feb 20 '16 at 22:33
  • 1
    First if you try to use resources of module B in a Test of module A sounds wrong to me, cause a unit test should be independent and in your case only do tests in module A without the need to access resources of module B. Furthermore accessing the file does not work cause the dependencies between modules are based on the jar files and that's why only the getResource access can work... – khmarbaise Feb 21 '16 at 00:43

1 Answers1

0

As khmarbaise pointed out already the design of this application is completely messed up. I found an ugly workaround but it makes things work and is well tested. The main problem is, that different modules need to access the same files. Unfortunately the files cannot be processed as streams (which would make things a lot easier) since 3rd party libraries need an actual file handle. And receiving this (.getFile()) is the problem as Tunaki said already. The reason it was working in mvn test is that, these tests are run before the application is packed. By observing the path of the .getResource() it shows a change to jar:// when it's packed which makes it impossible to get actual file handles since there are no files anymore. However, it is possible to receive InputStreams.

The workaround is simple: Receiving the files as input streams, writing them to a temporary directory after the application is started.

private File copyResourceIntoTempFile(String resource, File target) throws IOException {
    InputStream input = getClass().getResourceAsStream(resource);

    OutputStream out = new FileOutputStream(target);
    int read;
    byte[] bytes = new byte[1024];

    while ((read = input.read(bytes)) != -1) {
        out.write(bytes, 0, read);
    }
    //target.deleteOnExit();


    if (!target.exists()) {
        throw new FileNotFoundException("Error: File " + target + " not found!");
    }

    return target;
}

It is also possible to iterate over the files of a directory:

InputStream in = this.getClass().getResourceAsStream(resource);
        BufferedReader rdr = new BufferedReader(new InputStreamReader(in));
        String line;
        while ((line = rdr.readLine()) != null) {
            this.copyResourceIntoTempFile(resource+"/"+line, new File(dir, line));
        }
        rdr.close();

I know that this is by far not the nicest solution. However, the solution of the guy that started the project was to ensure that some files are in the directory (manually) wherever the application runs. After some cumbersome work with deploying the application it got refactored to download the needed files and unzip them which took forever.

wjentner
  • 525
  • 1
  • 7
  • 16