gradle nativeBinaries fails to satisfy dependencies - kotlin

So, I wanted to generate native Kotlin binary for my app. I've came up with this build.gradle.kts:
plugins {
application
kotlin("multiplatform") version "1.3.70"
}
version = "1.0.2"
group = "org.gradle.sample"
repositories {
mavenCentral()
}
kotlin {
linuxX64("native") {
binaries {
executable()
}
}
}
dependencies {
implementation(kotlin("stdlib"))
implementation("io.javalin:javalin:3.8.0")
}
The code itself is simple:
package org.gradle.sample
import io.javalin.Javalin
fun main() {
val app = Javalin.create().start(7000)
app.get("/") { ctx -> ctx.result("Hello World") }
}
Problem here is that it fails when compiling, like if the dependencies were not satisfied:
> Task :compileKotlinNative FAILED
Caching disabled for task ':compileKotlinNative' because:
Build cache is disabled
Task ':compileKotlinNative' is not up-to-date because:
Task has failed previously.
file or directory '/home/keddad/Documents/samplekotlinapi/src/commonMain/kotlin', not found
file or directory '/home/keddad/Documents/samplekotlinapi/src/commonMain/kotlin', not found
Run tool: konanc with args: -g -ea -target linux_x64 -p library -o /home/keddad/Documents/samplekotlinapi/build/classes/kotlin/native/main/basic-api.klib -Xmulti-platform -no-endorsed-libs /home/keddad/Documents/samplekotlinapi/src/nativeMain/kotlin/org/gradle/sample/Main.kt
e: /home/keddad/Documents/samplekotlinapi/src/nativeMain/kotlin/org/gradle/sample/Main.kt: (3, 8): Unresolved reference: io
e: /home/keddad/Documents/samplekotlinapi/src/nativeMain/kotlin/org/gradle/sample/Main.kt: (6, 15): Unresolved reference: Javalin
e: /home/keddad/Documents/samplekotlinapi/src/nativeMain/kotlin/org/gradle/sample/Main.kt: (7, 20): Cannot infer a type for this parameter. Please specify it explicitly.
:compileKotlinNative (Thread[Execution worker for ':',5,main]) completed. Took 0.201 secs.
FAILURE: Build failed with an exception.
Same thing worked when compiling for JVM, but for Native it breaks. What am I doing wrong?

Unfortunately, you will not be able to compile this code at the moment. It seems like the Javalin framework is not targeting Kotlin/Native, it publishes only for Kotlin/JVM. The only libraries published with K/N in mind will be available to use.
In fact, the problem is that Kotlin flavors are not equivalent internally. They can share pure Kotlin code via common... source sets, but one cannot take a Kotlin/JVM project and just change the target. Kotlin/Native differs from the Kotlin/JVM, both of them are not the same as the Kotlin/JS. To make them work together, an approach named Kotlin/Multiplatform is recommended, see this article.
If you are interested in adapting this code to become multiplatform, consider looking at the Ktor. It provides support of the Kotlin/Native, and you'll be able to partially share code between platforms.

Related

How to force JAR dependency order after a maven dependency

