简体   繁体   English

Spring 解码时启动 Webflux 处理程序错误 XML 将正文内容请求到 Mono 或 Flux object

[英]Spring Boot Webflux Handler errors when decoding XML request body content to Mono or Flux object

I have been trying to implement Spring reactive routers and handler instead of MVC controllers.我一直在尝试实现 Spring 反应式路由器和处理程序而不是 MVC 控制器。 Seemed simple enough, but my WebTestClient test has been failing with 500 Internal Server Error.看起来很简单,但我的 WebTestClient 测试一直失败并出现 500 Internal Server Error。 Shorted code versoin of test.测试的短代码版本。

@ContextConfiguration(classes = {FooRouter.class, FooServiceConfig.class, FoonHandler.class})
@WebFluxTest
public class FooHandlerTest {

@Test
public void testFooPost()  {
    webTestClient.post()
            .uri("/foot")
            .contentType(MediaType.APPLICATION_XML)
            .accept(MediaType.APPLICATION_XML)
            .body(Mono.just(foo), Foo.class)
            .exchange()
            .expectStatus().isCreated()
            .expectBody(Bar.class)
            .isEqualTo(bar);
}

During the test the router works fine and calls the handler.在测试期间,路由器工作正常并调用处理程序。 When the handler tries to create the Mono from the request body:当处理程序尝试从请求主体创建 Mono 时:

Mono<Foo> fooMono = request.bodyToMono(Foo.class);

that line kills the unit test and the WebTestClient receives a 500 status code.该行终止单元测试并且 WebTestClient 收到 500 状态代码。 During debugging, although the mime-type is application/xml and it did map the Java class, the BodyExtractors is filtering the decoders and matches the class and mime type.在调试过程中,虽然 mime 类型是 application/xml 并且它做了 map Java class,但 BodyExtractor 正在过滤解码器并匹配 class 和 mime 类型。 For Json it is looking at the Java class and trying to get a mapping off of it before it compares the mime type.对于 Json,它正在查看 Java class 并在比较 MIME 类型之前尝试从中获取映射。 Deep within debug it crashes when it is still trying map the class to an object mapper.在调试的深处,当它仍在尝试 map class 到 object 映射器时,它崩溃了。

I am currently using Spring Boot version 2.3.4-RELEASE with Java8.我目前正在使用 Spring 引导版本 2.3.4-RELEASE 和 Java8。 Documentation mentions if you have JaxB in your classpath then for XML it should use Jaxb2XmlDecoder and Endoder for default codecs.文档提到如果您的类路径中有 JaxB,那么对于 XML,它应该使用 Jaxb2XmlDecoder 和 Endoder 作为默认编解码器。 It will also use Jackson if you have that on your classpath.如果您的类路径中有 Jackson,它也会使用它。 I do happen to have both minus the jackson-dataformat-xml dependency.我确实碰巧都减去了 jackson-dataformat-xml 依赖项。 I'm pretty sure it's either my test configuration or it can be WebFluxConfigurer, which I tried setting the default codec for the jaxb2Decoder and Encoder.我很确定它要么是我的测试配置,要么是 WebFluxConfigurer,我尝试为 jaxb2Decoder 和编码器设置默认编解码器。 I also did try adding the jackson-dataformat-xml dependency, but that did not work either.我也确实尝试添加 jackson-dataformat-xml 依赖项,但这也不起作用。 This is the webconfig I tried to use, but still crashing trying to decode mime-types of application/xml with the Json decoder.这是我尝试使用的 webconfig,但在尝试使用 Json 解码器解码 mime 类型的 application/xml 时仍然崩溃。 Here is the webconfig:这是网络配置:

@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {

    @Override
    public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
        configurer.registerDefaults(false);
        configurer.defaultCodecs().jaxb2Decoder(new Jaxb2XmlDecoder(MediaType.APPLICATION_XML));
        configurer.defaultCodecs().jaxb2Encoder(new Jaxb2XmlEncoder());
    }
}

I've been debugging and printed out the request objects message readers and the Jaxb2XmlEncoder is one of the codecs to the xml mime type.我一直在调试并打印出请求对象消息阅读器,而 Jaxb2XmlEncoder 是 xml mime 类型的编解码器之一。 Here is the print message for JSON and XML Decoders:这是 JSON 和 XML 解码器的打印消息:

Message Reader: org.springframework.http.codec.DecoderHttpMessageReader@5b2cea27
    DecoderHttpMessageReader Decoder: org.springframework.http.codec.json.Jackson2JsonDecoder@87b7472
        Mime Type: application/json
        Mime Type: application/*+json
Message Reader: org.springframework.http.codec.DecoderHttpMessageReader@198a86e1
    DecoderHttpMessageReader Decoder: org.springframework.http.codec.xml.Jaxb2XmlDecoder@50cb41d0
        Mime Type: application/xml
        Mime Type: text/xml
        Mime Type: application/*+xml

When in the readWithMessageReaders method in the BodyExtractors class there is a filter in the function that iterates through the message readers and decoders.当在 BodyExtractors class 的 readWithMessageReaders 方法中时,function 中有一个过滤器会遍历消息阅读器和解码器。 When it gets to the DecoderHttpMessageReader,Jackson2JsonDecoder it starts to try and decode the request.当它到达 DecoderHttpMessageReader,Jackson2JsonDecoder 时,它开始尝试解码请求。 Not sure why since the mime type in the debugger shows application/xml.不确定为什么,因为调试器中的 mime 类型显示 application/xml。

Does anyone have any suggestions on how to debug this piece of code:有没有人对如何调试这段代码有任何建议:

Mono<Foo> fooMono = request.bodyToMono(Foo.class);

This is where it dies during Unit testing with the code above.这是它在使用上面的代码进行单元测试期间死掉的地方。 I've tried debugging, but it will just stop the test when I get too deep.我试过调试,但当我太深入时它只会停止测试。 I just know it is going through the Java type when it is trying to match a codec.我只知道它在尝试匹配编解码器时正在通过 Java 类型。 Most codecs just return right away, but the Json and XML decoders are trying to get the Java class attributes and are choking.大多数编解码器立即返回,但 Json 和 XML 解码器正在尝试获取 Java class 属性并且令人窒息。 The class is a JaxB class with all proper annotations. class 是带有所有正确注释的 JaxB class。 The WebTestClient has no problem encoding the class to XML for the test. WebTestClient 将 class 编码为 XML 进行测试没有问题。 So why can't the handler just convert the body to mono?那么为什么处理程序不能将正文转换为 mono? Nothing is being thrown from that code statement.该代码语句没有抛出任何内容。

I knew it was something in my setup and unit testing was not showing the correct problem.我知道这是我的设置中的问题,单元测试没有显示正确的问题。

It was my return statement that was actually causing the error when getting the body content.在获取正文内容时,实际上是我的返回语句导致了错误。

Old return statement:旧的退货声明:

return created(URI.create(response.getDocument().getPath()))
    .bodyValue(Mono.just(response));

New return statement:新的退货声明:

return created(URI.create(response.getDocument().getPath()))
    .body(Mono.just(response), Response.class);

See the difference with bodyValue and just body?看到 bodyValue 和 just body 的区别了吗? That caused caused the request body not being able to convert to a Mono.这导致请求正文无法转换为 Mono。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Spring 5 WebFlux Mono和Flux - Spring 5 WebFlux Mono and Flux 在Flux / Mono中调用异步任务(Spring boot webflux) - Call async task in Flux/Mono (Spring boot webflux) Java Spring Boot Webflux - Mono response when there is no http body, but just http status - Java Spring Boot Webflux - Mono response when there is no http body, but just http status Spring WebFlux,单元测试 Mono 和 Flux - Spring WebFlux, unit testing Mono and Flux 使用打开的 api 代码生成器为 spring-webflux 生成 API 接口时,如何防止 Mono 请求正文生成? - How to prevent Mono Request body generation when generating the API interfaces for spring-webflux with open api code generator? Spring Webflux和@Cacheable - Mono / Flux类型的缓存结果的正确方法 - Spring Webflux and @Cacheable - proper way of caching result of Mono / Flux type 是否可以退回 spring webflux Flux<t> / Mono<t> 对于 Graphql 查询?</t></t> - Is it possible to return spring webflux Flux<T> / Mono<T> for Graphql Queries? 在 Spring 引导中使用 Mono 迭代 Flux 和 concat - Iterate Flux and concat with Mono in Spring Boot Spring Webflux(Mono/Flux) 与 AOP 触发 REST 调用在拦截和使用 Mono/Flux - Spring Webflux(Mono/Flux) with AOP triggering REST call at interception and working with Mono/Flux 如何从 Spring WebFlux 反应式中的 ServerRequest 对象获取请求正文? - How to get request body from ServerRequest object in Spring WebFlux reactive?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM