0

Tech stack details:

Spring Boot version 2.7.0
Java Version : Java 17.0.3.1
Operating System : Windows 10 Pro

Setup: Trying to run the application built using Spring Boot and packaged as JAR

Business code reads a JSON file. Currently it was achieved by opening an InputStream over BufferedReader readLine()

As part of JDK upgrade from v8 to v17. we are planning to achieve the same using java.nio.file.Files readString(Path, Charset). readString takes Path as an argument. We are trying to build the path using Paths.get(new ClassPathResource(WAVEFORM_FILE_NAME).getURI() But above line is throwing java.nio.file.FileSystemNotFoundException at ZipFileSystemProvider.getFileSystem(ZipFileSystemProvider.java:156). After debug what I understood is ZipFileSystemProvider has a hashMap filesystems. This is EMPTY. So even when uriToPath(URI uri) is building Path properly, getFileSystem(URI uri) of ZipFileSystemProvider is throwing FileSystemNotFoundException at line#156.

Stack Trace:

 at jdk.zipfs/jdk.nio.zipfs.ZipFileSystemProvider.getFileSystem(ZipFileSystemProvider.java:156)
        at jdk.zipfs/jdk.nio.zipfs.ZipFileSystemProvider.getPath(ZipFileSystemProvider.java:142)
        at java.base/java.nio.file.Path.of(Path.java:208)
        at java.base/java.nio.file.Paths.get(Paths.java:98)
        at com.x.y.z.streaming.mock.DataLoader.loadData(DataLoader.java:42)

Please note: things work fine when spring application is ran inside an editor. Issue comes when we run application as java -jar app.jar

I see suggestions to use FileSystems.newFileSystem(URI.create(pathArray[0]), env) to make this work. I do not understand why Path.get() is having a challenge to read a JSON file inside SpringBoot built JAR. Any pointers would help!

I tried to debug and understand why the exception is thrown. Root Cause Analysis is given in the question. Also proposed solution in some discussion thread also tried. It seems to work but do not understand why Path.get() is not able to work independently. Trying to discuss the technicality.

Vinay
  • 11
  • 3
  • 1
    Which aspect don’t you understand? You already know the solution, which is to create the filesystem via `FileSystems.newFileSystem(…)`. If you don’t create the filesystem, there is no such filesystem. – Holger Dec 21 '22 at 13:24
  • **Thanks for confirming that my approach is correct**. My question was more into design aspect of the `Path.get()` method. I do not understand the need of making a `FileSystems.newFileSystem(…)` call before `Path.get()`. I mean why not it can be taken care of implicitly. If this is how it is designed to work, may I know if `removeFileSystem(Path, ZipFileSystem)` should be called once we are completely done with that particular file read/write – Vinay Dec 22 '22 at 03:30
  • 1
    `removeFileSystem` is not a `public` method. You have to `close()` the filesystem after use, which will eventually call remove after all the other cleanup. Compare with [this answer](https://stackoverflow.com/a/36021165/2711488) – Holger Dec 22 '22 at 10:04
  • Thanks @Holger we initially thought of moving to `Files.readString` from `BufferedReader readline()` because we felt former guy does many things implicitly like open/read/close file implicitly and also code looks concise etc .. but now looking at `Files.readString` setup like `FileSystem.newFIleSystem` and again constraint that you need to do `newFileSystem` exactly once, second time onwards we need to do `getFileSystem` to avoid `FileSystemAlreadyExists` error and we need to consider closing once done. Looks too much of overhead. – Vinay Dec 23 '22 at 03:47
  • Sorry if I am deviating the topic .. can someone suggest me what is the exact use case when we should be going for `Files.readString` or any Performance benefits of one over another ? – Vinay Dec 23 '22 at 03:47
  • 1
    It works best when using modules. As then, all resources are available through the jrt: filesystem which is always open. Then, you can indeed read a string resource in a one-liner. – Holger Dec 23 '22 at 07:34
  • @Holger thanks! If not any performance optimization, at this moment Files.readString() is not working well for our use case. We need to run in Jar and Docker mode! – Vinay Dec 27 '22 at 15:00

0 Answers0