I have the following dependencies (among others):
dependencies {
compileOnly("com.destroystokyo.paper:paper-api:$paperApiVersion")
compileOnly(files("libs/craftbukkit-1.12.2.jar"))
}
I want to use all classes from the 2nd dependency under "org.bukkit.craftbukkit" group and nothing else, beacause the rest is collidating with paper-api classes (the 1st dependency). When I try to build a jar using ./gradlew shadowJar, I'm getting errors indicating some methods inside paper-api library were not found:
e: /plugin/src/main/kotlin/com/hakim/common/bukkit/command/RegisterCommandRuntime.kt: (12, 49): Unresolved reference: getCommandMap
e: /plugin/src/main/kotlin/com/hakim/infrastructure/request/model/CommandHandlerRequest.kt: (22, 18): None of the following functions can be called with the arguments supplied:
public abstract fun sendMessage(p0: Array<(out) String!>!): Unit defined in org.bukkit.entity.Player
public abstract fun sendMessage(p0: String!): Unit defined in org.bukkit.entity.Player
e: /plugin/src/main/kotlin/com/hakim/network/ui/command/HubCmd.kt: (19, 64): Unresolved reference: toCenterLocation
e: /plugin/src/main/kotlin/com/hakim/statefulblocks/domain/StatefulBlock.kt: (23, 35): Unresolved reference: toBlockLocation
paths were modified
I know for a fact the methods exist in Bukkit class inside the paper-api library, but do not exist in the craftbukkit library.
I attach the screenshot to present what dependencies order I'm getting from build.gradle.kts. Pay attention where the craftbukkit-1.12.2.jar dependency is placed.
I attach the screenshot to present what dependencies order I want to get from build.gradle.kts. Pay attention where the craftbukkit-1.12.2.jar dependency is placed.
How can I achieve it?
Gradle version:
------------------------------------------------------------
Gradle 7.4.2
------------------------------------------------------------
Build time: 2022-03-31 15:25:29 UTC
Revision: 540473b8118064efcc264694cbcaa4b677f61041
Kotlin: 1.5.31
Groovy: 3.0.9
Ant: Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM: 11.0.16 (Ubuntu 11.0.16+8-post-Ubuntu-0ubuntu122.04)
OS: Linux 5.15.0-48-generic amd64
I've solved my issue with the help from the video https://www.youtube.com/watch?v=FrZ9IJoDfkk. Instead of adding craftbukkit as a separate dependency, I'm using one containing both paper-api and craftbukkits components.

Cannot access Authentication plugin in KTOR, kotlin project

I am trying out KTOR for building backend server application. When I try to include implementation("io.ktor:ktor-auth:1.6.8") dependency, it gives me an error
Supertypes of the following classes cannot be resolved. Please make sure you have the required dependencies in the classpath:
class io.ktor.auth.Authentication.Feature, unresolved supertypes: io.ktor.application.ApplicationFeature
Adding -Xextended-compiler-checks argument might provide additional information.
Type mismatch: inferred type is Authentication.Feature but Plugin<TypeVariable(P), TypeVariable(B), TypeVariable(F)> was expected
Here is the error
fun Application.authentication() {
install(Authentication) { // here is the error
jwt {
}
}
}
I looked at the Authentication.kt file and it does not have any plugin in it.
how to correct this?
I took the version from mvnrepository https://mvnrepository.com/artifact/io.ktor/ktor-auth/1.6.8
EDIT. I was able to resolve it by adding different dependencies
implementation("io.ktor:ktor-server-auth-jvm:$ktor_version")
implementation("io.ktor:ktor-server-auth-jwt-jvm:$ktor_version")

ssl certificate issue for jgit in javafx app image versus javafx app runtime

I have developed a simple JavaFX app using jgit, that is allowing users to play with git.
When the app was started from the IntelliJ idea, I was able to clone the GitHub repo using my jgit implementation of the "git clone" command without any issues. But as soon as I created an image from my app and started the app from the image, I am getting an SSL certificate issue:
Exception:org.eclipse.jgit.api.errors.TransportException:
Secure connection to https://my-github-repo.git could not be established because of SSL problems.
I am trying to understand why I am getting the SSL certificate issue only when I am running the app from the image. Can somebody explain that? I understand that I can disable SSL verification (there are some questions answered on that topic), but I want to know why it is working from IDE and not from the created image...
here is my simplified git clone implementation for http:
try {
CloneCommand command = Git.cloneRepository();
command.setCredentialsProvider(new UsernamePasswordCredentialsProvider(httpUsername, httpPassword));
// run the clone command
command.setURI(repositoryUrl);
command.setDirectory(dirFramework);
git = command.call();
} catch (Exception e) {
LOG.error("Error occurred during task: Git clone: " + e);
}
For creating the image I am using the "org.beryx.runtime" plugin with the Gradle task "runtime".
Here is the build.gradle content:
plugins {
id 'java'
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.8'
id 'org.beryx.runtime' version '1.11.4'
}
group 'org.sovap'
version '1.0-SNAPSHOT'
sourceCompatibility = 11
targetCompatibility = 11
repositories {
mavenCentral()
}
dependencies {
// xml stuff
compile 'jakarta.xml.bind:jakarta.xml.bind-api:2.3.3'
compile 'org.glassfish.jaxb:jaxb-runtime:2.3.2'
compile 'jakarta.activation:jakarta.activation-api:1.2.2'
// logger
compile 'org.apache.logging.log4j:log4j-core:2.13.3'
compile 'org.slf4j:slf4j-api:1.7.30'
compile 'org.slf4j:slf4j-simple:1.7.30'
// cucumber
compile 'io.cucumber:gherkin:15.0.2'
// jgit
compile 'org.eclipse.jgit:org.eclipse.jgit:5.9.0.202009080501-r'
compile 'org.eclipse.jgit:org.eclipse.jgit.archive:5.9.0.202009080501-r'
compile 'org.eclipse.jgit:org.eclipse.jgit.ssh.jsch:5.9.0.202009080501-r'
// file utils
compile 'commons-io:commons-io:2.7'
//controlsfx
compile 'org.controlsfx:controlsfx:11.0.2'
}
javafx {
version = "15"
modules = ['javafx.controls', 'javafx.fxml', 'javafx.web', "javafx.graphics"]
}
application {
mainClassName = 'org.sovap.taman.Launcher'
applicationName = 'taman'
}
runtime {
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
imageDir = file("$buildDir/taman")
}
Edit 1:
How the image is created? - image is created with the plugin 'org.beryx.runtime' version '1.11.4', with Gradle task called 'runtime'. At the end of the build.gradle content you can see some specific configuration for runtime task.
Also, it is possible to include modules there as described here: https://badass-runtime-plugin.beryx.org/releases/latest/
I have tested the config with modules you are mentioning for runtime task in build.gradle (also one by one):
runtime {
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
imageDir = file("$buildDir/taman")
modules = ['jdk.crypto.cryptoki', 'jdk.crypto.ec', 'jdk.crypto.mscapi']
}
But with that I am getting following exception when starting the app from image:
Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/stream/XMLStreamException
at org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory.newConfigurationBuilder(ConfigurationBuilderFactory.java:38)
at org.apache.logging.log4j.core.config.properties.PropertiesConfigurationBuilder.<init>(PropertiesConfigurationBuilder.java:72)
at org.apache.logging.log4j.core.config.properties.PropertiesConfigurationFactory.getConfiguration(PropertiesConfigurationFactory.java:52)
at org.apache.logging.log4j.core.config.properties.PropertiesConfigurationFactory.getConfiguration(PropertiesConfigurationFactory.java:35)
at org.apache.logging.log4j.core.config.ConfigurationFactory$Factory.getConfiguration(ConfigurationFactory.java:551)
at org.apache.logging.log4j.core.config.ConfigurationFactory$Factory.getConfiguration(ConfigurationFactory.java:475)
at org.apache.logging.log4j.core.config.ConfigurationFactory.getConfiguration(ConfigurationFactory.java:323)
at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:687)
at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:708)
at org.apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:263)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:153)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:45)
at org.apache.logging.log4j.LogManager.getContext(LogManager.java:194)
at org.apache.logging.log4j.LogManager.getLogger(LogManager.java:602)
at org.sovap.taman.App.<clinit>(App.java:15)
at org.sovap.taman.Launcher.main(Launcher.java:6)
Caused by: java.lang.ClassNotFoundException: javax.xml.stream.XMLStreamException
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(Unknown Source)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(Unknown Source)
at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
... 16 more
What version of Java 11 are you using? - java version "11.0.8" 2020-07-14 LTS
Regarding the different versions of JDK for image and for IntelliJ IDEA environment - it should be using the same installation on my machine
I guess I need to add modules to the runtime task, but I do not know which ones and how to identify them... Any direction you can point me to?
Edit 2:
According to the accepted answer, I was missing modules in my runtime task configuration. Here is how I have figured which ones to add:
The plugin 'org.beryx.runtime' contains a task I used for suggesting modules for the runtime task (task: suggestModules)
After running it I have created a list of modules with the following runtime config (included the ones from accepted answer):
runtime {
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
imageDir = file("$buildDir/taman")
modules = [
'java.desktop',
'java.logging',
'java.xml',
'java.compiler',
'java.datatransfer',
'java.rmi',
'java.sql',
'java.naming',
'java.scripting',
'java.management',
'java.security.jgss',
'jdk.jfr',
'java.net.http',
'jdk.jsobject',
'jdk.xml.dom',
'jdk.unsupported',
'jdk.crypto.cryptoki',
'jdk.crypto.ec',
'jdk.crypto.mscapi']
}
Now everything works as expected.
The most likely situation is that you are missing a module in the JRE image related to crypto that is required to authenticate the SSL connection.
What jdk.crypto.* modules are in the final image?
Perhaps if one of these is missing it will affect the ability to handle the SSL certificates?
jdk.crypto.cryptoki
jdk.crypto.ec
jdk.crypto.mscapi
Since some aspects of the security/crypto code are done via service providers, perhaps when you generate the JRE image you should pass the
"--bind-services" option to "Link in service provider modules and their dependences"
You will need to share more details about how the image is created and what specific errors are reported. Try to include the full stack trace of any reported exceptions.
What version of Java 11 are you using?
Could you be running into this: JDK 11 SSL Error on valid certificate (working in previous versions)
(It is unlikely if you are running with the same JDK version in the IDE and the packaged image, but thought I would mention it just in case it gives you a hint.)

