https://kotlinlang.org logo
#ktor
Title
# ktor
m

MyCodeFlow

08/30/2021, 5:39 AM
Hello everyone. I have recently tried to install WebSocket feature on my Ktor Server (Ktor version 1.6.2) and implement simple chat example from ktor docs (Btw when following tutorial from chat example from docs i got 'Web socket feature is not installed Error' because in tutorial it recommends to open routing function before closing the Websocket feature install bracket, which is incorrect according to the answer i found in google - 'you should close install bracket before start writing routing for webScoket'. Anyway, when got rid of the previous error, when deploying on Heroku platform and trying to open my cloud server i got it crashed with the next Error: Exception in thread "main" java.lang.LinkageError: loader constraint violation: when resolving method "io.ktor.application.ApplicationEvents.subscribe(Lio/ktor/application/EventDefinition;Lkotlin/jvm/functions/Function1;) Lkotlinx/coroutines/DisposableHandle;" the class loader (instance of io/ktor/server/engine/OverridingClassLoader$ChildURLClassLoader) of the current class, io/ktor/websocket/WebSockets$Feature, and the class loader (instance of sun/misc/Launcher$AppClassLoader) for the method's defining class, io/ktor/application/ApplicationEvents, have different Class objects for the type kotlinx/coroutines/DisposableHandle used in the signature I guess it is kinda bug or problem with installing WebSocket feature on Server which is further deployed on Heroku platform. Is there any altrenative how can i implement WebSocket feature on my Server which is gonna be deployed on a Cloud based platform? P.S: When deleting code connected with installing and configuration of WebScoket feature, server runs well without crash when deployed on Heroku. My Application class code looks like:
Copy code
fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)

fun Application.module(testing: Boolean = false) {

    //initialization of the Database
    DataBaseFactory.init()
    val userDb = UserDataBaseDao() //Users Database
    val loveCardDb = LoveCardsDataBaseDao()
    val hashFunction = { s: String -> hash(s) }
    val jwtService = JwtService()

    //installing content receive/respond functionality
    install(ContentNegotiation) {
        json() //converter for serialization of kotlin classes
    }
    //installing authentication
    install(Authentication){
        jwt("jwt") {
            verifier(jwtService.varifier)
            realm = "Lovecard server"
            validate {
                val payload = it.payload
                val email = payload.getClaim("email").asString()
                val user = userDb.findUserByEmail(email)
                user
            }
        }
    }

    //installing WebSocket
    install(WebSockets) {
        pingPeriod = Duration.ofSeconds(15)
        timeout = Duration.ofSeconds(15)
        maxFrameSize = Long.MAX_VALUE
        masking = false
    }
    routing {
        //basic route on connection to server
        get("/") {
            call.respondText("Hello world!", contentType = ContentType.Text.Plain)
        }
        //echo unit of websocket
        webSocket("/echo") {
            send("Please enter your name")
            for (frame in incoming) {
                when (frame) {
                    is Frame.Text -> {
                        val receivedText = frame.readText()
                        if (receivedText.equals("bye", ignoreCase = true)) {
                            close(CloseReason(CloseReason.Codes.NORMAL, "Client said BYE"))
                        } else {
                            send(Frame.Text("Hi, $receivedText!"))
                        }
                    }
                }
            }
        }
        //Websocket for data exchange
        val connections = Collections.synchronizedSet<Connection?>(LinkedHashSet())
        webSocket("/connection") {
            val thisConnection = Connection(this)
            connections += thisConnection
            send("You've logged in as [${thisConnection.name}]")

            for (frame in incoming) {
                when (frame) {
                    is Frame.Text -> {
                        val receivedText = frame.readText()
                        val textWithUsername = "[${thisConnection.name}]: $receivedText"
                        connections.forEach {
                            it.session.send(textWithUsername)
                        }
                    }
                }
            }
        }

        //register Authentication routes
        authRouting(hashFunction, jwtService)
        //register User routes
        userRouting(userDb, jwtService, hashFunction)
        //register LoveCards routes
        loveCardsRouting(loveCardDb)
    }
    
    class Connection(val session: DefaultWebSocketSession) {

      companion object{
          var lastId = AtomicInteger(0)
      }
    val name = "User ${lastId.getAndIncrement()}"
    }
}
🧵 4
a

Aleksei Tirman [JB]

08/30/2021, 1:55 PM
m

MyCodeFlow

08/30/2021, 2:16 PM
I replied in the section as well
2 Views