4

I am working on a web app in Kotlin/JS, and I'm trying to use a Kotlin library "com.beust:klaxon:3.0.1" (I've explicitly compiled the lib's dependencies and removed them from the lib to reduce probability of version conflict, after not succeeding without the explicit compilation):

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version"
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
    implementation('com.beust:klaxon:3.0.1') {
        exclude group: 'org.jetbrains.kotlin'
    }
}

But I can't use it: failure to build in IntelliJ

Gradle output:

19:40:45: Executing task 'build'...

:compileJava NO-SOURCE
e: .../School-Web-Project/frontend/src/requests/Abstraction.kt: (3, 8): Unresolved reference: com
e: .../School-Web-Project/frontend/src/requests/Abstraction.kt: (20, 57): Unresolved reference: Klaxon
:compileKotlin2Js FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':compileKotlin2Js'.
> Compilation error. See log for more details

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 2s
1 actionable task: 1 executed
Compilation error. See log for more details
19:40:48: Task execution finished 'build'.

I have no leads on what the mistake is. I've run gradle clean and invlidated caches and restarted.

Thank you for your time.

Complete files:

build.gradle

version '1.0'

buildscript {
    ext.kotlin_version = '1.2.50'
    ext.web_dir = "${projectDir}/web/"
    repositories {
        jcenter()
        mavenCentral()
        maven { url "https://plugins.gradle.org/m2/" }
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath "com.gradle:build-scan-plugin:1.14"
    }
}

apply plugin: 'kotlin2js'
apply plugin: 'com.gradle.build-scan'

sourceSets {
    main.kotlin.srcDirs += "src/"
}

repositories {
    mavenCentral()
    jcenter()
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version"
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
    implementation('com.beust:klaxon:3.0.1') {
        exclude group: 'org.jetbrains.kotlin'
    }
}

clean.doFirst() {
    delete("${web_dir}")
}

build.doLast() {
    // Copy kotlin.js and kotlin-meta.js from jar into web directory
    configurations.compile.each { File file ->
        copy {
            includeEmptyDirs = false

            from zipTree(file.absolutePath)
            into "${web_dir}/lib"
            include { fileTreeElement ->
                def path = fileTreeElement.path
                path.endsWith(".js") && (path.startsWith("META-INF/resources/") || !path.startsWith("META-INF/"))
            }
        }
    }

Abstraction.kt

package requests

import com.beust.klaxon.Klaxon
import org.w3c.xhr.XMLHttpRequest

object Requestables {
    fun requestWeapons(id: Int, amount: Int)
            = "backend/request_weapons.php?id=$id&amount=$amount"
}

object RawRequestData {
    fun getWeaponsRaw(id: Int, amount: Int, callback: (String) -> Unit, error: (XMLHttpRequest) -> Unit = {}) {
        CommonDataRequest.makeAsyncRequest("GET", Requestables.requestWeapons(id, amount), {
            callback(responseText)
        }, error)
    }
}

object WeaponRawProcessing {
    fun getWeaponDTOs(rawData: String): WeaponRowDTO =  Klaxon().parse(rawData)?: throw NullPointerException("What a Terrible Failure!")
}

object Requests {
    fun getWeapons(id: Int, amount: Int, callback: (WeaponRowDTO) -> Unit, error: (XMLHttpRequest) -> Unit = {}) {
        RawRequestData.getWeaponsRaw(id, amount, {
            callback(WeaponRawProcessing.getWeaponDTOs(it))
        }, error)
    }
}

    // Copy scripts to web directory
    copy {
        into "${web_dir}"
        from ("build/classes/kotlin/main") {
            include "*.js"
        }
    }
}

buildScan {
    termsOfServiceUrl = 'https://gradle.com/terms-of-service'
    termsOfServiceAgree = 'yes'
}
EmmanuelMess
  • 166
  • 1
  • 10
  • 26
  • How come you're specifying dependencies under the `implementation` configuration? Shouldn't that be `compile`? I don't see where you're applying the `java-library` plugin, which is whet I thought was necessary for the `api` and `implementation` configurations to exist. – user31601 Jul 10 '18 at 14:52
  • @user31601 [`compile` is now deprecated](https://stackoverflow.com/a/44493379/3124150). Although `api` will let me use klaxon's libraries, what I want to do is "forcefully" update them so I can prevent versioning problems. – EmmanuelMess Jul 10 '18 at 17:31
  • I believe the linked answer you refer to about `compile` being deprecated is an oversimplification. If you read through to the actual Gradle documentation, you'll see these newer configurations only apply when using the `java-library` plugin, as opposed to the `java` plugin on its own. Which set of dependencies you should use here will depend on which plugins `kotlin2js` transitively applies - I'm not sure which it is. – user31601 Jul 10 '18 at 19:19
  • > If you read through to the actual Gradle documentation, you'll see these newer configurations only apply when using the java-library plugin, as opposed to the java plugin on its own.
    Could you give me a source link please?
    – EmmanuelMess Jul 10 '18 at 19:53
  • Sure, [here](https://docs.gradle.org/current/userguide/java_library_plugin.html) it is. I only didn't supply the link before because I didn't know how in comments (and missed the little 'help' link). – user31601 Jul 10 '18 at 20:04
  • I had the similar "works with `compile` and breaks with `implementation`" problem and what I ended up with is replacing `configurations.compile` with `configurations.runtimeClasspath`. Hope that will work for you – Eugene T Mar 22 '19 at 16:14

2 Answers2

1

I believe com.beust:klaxon is meant to be used with kotlin-jvm. For kotlin-js you should use libraries specially built for js, like kotlin-stdlib-js.

  • This isn't really helpful, why would it not work? It isn't like it's written in a different language, isn't there a compatibilization method? – EmmanuelMess Jul 10 '18 at 19:02
  • 1
    But it is compiled for different platform, it contains .class files for jvm inside a jar. To make it compatible, author should compile it with kotlin2js compiler. I’ll try to find relevant documentation clarifying this and update my answer. – Vyacheslav Gerasimov Jul 10 '18 at 19:08
0

Looking at the source code for the Kotlin Gradle plugins, it appears that they only transitively apply the java plugin, not the java-library plugin. This would mean that the compile classpath for the source set won't include the implementation configuration (or the api configuration).

I reckon that to fix, you could either:

  1. apply plugin 'java-library' in your build.gradle
  2. Change your dependencies to compile "<coordinates>" so that they're added to the compile configuration instead.

I haven't tested this, so let me know if it works.

user31601
  • 1,604
  • 1
  • 9
  • 17