How to load resources in new MPP

Hello

I try to load resources in a new MPP like SampleMain::class.java.getResource("/sample/config.properties") without success. When i looking in the build folder, the resources are placed in the build/processedResources folder. But when i start an application with an IDEA run configuration this folder will not get applied to the classpath / classloader. The only workaround i see at the moment is to copy those resources with an custom Gradle copy taks to copy them into the build/classes/kotlin/jvm/main folder and execute this task before main start. Or do i anything wrong?

Regards

2 Likes

Having the same issue here.

If MPP is “multiplatform projects prototype” then it suppose to support JS target, right ?
In JS it is hard and invalid to perform synchronous blocking resource read, since all data fetch in JS is async.

Or am I miss something ?

Same issue as well.

Well, it does not have to be blocking. MPP probably needs some kind of internal way to load resources. For example using coroutines. It does not have to be done on a language level and could be implemented by libraries, but it requires some kind of support from the build system, meaning that resources must be loaded into the webpack bundle on JS.

Well, the thread starter initially requested it to be blocking.
If async is OK, then it should fit in classical multiplatform paradigm: mpp interface and platform implementations: for web, for jvm/android, and for iOS.

So the thread starter can

  • declare multiplatform (async) resource loading interface
  • implement it on required platforms.
  • package the resources in platform-specific way.

The problem as I see it is not in code, but in packaging and tooling. In JVM the content of resource directory is automatically included in jar. On JS, the resource should be somehow added to webpack build. On native, resources should probably come in a separate directory. Then there could be a platform specific resource getter that could load it from default directory for this platform. It should not be very hard to implement, but requires modifications to the gradle mpp plugin.

Well, if the problem is in the tool-chain and plugin, then it might be possible to file an YT issue describing the problem ?

Like this one: https://youtrack.jetbrains.com/issue/KT-29311? I have not found a universal proposal for common way to load resources. Probably I should write it later.

I hope https://github.com/orangy/kotlinx-files will support cross-platform read-only Resources filesystem.

Sorry for my very late answer!

I think, my description of the problem was not clear enough when i read it now.

I think it’s neither related to JS / shared code or async / sync. It looks to me more like an IDE / classpath / build problem. I attached a very simple MPP project with just a properties file and a main class. If i execute the main function via IDEA run configuration, the resource will not be found.

mpp.zip (78.2 KB)

I’m having this same problem as described in the original post, in a project that mixes JVM and JS. People are talking about cross platform resources, but I don’t think it’s that complicated. In JVM code you need to load a resource, but they’re not on the classpath. For example: I’m getting errors from Apache log4j2 because it’s config file is not on the classpath, even though I have it under src/jvmMain/resources. It’s under jvmMain, not commonMain – I only need it on the JVM side.

I agree with you. I think it’s only this bug https://youtrack.jetbrains.com/issue/KT-24463

But it should be qualified as BUG and not problem, with a critical priority. Let me explain why.

When you create a multiplatform JS / JVM project using Intellij Idea

you get a Ktor project with a jvmMain/resources/logback.xml file.

image

Everything looks fine, and you can run the project directly from the main function.

The problem is that the file is not in the classpath.

It takes time to understand the problem and this is a terrible first experience for someone who is trying to run a multiplatform project.

This bug is specific to the new MPP plugin. The same project split into modules with the “old” multiplatform plugin does not have the problem. However, the old plugin is not mentioned anymore in Kotlin documentation. Maybe it should remain until all the major and critical issues of the new MPP plugin are resolved.

Thanks for the explanation, exactly what I had observed too, but i didn’t found that issue.
I think to use the new MPP is anyway a good choice, at least for growing projects to avoid migrations.

A “workaround” is maybe to use the Gradle application plugin, works perfectly for me.