spring - 是否可以将 Spring HATEOAS WebFluxLinkBuilders 与 Kotlin 协程一起使用?

标签 spring kotlin spring-hateoas

我正在尝试将以下响应式代码转换为 kotlin 协程:

  @GetMapping
  fun getAllTodosMono(): Mono<CollectionModel<TodoItem>> =
      repository
        .findAll()
        .collectList()
        .flatMap { mkSelfLinkMono(it) }

  private fun mkSelfLinkMono(list: List<TodoItem>): Mono<CollectionModel<TodoItem>> {
    val method = methodOn(Controller::class.java).getAllTodosMono()
    val selfLink = linkTo(method).withSelfRel().toMono()
    return selfLink.map { CollectionModel.of(list, it) }
  }

协程版本:

  @GetMapping
  suspend fun getAllTodosCoroutine(): CollectionModel<TodoItem> =
      repository
        .findAll()
        .collectList()
        .awaitSingle()
        .let { mkSelfLinkCoroutine(it) }

  private suspend fun mkSelfLinkCoroutine(list: List<TodoItem>): CollectionModel<TodoItem> {
    val method = methodOn(Controller::class.java).getAllTodosCoroutine()
    val selfLink = linkTo(method).withSelfRel().toMono().awaitSingle()
    return CollectionModel.of(list, selfLink)
  }

但是,我在尝试运行代码时遇到运行时错误。

java.lang.ClassCastException: class org.springframework.hateoas.server.core.LastInvocationAware$$EnhancerBySpringCGLIB$$d8fd0e7e cannot be cast to class org.springframework.hateoas.CollectionModel (org.springframework.hateoas.server.core.LastInvocationAware$$EnhancerBySpringCGLIB$$d8fd0e7e is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @62b177e9; org.springframework.hateoas.CollectionModel is in unnamed module of loader 'app')

我怀疑 methodOn(...) 不支持挂起函数。唯一实际可行的解决方案是手动构建链接,而不是使用 linkTo(...) 函数:

  private fun mkSelfLink(list: List<TodoItem>): CollectionModel<TodoItem> {
    return Link
      .of("/api/v1/todos")
      .withSelfRel()
      .let { CollectionModel.of(list, it) }
  }

但是,我无法链接到我的 REST Controller 中的现有端点以及自动添加到链接 uri 的主机。

我错过了什么吗?

编辑:这是我的 github 存储库的链接:https://github.com/enolive/kotlin-coroutines/tree/master/todos-coroutini

如果您将以下代码示例粘贴到 TodoController 中替换原来的 getTodo(...) 方法,您会看到我上面描述的失败。

private suspend fun Todo.withSelfLinkByBuilder(): EntityModel<Todo> {
    val method = methodOn(Controller::class.java).getTodo(id!!)
    val selfLink = linkTo(method).withSelfRel().toMono().awaitSingle()
    return EntityModel.of(this, selfLink)
  }
  @GetMapping("{id}")
  suspend fun getTodo(@PathVariable id: ObjectId) =
    repository.findById(id)?.withSelfLinkByBuilder()
      ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)

最佳答案

好吧,我找到了一个解决方案,我不知道它是否令人满意,但它确实有效。

通过简单地将函数调用链接在一起,运行时似乎按预期工作:

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)
  }

这确实很奇怪,但事实就是如此。

关于spring - 是否可以将 Spring HATEOAS WebFluxLinkBuilders 与 Kotlin 协程一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64865812/

相关文章:

android - 必须设置模块

android - 在 Kotlin 中使用 Gson 解析 JSON 数组

java - 如何在 Spring-Boot 微服务项目中实现 HATEOAS

java - 使用 Spring Java 验证多部分文件大小限制

java - 正则表达式选择数学公式中的最新表达式以更改符号

multithreading - 使用多线程加载 spring 上下文

spring-data-jpa - 如何将自定义方法添加到 Spring Data Rest JPA 实现并利用 HATEOAS 支持?

java.lang.NoSuchMethodError : org. apache.tomcat.util.res.StringManager.getManager with tomcat in Spring hetos

java - 两个 jar 之间的 Spring Boot 和 @ComponentScan

java - DynamoDB Spring Boot 数据剩余 "PersistentEntity must not be null!"