vertx-guide-for-java-devs
vertx-guide-for-java-devs copied to clipboard
Example of kotlin version with service proxy
Hi, can anybody provide kotlin version of this tutorial with service proxies? I couldn't manage it to work;
Every time I get such error on build:
build/tmp/kapt3/stubs/main/uz/craftier/database/WikiDatabaseService.java:46: error: Could not generate model for uz.craftier.database.WikiDatabaseService.Companion: @VertxGen can only be used with interfaces or enums in uz.craftier.database.WikiDatabaseService.Companion
Here is my interface:
And, added kapt plugin to build.gradle:
apply plugin: 'kotlin-kapt'
dependencies {
...
kapt "io.vertx:vertx-codegen:$vertx_version:processor"
compileOnly "io.vertx:vertx-codegen:$vertx_version"
...
}
I ran into the same issue when experimenting with service proxies.
The problematic part is the companion object
, which trips up the annotation generator.
A possible workaround:
@ProxyGen
@VertxGen
interface MyService {
fun myMethod(param: String)
}
object MyServiceFactory {
fun create(vertx: Vertx): MyService{
return MyServiceImpl(vertx)
}
fun createProxy(vertx: Vertx, address: String, options: DeliveryOptions = DeliveryOptions()): MyService {
return MyServiceVertxEBProxy(vertx, address, options)
}
}
Is it also possible to generate the rx version of the proxy?
I have the same problem on rx version of the service proxy..
I also get the same problem, and then based on @abelhegedus' idea, here my workaround:
@ProxyGen
interface WikiDatabaseService {
@Fluent
fun fetchAllPages(resultHandler: Handler<AsyncResult<JsonArray>>): WikiDatabaseService
@Fluent
fun fetchPage(name: String, resultHandler: Handler<AsyncResult<JsonObject>>): WikiDatabaseService
@Fluent
fun createPage(title: String, markdown: String, resultHandler: Handler<AsyncResult<Void>>): WikiDatabaseService
@Fluent
fun savePage(id: Int, markdown: String, resultHandler: Handler<AsyncResult<Void>>): WikiDatabaseService
@Fluent
fun deletePage(id: Int, resultHandler: Handler<AsyncResult<Void>>): WikiDatabaseService
@GenIgnore
companion object {
fun create(dbClient: JDBCClient, sqlQueries: Map<SqlQuery, String>,
readyHandler: Handler<AsyncResult<WikiDatabaseService>>): WikiDatabaseService =
WikiDatabaseServiceImpl(dbClient, sqlQueries, readyHandler)
fun createProxy(vertx: Vertx, address: String): WikiDatabaseService =
WikiDatabaseServiceVertxEBProxy(vertx, address)
}
}
I added @GenIgnore
annotation on companion object
because kapt
keeps complaining about Map<SqlQuery, String>
and JDBCClient
are not legal types.
@desmondtzq @mustafakibar To my knowledge there is no way to do this in 1.2.x as interfaces are not allowed to have @JvmStatic
members.
However, support for this is added in 1.3 (https://youtrack.jetbrains.com/issue/KT-6301) meaning that the following should work:
@ProxyGen
interface WikiDatabaseService {
@Fluent
fun fetchAllPages(resultHandler: Handler<AsyncResult<JsonArray>>): WikiDatabaseService
@Fluent
fun fetchPage(name: String, resultHandler: Handler<AsyncResult<JsonObject>>): WikiDatabaseService
@Fluent
fun createPage(title: String, markdown: String, resultHandler: Handler<AsyncResult<Void>>): WikiDatabaseService
@Fluent
fun savePage(id: Int, markdown: String, resultHandler: Handler<AsyncResult<Void>>): WikiDatabaseService
@Fluent
fun deletePage(id: Int, resultHandler: Handler<AsyncResult<Void>>): WikiDatabaseService
@GenIgnore
companion object {
@JvmStatic
fun create(dbClient: JDBCClient, sqlQueries: Map<SqlQuery, String>,
readyHandler: Handler<AsyncResult<WikiDatabaseService>>): WikiDatabaseService =
WikiDatabaseServiceImpl(dbClient, sqlQueries, readyHandler)
@JvmStatic
fun createProxy(vertx: Vertx, address: String): WikiDatabaseService =
WikiDatabaseServiceVertxEBProxy(vertx, address)
}
}
(You can actually use this feature now, as per Michael Bogdanov's comment, though since it's pre-release it's technically not stable.)
@rgmz , I've tried adding @JvmStatic like you did on Kotlin 1.3.21n and I still have this error ".Companion is not legal for use for a constant type in code generation"
Any other workarounds that you might suggest?
@raghumulukutla A change introduced in Vert.x 3.6.x inadvertently broke this.
I created a pull request to fix this—hopefully it makes it into the next release, or a viable workaround is provided.
@gmariotti do you have any suggested workarounds to mimic this behaviour?
@rgmz sorry, I wanted to look into it but I never found the time. With @vietj, we discussed in the past to try to find a solution that wasn't Kotlin specific but I didn't find anything so far
@gmariotti @rgmz Thanks! I've also tried using a Vertx version < 3.6.x. Reproduces the same error.
@raghumulukutla Can you provide a reproducer? I do not get the error in version 3.5.4.
Try this ad-hoc example: https://github.com/rgmz/vertx-kotlin-service-proxy
@rgmz I'm sorry, I should correct myself. I do not get the same error. But I do get a kaptKotlin error. Here's the reproducer: https://github.com/raghumulukutla/vertx-guide-kotlin/tree/service_proxy/src/main/kotlin/com/raghu/vertx3guide/wiki/step3/database
WikiDatabaseService.kt
package com.raghu.vertx3guide.wiki.step3.database
import io.vertx.codegen.annotations.Fluent
import io.vertx.codegen.annotations.GenIgnore
import io.vertx.codegen.annotations.ProxyGen
import io.vertx.codegen.annotations.VertxGen
import io.vertx.core.AsyncResult
import io.vertx.core.Handler
import io.vertx.core.Vertx
import io.vertx.core.json.JsonArray
import io.vertx.core.json.JsonObject
import io.vertx.ext.asyncsql.AsyncSQLClient
@ProxyGen
@VertxGen
interface WikiDatabaseService {
@Fluent
fun fetchAllPages(resultHandler: Handler<AsyncResult<JsonArray>>):WikiDatabaseService
@Fluent
fun fetchPage(name:String,resultHandler: Handler<AsyncResult<JsonObject>>):WikiDatabaseService
@Fluent
fun createPage(title:String, markdown:String, resultHandler: Handler<AsyncResult<Void>>):WikiDatabaseService
@Fluent
fun savePage(id:Int, markdown:String,resultHandler: Handler<AsyncResult<Void>>):WikiDatabaseService
@Fluent
fun deletePage(id:Int, resultHandler: Handler<AsyncResult<Void>>):WikiDatabaseService
@GenIgnore
companion object {
@GenIgnore
@JvmStatic
fun create(dbClient:AsyncSQLClient, sqlQueries: HashMap<SqlQuery, String>, readyHandler: Handler<AsyncResult<WikiDatabaseService>>):WikiDatabaseService {
return WikiDatabaseServiceImpl(dbClient, sqlQueries, readyHandler)
}
@GenIgnore
@JvmStatic
fun createProxy(vertx: Vertx, address:String ):WikiDatabaseService {
return WikiDatabaseServiceVertxEBProxy(vertx, address)
}
}
}
Error:
could not generate model for com.raghu.vertx3guide.wiki.step3.database.WikiDatabaseService#create(io.vertx.ext.asyncsql.AsyncSQLClient,java.util.HashMap<com.raghu.vertx3guide.wiki.step3.database.SqlQuery,java.lang.String>,io.vertx.core.Handler<io.vertx.core.AsyncResult<com.raghu.vertx3guide.wiki.step3.database.WikiDatabaseService>>): type java.util.HashMap<com.raghu.vertx3guide.wiki.step3.database.SqlQuery,java.lang.String> is not legal for use for a parameter in code generation
public static com.raghu.vertx3guide.wiki.step3.database.WikiDatabaseService create(@org.jetbrains.annotations.NotNull()
just use java interface in kotlin project
Is extension function a possible workaround? So that we won't need to setup companion object
@ProxyGen
interface WikiDatabaseService{
...
}
fun WikiDatabaseService.create(
dbClient:AsyncSQLClient,
sqlQueries: HashMap<SqlQuery, String>,
readyHandler: Handler<AsyncResult<WikiDatabaseService>>
):WikiDatabaseService = WikiDatabaseServiceImpl(dbClient, sqlQueries, readyHandler)
fun WikiDatabaseService.createProxy(
vertx: Vertx,
address:String
):WikiDatabaseService = WikiDatabaseServiceVertxEBProxy(vertx, address)
Is extension function a possible workaround? So that we won't need to setup companion object
Unfortunately Kotlin does not support static extension functions; in order to call create
you'd need to already have an instance of WikiDatabaseServiceImpl
.
Additionally, non-static methods are not picked up by codegen so you would need to manually define factory methods for everything, e.g. the rxified API.
@raghumulukutla A change introduced in Vert.x 3.6.x inadvertently broke this.
I created a pull request to fix this—hopefully it makes it into the next release, or a viable workaround is provided.
FYI, once Vert.x 4.1.0 is released this issue should be resolved.
Try this ad-hoc example: https://github.com/rgmz/vertx-kotlin-service-proxy
4.1.0 isn't released yet, but this is now updated to 4.1.0.CR2.