Gradle build doing nothing on WSL

I'm writing a Kotlin program, and using Gradle as the build system, as is customary in that language. I usually work on Windows, but it's time to start testing on Linux, so using WSL for that. Installed Gradle, cloned a copy of my code in WSL...
(base) a#DESKTOP-4B7M920:~/ayane$ gradle -version
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.codehaus.groovy.reflection.CachedClass (file:/usr/share/java/groovy-all.jar) to method java.lang.Object.finalize()
WARNING: Please consider reporting this to the maintainers of org.codehaus.groovy.reflection.CachedClass
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
------------------------------------------------------------
Gradle 4.4.1
------------------------------------------------------------
Build time: 2012-12-21 00:00:00 UTC
Revision: none
Groovy: 2.4.16
Ant: Apache Ant(TM) version 1.10.5 compiled on March 28 2019
JVM: 11.0.7 (Ubuntu 11.0.7+10-post-Ubuntu-2ubuntu218.04)
So far so good, that warning happens sometimes, doesn't seem to portend immediate trouble.
This is my build file, that works on Windows:
(base) a#DESKTOP-4B7M920:~/ayane$ cat build.gradle.kts
plugins {
kotlin("jvm") version "1.3.72"
}
repositories {
jcenter()
}
dependencies {
implementation(kotlin("stdlib"))
testImplementation("org.junit.jupiter:junit-jupiter:5.6.2")
}
tasks.test {
useJUnitPlatform()
testLogging {
events("passed", "skipped", "failed")
}
}
Here goes.
(base) a#DESKTOP-4B7M920:~/ayane$ gradle build
> Task :buildEnvironment
------------------------------------------------------------
Root project
------------------------------------------------------------
classpath
No dependencies
BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed
<-------------> 0% WAITING
Uh? I could understand if it threw an error because some prerequisite or other was unavailable. But no error, just nothing? What's going on?
You are using the newest version at this time of the Kotlin plugin for Gradle (1.3.72). However, you are using a really old version of Gradle (4.4.1). As you can read from the Kotlin documentation:
The Kotlin Gradle plugin 1.3.72 works with Gradle 4.9 and later.
It is unfortunate that the plugin doesn't check for this and give a more proper error message instead of just silently doing nothing. I guess you could create an issue for Jetbrains on this if you like.
Just as has been mentioned in the comment to your question, I also highly recommend using the wrapper. It ensures that the project is built with a particular declared version of Gradle that you, the build author, has decided on. Otherwise, you will have to document how to set up the environment correctly, including what version of Gradle to install.
Same thing goes for Java: be sure to clearly document which version is required or supported.
As for building in WSL, the only issue I've ever had with it was a remote build cache not working. This was because I had configured Git to checkout with POSIX line endings (LF) for source files, whereas the cache were populated on a Windows machine using CRLF line endings). It doesn't sound like you are using that feature, but other than that, everything has been working fine for me in WSL.

