Skip to content
Advertisement

how read/reach/access a file from Kotlin when the application is deployed either in Kubernetes or Linux

Context: I successfully parse a json file while debugging/running locally in my Windows PC that way

import com.fasterxml.jackson.core.JsonFactory
import com.fasterxml.jackson.core.JsonParser
import java.io.File
import java.nio.file.Paths

...

val basePath = Paths.get("").toAbsolutePath().toString()

val parser: JsonParser = JsonFactory().createParser(File("$basePath/app/src/main/resources/support/certain-file.json"))

When I deployed it to either docker or AWS I get this error

 /app/src/main/resources/support/certain-file.json (No such file or directory)

Is there a more reliable way to “navigate” to a file placed in resources folder? I mean someway it wouldn’t be affected either it is Windows/Linux/Kubernetes/etc?

Advertisement

Answer

The usual way to access resource files is via the classpath, not by going directly to the filesystem.

There are several advantages to this:

  • The resources will usually be deployed automatically, along with your compiled code; no need for manual copying.  (Maven and Gradle usually know to treat the src/main/resources folder this way.)
  • If you build the application as a .jar/.war file, the resources will get included in that.  (Your code doesn’t need to know or care that they’re in an archive; as long as you access the resource as a stream, loading just works.)
  • The application isn’t tied to a particular directory layout or OS; it can run in any directory on any machine.
  • You can override files.  Because the classpath can give several locations, a file in a later location can be overridden by adding a file into an earlier location.

It’s easy enough to do: just call getResourceAsStream() on the relevant classloader.  In this case, it could be as simple as:

val parser = javaClass.classLoader.getResourceAsStream("support/certain-file.json")?.use {
    JsonFactory().createParser(it)
}

Here javaClass.classLoader gets the current class’s ClassLoader.  (You could use the system one instead, of course.)

use() takes care of closing the resulting InputStream once it’s been read.

And luckily, there’s a createParser() method which accepts the InputStream.

(Disclaimer: I don’t know anything about Kubernetes, or about running Kotlin/Java programs on Windows.  But the beauty of using the classloader is that you don’t need to!  If it can load classes, it can load resources too.)

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement