是否可以将Spring HATEOAS WebFluxLinkBuilders与Kotlin协同程序一起使用?
我正在尝试将以下反应式代码转换为kotlin协程:是否可以将Spring HATEOAS WebFluxLinkBuilders与Kotlin协同程序一起使用?,spring,kotlin,spring-hateoas,Spring,Kotlin,Spring Hateoas,我正在尝试将以下反应式代码转换为kotlin协程: @GetMapping fun getAllTodosMono():Mono= 存储库 .findAll() .LIST() .flatMap{mkSelfLinkMono(it)} 私人娱乐mkSelfLinkMono(列表:列表):Mono{ val method=methodOn(Controller::class.java).getAllTodosMono() val selfLink=linkTo(方法).withSelfRel().
@GetMapping
fun getAllTodosMono():Mono=
存储库
.findAll()
.LIST()
.flatMap{mkSelfLinkMono(it)}
私人娱乐mkSelfLinkMono(列表:列表):Mono{
val method=methodOn(Controller::class.java).getAllTodosMono()
val selfLink=linkTo(方法).withSelfRel().tomino()
返回selfLink.map{CollectionModel.of(list,it)}
}
协同程序版本:
@GetMapping
suspend fun getAllTodosCoroutine():CollectionModel=
存储库
.findAll()
.LIST()
.单
.let{mkSelfLinkCoroutine(it)}
private suspend fun mkSelfLinkCorroutine(列表:列表):CollectionModel{
val method=methodOn(Controller::class.java)
val selfLink=linkTo(方法).withSelfRel().toMono().waitingsingle()
return CollectionModel.of(列表,自链接)
}
但是,我在尝试运行代码时遇到运行时错误
java.lang.ClassCastException:class org.springframework.hateoas.server.core.LastInvocationAware$$EnhancerBySpringCGLIB$$d8fd0e7e不能强制转换为类org.springframework.hateoas.CollectionModel(org.springframework.hateoas.server.core.LastInvocationAware$$EnhancerBySpringCGLIB$$d8fd0e7e位于加载程序org.springframework.boot.devtools.restart.classloader.RestartClassLoader@62b177e9的未命名模块中;org.springframework.hateoas.CollectionModel位于加载程序“app”的未命名模块中)
我怀疑methodOn(…)不支持挂起函数。唯一有效的解决方案是手动构建链接,而不是使用linkTo(…)函数:
private fun mkSelfLink(list:list):CollectionModel{
返回链接
.of(“/api/v1/todos”)
.withSelfRel()
.let{CollectionModel.of(list,it)}
}
但是,我失去了链接到REST控制器中现有端点的能力,也失去了自动添加到链接uri的主机的能力
我错过什么了吗
编辑:以下是指向我的github repo的链接:
如果将下面的代码示例粘贴到TodoController中,替换原来的getTodo(…)方法,则可以看到上面描述的失败
private-suspend-fun-Todo.withSelfLinkByBuilder():EntityModel{
val method=methodOn(Controller::class.java).getTodo(id!!)
val selfLink=linkTo(方法).withSelfRel().toMono().waitingsingle()
返回(此,自链接)的EntityModel.of
}
@GetMapping(“{id}”)
suspend fun getTodo(@PathVariable id:ObjectId)=
repository.findById(id)?.withSelfLinkByBuilder()
?:抛出ResponseStatusException(未找到HttpStatus.NOT_)
您可能忘了将协同程序添加到项目中。请将这些依赖项添加到gradle文件中:
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
嗯,我找到了一个解决方案,我不知道这是否是一个令人满意的解决方案,但它仍然有效 通过简单地将函数调用链接在一起,运行时似乎可以按预期工作:
private suspend fun mkSelfLinkCoroutine(list: List<TodoItem>): CollectionModel<TodoItem> {
val selfLink = linkTo(methodOn(Controller::class.java)
.getAllTodosCoroutine())
.withSelfRel()
.toMono()
.awaitSingle()
return CollectionModel.of(list, selfLink)
}
private-suspend-fun mkSelfLinkCoroutine(列表:列表):CollectionModel{
val selfLink=linkTo(methodOn(Controller::class.java)
.getAllTodosCoroutine())
.withSelfRel()
.toMono()
.单
return CollectionModel.of(列表,自链接)
}
这真的很奇怪,但事实就是如此。我检查了我的依赖项,并且coroutines reactor和core都是依赖项列表的一部分。我更新了我的原始问题,因此有一个指向我的github repo的链接,其中有一些演示代码可供摆弄(例如将上面的代码粘贴到控制器中,并看到它失败).谢谢!我确认它(以某种方式)是有效的,并向我的回购协议提交了变更细节: