悬浮函数只能在vertx的协程体内调用
Suspension functions can be called only within coroutine body in vertx
我有以下未编译的代码:
private suspend fun createRoutes(router: Router, auth: OAuth2Auth): Unit {
val oauth2 = OAuth2AuthHandler.create(vertx, auth)
val authz = KeycloakAuthorization.create()
router.route().handler(LoggerHandler.create())
router.route("/api/*").handler(oauth2)
router.route("/api/greet").handler {
println(RoleBasedAuthorization.create("ad-admins").match(it.user()))
authz.getAuthorizations(it.user()).await()
}
}
编译器抱怨:
Suspension functions can be called only within coroutine body
没有协程,只好写成回调方式:
private fun createRoutes(router: Router, auth: OAuth2Auth): Unit {
val oauth2 = OAuth2AuthHandler.create(vertx, auth)
val authz = KeycloakAuthorization.create()
router.route().handler(LoggerHandler.create())
router.route("/api/*").handler(oauth2)
router.route("/api/greet").handler {
println(RoleBasedAuthorization.create("ad-admins").match(it.user()))
authz.getAuthorizations(it.user())
.onSuccess { _ ->
println(RoleBasedAuthorization.create("ad-admins").match(it.user()))
val res = it.response()
res.putHeader("content-type", "text/plain")
// Write to the response and end it
res.end("I am interests path")
}
}
}
但是我想使用协程而不是回调样式。
更新
这就是全部代码:
class MainVerticle : CoroutineVerticle() {
private suspend fun initConfig(): JsonObject {
val yamlConfigOpts = ConfigStoreOptions()
.setFormat("yaml")
.setType("file")
.setConfig(JsonObject().put("path", "config.yaml"))
val configRetrieverOpts = ConfigRetrieverOptions()
.addStore(yamlConfigOpts)
val configRetriever = ConfigRetriever.create(vertx, configRetrieverOpts)
return configRetriever.config.await()
}
private suspend fun createJwtAuth(): OAuth2Auth =
KeycloakAuth.discover(
vertx,
OAuth2Options()
.setFlow(OAuth2FlowType.AUTH_CODE)
.setClientID("svc")
.setClientSecret("9d782e45-67e7-44b1-9b74-864f45f9a18f")
.setSite("https://oic.dev.databaker.io/auth/realms/databaker")
).await()
private suspend fun createRoutes(router: Router, auth: OAuth2Auth): Unit {
val oauth2 = OAuth2AuthHandler.create(vertx, auth)
val authz = KeycloakAuthorization.create()
router.route().handler(LoggerHandler.create())
router.route("/api/*").handler(oauth2)
router.route("/api/greet").handler {
println(RoleBasedAuthorization.create("ad-admins").match(it.user()))
authz.getAuthorizations(it.user()).await()
}
}
private suspend fun server(router: Router): HttpServer {
val server = vertx.createHttpServer()
return server.requestHandler(router)
.listen(8080)
.onSuccess {
println("HTTP server started on port ${it.actualPort()}")
}
.onFailure {
println("Failed to start the server. Reason ${it.message}")
}
.await()
}
override suspend fun start() {
val router = Router.router(vertx)
createRoutes(router, createJwtAuth())
server(router)
}
}
我得到的错误是:
authz.getAuthorizations(it.user()).await()
如果您愿意在 Kotlin 中编写某种包装器,那么使用协程真的很容易。对于初学者,请查看 documentation.
协程可以简单到GlobalScope.launch { createRoutes(router, auth) }
您不应在 Vert.x 代码中使用 GlobalScope
,因为它会破坏结构化并发的概念。
要从 CoroutineVerticle 启动协程,您可以简单地使用 launch() 函数:
router.route("/api/greet").handler {
launch {
// Your code goes here
}
}
不过您必须使用 suspend
关键字标记您的函数。
我有以下未编译的代码:
private suspend fun createRoutes(router: Router, auth: OAuth2Auth): Unit {
val oauth2 = OAuth2AuthHandler.create(vertx, auth)
val authz = KeycloakAuthorization.create()
router.route().handler(LoggerHandler.create())
router.route("/api/*").handler(oauth2)
router.route("/api/greet").handler {
println(RoleBasedAuthorization.create("ad-admins").match(it.user()))
authz.getAuthorizations(it.user()).await()
}
}
编译器抱怨:
Suspension functions can be called only within coroutine body
没有协程,只好写成回调方式:
private fun createRoutes(router: Router, auth: OAuth2Auth): Unit {
val oauth2 = OAuth2AuthHandler.create(vertx, auth)
val authz = KeycloakAuthorization.create()
router.route().handler(LoggerHandler.create())
router.route("/api/*").handler(oauth2)
router.route("/api/greet").handler {
println(RoleBasedAuthorization.create("ad-admins").match(it.user()))
authz.getAuthorizations(it.user())
.onSuccess { _ ->
println(RoleBasedAuthorization.create("ad-admins").match(it.user()))
val res = it.response()
res.putHeader("content-type", "text/plain")
// Write to the response and end it
res.end("I am interests path")
}
}
}
但是我想使用协程而不是回调样式。
更新
这就是全部代码:
class MainVerticle : CoroutineVerticle() {
private suspend fun initConfig(): JsonObject {
val yamlConfigOpts = ConfigStoreOptions()
.setFormat("yaml")
.setType("file")
.setConfig(JsonObject().put("path", "config.yaml"))
val configRetrieverOpts = ConfigRetrieverOptions()
.addStore(yamlConfigOpts)
val configRetriever = ConfigRetriever.create(vertx, configRetrieverOpts)
return configRetriever.config.await()
}
private suspend fun createJwtAuth(): OAuth2Auth =
KeycloakAuth.discover(
vertx,
OAuth2Options()
.setFlow(OAuth2FlowType.AUTH_CODE)
.setClientID("svc")
.setClientSecret("9d782e45-67e7-44b1-9b74-864f45f9a18f")
.setSite("https://oic.dev.databaker.io/auth/realms/databaker")
).await()
private suspend fun createRoutes(router: Router, auth: OAuth2Auth): Unit {
val oauth2 = OAuth2AuthHandler.create(vertx, auth)
val authz = KeycloakAuthorization.create()
router.route().handler(LoggerHandler.create())
router.route("/api/*").handler(oauth2)
router.route("/api/greet").handler {
println(RoleBasedAuthorization.create("ad-admins").match(it.user()))
authz.getAuthorizations(it.user()).await()
}
}
private suspend fun server(router: Router): HttpServer {
val server = vertx.createHttpServer()
return server.requestHandler(router)
.listen(8080)
.onSuccess {
println("HTTP server started on port ${it.actualPort()}")
}
.onFailure {
println("Failed to start the server. Reason ${it.message}")
}
.await()
}
override suspend fun start() {
val router = Router.router(vertx)
createRoutes(router, createJwtAuth())
server(router)
}
}
我得到的错误是:
authz.getAuthorizations(it.user()).await()
如果您愿意在 Kotlin 中编写某种包装器,那么使用协程真的很容易。对于初学者,请查看 documentation.
协程可以简单到GlobalScope.launch { createRoutes(router, auth) }
您不应在 Vert.x 代码中使用 GlobalScope
,因为它会破坏结构化并发的概念。
要从 CoroutineVerticle 启动协程,您可以简单地使用 launch() 函数:
router.route("/api/greet").handler {
launch {
// Your code goes here
}
}
不过您必须使用 suspend
关键字标记您的函数。