Strange exception thrown in Ktor - kotlin

Today i encountered a strange status page exception being thrown in Ktor.
I am trying to build a simple api with ktor and i did this Route:
fun Route.phrase(db : Repository){
post(PHRASE_ENDPOINT){
val request = call.receive<Request>()
val phrase = db.add(EmojiPhrase(request.toString(), request.toString()))
this.call.respond(phrase)
}}
when i try to send the request i get
java.lang.ClassNotFoundException: kotlinx.coroutines.io.ByteReadChannel
has anyone encountered this problem
im using :
ktor_version=1.3.2,
kotlin_version=1.4.10,
moshi_version= 1.0.1

Issue appears to be in moshi converter: https://github.com/rharter/ktor-moshi/issues/7#issuecomment-580977097
Until the PR is merged, you can use the patched version through
jitpack
buildscript {
repositories {
jcenter()
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.cs125-illinois:ktor-moshi:7252ca49ed'
}

Related

Unable to add duplicate strategy in gradle

Disclaimer: I am new to gradle, so it's likely I'm missing something simple.
Background: I am splitting a service into two services that will live in the same repo. The second service (tester) uses code from the first service (engine), which I have managed to tell gradle. But I have an issue.
Building the tester fails, giving the following error:
Execution failed for task ':engine:processResources'.
Entry application.properties is a duplicate but no duplicate handling strategy has been set
It seems this is a common issue in gradle that someone has already posted about. Unfortunately, pasting each of the responses in my build file has yielded nothing.
I've also tried the kotlin solutions in this thread with similar results: I keep getting the duplicate strategy not set error.
Surely I'm missing something but I can't for the life of me figure out what.
Tester build.gradle.kts Code
plugins {
kotlin("jvm") version "1.5.10"
kotlin("plugin.serialization") version "1.5.30"
id("net.linguica.maven-settings") version "0.5"
}
group = "my.group"
version = "1.0"
repositories {
mavenCentral()
maven(url = "my/url") {
name = "maven-snapshots"
authentication {
create<BasicAuthentication>("basic")
}
}
maven(url = "my/other/url") {
name = "maven-releases"
authentication {
create<BasicAuthentication>("basic")
}
}
}
//just trying all the things
rootProject.tasks.named("processResources", Copy::class.java) {
duplicatesStrategy = DuplicatesStrategy.WARN
}
tasks.withType<ProcessResources>() {
duplicatesStrategy = DuplicatesStrategy.WARN
}
tasks.withType<Copy>() {
duplicatesStrategy = DuplicatesStrategy.WARN
}
tasks.withType<Jar>() {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
dependencies {
implementation(project(":engine"))
}

Ktor client NoSuchMethodError

I want to write a telegram bot and use this library from Github for that. In this telegram bot I need to make some requests to another service, so I want to use the ktor client library for that. However when I try to instantiate the ktor httpClient I get the following exception:
Exception in thread "main" java.lang.NoSuchMethodError: 'void io.ktor.util.collections.ConcurrentMap.<init>(io.ktor.util.Lock, int, int, kotlin.jvm.internal.DefaultConstructorMarker)'
at io.ktor.client.engine.cio.CIOEngine.<init>(CIOEngine.kt:32)
at io.ktor.client.engine.cio.CIO.create(CIOCommon.kt:23)
at io.ktor.client.HttpClientKt.HttpClient(HttpClient.kt:42)
at io.ktor.client.HttpClientJvmKt.HttpClient(HttpClientJvm.kt:21)
at io.ktor.client.HttpClientJvmKt.HttpClient$default(HttpClientJvm.kt)
at problem.ktor.MainKt.main(Main.kt:9)
at problem.ktor.MainKt.main(Main.kt)
I made a new project and narrowed the problem down to the telegram bot library, which apparently conflicts with the kotr library. I assume some version conflict of the kotr library, because that's where the exception happens. How can I solve the conflict?
Here is a minimal reproducible example. Use the following build.gradle.kts file:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
application
kotlin("jvm") version "1.4.30"
}
repositories {
mavenCentral()
maven(url = "https://jitpack.io")
}
dependencies {
implementation("io.ktor:ktor-client-core:1.5.2")
implementation("io.ktor:ktor-client-cio:1.5.2")
implementation("com.github.kotlin-telegram-bot:kotlin-telegram-bot:6.0.4")
}
And run the following minimal main function:
import io.ktor.client.*
fun main() {
HttpClient()
}
Maybe it's important, I use Java 15.0.2.
The problematic dependency is com.github.kotlin-telegram-bot.kotlin-telegram-bot:webhook:6.0.4. As a workaround you can exclude it since it's just a sample:
implementation("com.github.kotlin-telegram-bot:kotlin-telegram-bot:6.0.4") {
exclude(module = "webhook")
}

Ktor - post unhanldled error with coroutines

I a new to Kotlin and Ktor in particular, so I have tried to do simple post request. As you can see below, there is nothing special.
routing {
post("/articles/add"){
val post = call.receive<ArticleRequest>()
println(post)
}
Error shown in logs is below and I don't understand why I should use here coroutines.
ERROR Application - Unhandled: POST - /articles/add
java.lang.IllegalStateException: Using blocking primitives on this dispatcher is not allowed. Consider using async channel instead or use blocking primitives in withContext(Dispatchers.IO) instead.
I am using 1.4.2 version. I would appreciate any help.
If you are using Jackson this is a bug and there is a suggested workaround:
routing {
post("/articles/add") {
with(Dispatchers.IO) {
val post = call.receive<ArticleRequest>()
println(post)
}
}
}
Or you can rollback to 1.4.1 until the bug is solved.
I've experienced the same issue after upgrading to ktor 1.4.2 and Kotlin 1.4.20, and I used both Moshi and Gson on this specific project but I don't believe they are causing this issue.
If you have a 'gradle.properties' file, add these ( or whatever version you wish to use ) :
ktor_version=1.3.2
kotlin_version=1.3.70.
Otherwise, in your 'build.gradle' file, create variables for different version :
buildscript {
ext.kotlin_version = '1.3.70'
ext.ktor_version = '1.3.2'
repositories {
jcenter()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
Then sync your gradle, run project.. all should be good.
However if you still experience some gradle-related issue, try this :
go to gradle (folder) -> wrapper -> open gradle_wrapper.properties and make sure the url has version 6.x.x or 5.x.x.
Mine looks like this currently:
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

Kotlin class servlet provoke NoClassDefFoundError

In a sample Java servlet project in my IntelliJ IDE, i have created this class in Kotlin :
#WebServlet(name = "TwitterAPIServlet", description = "This is used to test the servlet api", urlPatterns = ["/twitterAPIServlet"])
class TwitterAPIServlet : HttpServlet() {
#Throws(IOException::class)
override fun doGet(req: HttpServletRequest, resp: HttpServletResponse) {
// Print answer
val out = resp.writer
out.println("Request Done : </br>")
}
}
When i am trying to call this with my .jsp page, i have this error :
2020-05-10 15:30:34.218:WARN:oejs.HttpChannel:qtp60559178-27: /twitterAPIServlet
java.lang.NoClassDefFoundError: kotlin/jvm/internal/Intrinsics
at main.java.co.rezo.api.internal.v1.TwitterAPIServlet.doGet(TwitterAPIServlet.kt)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
When i am trying the same code in Java, it's working :
#WebServlet(
name = "TwitterAPIServlet",
description = "This is used to test the servlet api",
urlPatterns = "/twitterAPIServlet")
public class TwitterAPIServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
PrintWriter out = resp.getWriter();
out.println("Request Done : </br>");
}
}
What can i do to make my Kotlin code working?
Most probably the issue is that Kotlin's standard library is not included in the generated WAR (or is not on a classpath if you run the exploded app). Make sure to include it in your build.
Instructions for Gradle can be found in the official examples repository: kotlin-examples.
Maven is similar: https://kotlinlang.org/docs/reference/using-maven.html.
In case of pure IDEA (though it's recommended to use one of the build tools above), check the projects settings:
You should see Kotlin's stdlib included in the artifact:

java.lang.UnsupportedOperationException: Packages and file facades are not yet supported in Kotlin reflection

When starting a basic Ktor app, I get:
Exception in thread "main" java.lang.UnsupportedOperationException: Packages and file facades are not yet supported in Kotlin reflection. Meanwhile please use Java reflection to inspect this class: class com.example.ApplicationKt
at kotlin.reflect.jvm.internal.KClassImpl.reportUnresolvedClass(KClassImpl.kt:301)
at kotlin.reflect.jvm.internal.KClassImpl.access$reportUnresolvedClass(KClassImpl.kt:43)
at kotlin.reflect.jvm.internal.KClassImpl$Data$descriptor$2.invoke(KClassImpl.kt:53)
at kotlin.reflect.jvm.internal.KClassImpl$Data$descriptor$2.invoke(KClassImpl.kt:44)
at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:92)
at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:31)
at kotlin.reflect.jvm.internal.KClassImpl$Data.getDescriptor(KClassImpl.kt)
at kotlin.reflect.jvm.internal.KClassImpl$Data$objectInstance$2.invoke(KClassImpl.kt:106)
at kotlin.reflect.jvm.internal.ReflectProperties$LazyVal.invoke(ReflectProperties.java:62)
at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:31)
at kotlin.reflect.jvm.internal.KClassImpl$Data.getObjectInstance(KClassImpl.kt)
at kotlin.reflect.jvm.internal.KClassImpl.getObjectInstance(KClassImpl.kt:239)
at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.createModuleContainer(ApplicationEngineEnvironmentReloading.kt:328)
at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.executeModuleFunction(ApplicationEngineEnvironmentReloading.kt:317)
at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.instantiateAndConfigureApplication(ApplicationEngineEnvironmentReloading.kt:275)
at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.createApplication(ApplicationEngineEnvironmentReloading.kt:127)
at io.ktor.server.engine.ApplicationEngineEnvironmentReloading.start(ApplicationEngineEnvironmentReloading.kt:247)
at io.ktor.server.netty.NettyApplicationEngine.start(NettyApplicationEngine.kt:106)
at io.ktor.server.netty.NettyApplicationEngine.start(NettyApplicationEngine.kt:18)
at io.ktor.server.engine.ApplicationEngine$DefaultImpls.start$default(ApplicationEngine.kt:52)
at io.ktor.server.netty.EngineMain.main(EngineMain.kt:17)
at com.example.ApplicationKt.main(Application.kt:10)
The app is just:
fun main(args: Array<String>): Unit = EngineMain.main(args)
fun Application.demoModule() {
routing {
get("/") {
call.respondText("Hello ${call.parameters["name"]}")
}
}
}
I just noticed the file resources.application.conf had an issue.
It had the wrong module name. I changed com.example.ApplicationKt.module to com.example.ApplicationKt.demoModule:
ktor {
deployment {
port = 8080
port = ${?PORT}
}
application {
modules = [ com.example.ApplicationKt.demoModule ]
}
}
What's annoying is that the error help says nothing about it.