Gradle Kotlin Dsl Build for a Kotlin Gradle Plugin, which depends on a Groovy Class in the same Project

I have a Gradle plugin implemented with Kotlin, which is built with a gradle kotlin DSL build script. This works fine. The build script is as follows and is located in the buildSrc directory of project:
plugins {
groovy
`kotlin-dsl`
}
repositories {
mavenLocal()
mavenCentral()
jcenter()
}
dependencies {
testImplementation(gradleTestKit())
implementation(kotlin("gradle-plugin"))
implementation ("com.bmuschko:gradle-docker-plugin:6.1.3")
}
Now i want to call a existing Groovy Class in the same buildSrc Source Tree from the Kotlin Plugin code. This works fine in Intellij.
But when building with gradle i get a : unresolved reference Class for the Groovy Class.
Looking at the build, i see that the compileKotlin task is executed first. When i uncomment the failing reference, i see that the groovyCompile produces the correct binaries.
So i tried this:
tasks.compileKotlin {
dependsOn(tasks.compileGroovy)
}
Naturally that is not good enough, but i tried to get the build to compile the Groovy code first.
I got the following error:
Circular dependency between the following tasks:
:buildSrc:compileGroovy
\--- :buildSrc:compileJava
\--- :buildSrc:compileKotlin
\--- :buildSrc:compileGroovy (*)
So i tried without succeeding , to remove the compileJava task dependency from compileGroovy:
tasks.compileGroovy {
dependsOn.remove(tasks.compileJava)
}
Some problem as above. Basically it is unclear to me how to remove precondigured taskdependencies in gradle
What i really need is something equivalent to gradle groovy build as :
compileGroovy.dependsOn = compileGroovy.taskDependencies.values - 'compileJava'
compileKotlin.dependsOn compileGroovy
compileKotlin.classpath += files(compileGroovy.destinationDir)
classes.dependsOn compileKotlin
How would look that like the Gradle Kotlin Dsl?
Or are there better ways to solve this Groovy / Kotlin Code Dependency problem?
Version Info:
------------------------------------------------------------
Gradle 5.2.1
------------------------------------------------------------
Build time: 2019-02-08 19:00:10 UTC
Revision: f02764e074c32ee8851a4e1877dd1fea8ffb7183
Kotlin DSL: 1.1.3
Kotlin: 1.3.20
Groovy: 2.5.4
Ant: Apache Ant(TM) version 1.9.13 compiled on July 10 2018
JVM: 1.8.0_232 (AdoptOpenJDK 25.232-b09)
OS: Mac OS X 10.15.3 x86_64
I think this is equivalent, though I think it just knocks Java out of the picture, so Groovy/Kotlin/Java buildSrc code won't work...:
tasks {
val compileJava = named("compileJava", JavaCompile::class).get()
val compileKotlin = named("compileKotlin", KotlinCompile::class).get()
val compileGroovy = named("compileGroovy", GroovyCompile::class).get()
val classes by getting
compileGroovy.dependsOn.remove("compileJava")
compileKotlin.setDependsOn(mutableListOf(compileGroovy))
compileKotlin.classpath += files(compileGroovy.destinationDir)
classes.setDependsOn(mutableListOf(compileKotlin))
}
This has been vastly improved in Gradle 6.1
https://docs.gradle.org/6.1/release-notes.html#defining-compilation-order-between-groovy,-scala-and-java
And I'm not sure the above works for test ordering if they have unexpected language dependency ordering