Spring WebFlux在响应体中返回值时抛出“producer”类型未知的错误。

28

我正在使用Kotlin和Spring Boot,现在尝试通过传递一个响应式服务的处理程序来从GET restful服务获取状态值。

我能看到我正在传递的处理程序在请求中,但是无论何时我构建正文,都会出现以下异常:

java.lang.IllegalArgumentException: 'producer' type is unknown to ReactiveAdapterRegistry
    at org.springframework.util.Assert.notNull(Assert.java:198) ~[spring-core-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException

这是我的代码

@Bean
    fun getReceiptConversionStatus() = router {
        accept(MediaType.APPLICATION_JSON).nest {
            GET("/BsGetStatus/{handler}", ::handleGetStatusRequest)
        }
    }
    private fun handleGetStatusRequest(serverRequest: ServerRequest): Mono<ServerResponse> = ServerResponse
            .ok()
            .contentType(MediaType.APPLICATION_JSON)
            .body(GetStatusViewmodel(fromObject(serverRequest.pathVariable("handler"))), GetStatusViewmodel::class.java)
            .switchIfEmpty(ServerResponse.notFound().build())

这就是我的视图模型:

data class GetStatusViewmodel(
        @JsonProperty("handler") val documentHandler: String
)
4个回答

39

对我来说,我正在做类似这样的事情:

webClient.post()
    .uri("/some/endpoint")
    .body(postRequestObj, PostRequest.class) // erroneous line 
    .accept(MediaType.APPLICATION_JSON)
    .retrieve()
    .bodyToMono(PostResponse.class)
    .timeout(Duration.ofMillis(5000))

当查看该函数body()的springs文档时,解释如下:

Variant of body(Publisher, Class) that allows using any producer that can be resolved to Publisher via ReactiveAdapterRegistry.

Parameters:
     producer - the producer to write to the request
     elementClass - the type of elements produced

Returns:
    this builder

因此,第一个参数不能只是任何对象,它必须是生产者。将我的对象包装在Mono中,可以为我解决这个问题。

webClient.post()
    .uri("/some/endpoint")
    .body(Mono.just(postRequestObj), PostRequest.class)
    .accept(MediaType.APPLICATION_JSON)
    .retrieve()
    .bodyToMono(PostResponse.class)
    .timeout(Duration.ofMillis(5000))

参考文献:https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/reactive/function/client/WebClient.RequestBodySpec.html


7
根据您的示例,您也可以使用bodyValue而不是body来避免将对象包装为Mono。有关的行看起来会像这样:bodyValue(postRequestObj) - Valdèse Kamdem
1
@ValdèseKamdem,“bodyValue”函数对我有用。 - mazend

35
FluxMonoProducers,它们生成东西。你在请求体中没有传递一个producer,这就是为什么你会得到错误,它无法识别你传递的生产者,因为你传递了一个GetStatusViewmodel
你的请求体需要是Mono<GetStatusViewmodel>类型的。你可以用bodyValue替换body(它将自动为你包装),或者你可以在将其传递到body函数之前使用Mono#just将你的GetStatusViewodel包装在Mono中。

syncBody现已被弃用。 - jediz
7
只有在 Spring 生态系统中,这种错误才会是运行时错误而不是编译时错误! - Chad

4

我实际上已经解决了这个问题,并且我会在这里发布,以防有人犯同样的错误 :( 这是对于那些使用Java的人来说一个典型的错误,是错误的导入

我在我的应用程序中使用了fromObject()方法(“我更新了问题以匹配我的实际代码”)。您可以在这两个导入中找到此函数,并且我正在使用其中一个重载的body()函数来传递这个放错位置的函数:

//this is the wrong import I was using
import org.springframework.web.reactive.function.server.EntityResponse.fromObject
//this is the correct one for building the mono body
import org.springframework.web.reactive.function.BodyInserters.fromObject

通过使用BodyInserters方法,您可以将fromObject(T)传递给body方法,并且它将返回mono结果。

2
指定的代码解决了问题。
public Mono<ServerResponse> getName(ServerRequest request) {

    return ServerResponse.ok()
            .contentType(MediaType.APPLICATION_JSON)
            .bodyValue(birthday);

}

1
它也解决了我的问题。我原来使用的是.body,改为.bodyValue就解决了。 - Chaitan Yadav

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接