2

org.springframework.core.codec.CodecException: No SSE encoder configured and the data is not String

On Spring Initialize, I generated a project with just Spring Reactive Web. And here is the main class as I made it a REST controller.

package com.example.demospringwebflux;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

@RestController
@SpringBootApplication
public class DemoSpringWebfluxApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoSpringWebfluxApplication.class, args);
    }

    @GetMapping("/tuple")
    public Flux<Long> getTuple() {
        return Flux.fromArray(new Long[]{7L, 11L});
    }

}

Which works GREAT...

$ curl 0.0.0.0:8080/tuple
[7,11]

... Until I add a module-info.java as follows :

module com.example.demospringwebflux {
    exports com.example.demospringwebflux;

    opens com.example.demospringwebflux;

    requires spring.boot;
    requires spring.boot.autoconfigure;
    requires spring.context;
    requires spring.web;
    requires spring.webflux;

    requires reactor.core;
}

At which point cURL triggers a runtime exception

    org.springframework.core.codec.CodecException: No SSE encoder configured and the data is not String.
        at spring.web@5.3.9/org.springframework.http.codec.ServerSentEventHttpMessageWriter.encodeEvent(ServerSentEventHttpMessageWriter.java:171) ~[spring-web-5.3.9.jar:na]
        Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
    Error has been observed at the following site(s):
        |_ checkpoint ⇢ Handler com.example.demospringwebflux.DemoSpringWebfluxApplication#getTuple() [DispatcherHandler]
        |_ checkpoint ⇢ HTTP GET "/tuple" [ExceptionHandlingWebHandler]
    Stack trace:
            at spring.web@5.3.9/org.springframework.http.codec.ServerSentEventHttpMessageWriter.encodeEvent(ServerSentEventHttpMessageWriter.java:171) ~[spring-web-5.3.9.jar:na]
            at spring.web@5.3.9/org.springframework.http.codec.ServerSentEventHttpMessageWriter.lambda$encode$0(ServerSentEventHttpMessageWriter.java:159) ~[spring-web-5.3.9.jar:na]
            [--- truncated output all from reactor-core ---]
            at reactor.core@3.4.8/reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) ~[reactor-core-3.4.8.jar:na]
            at reactor.netty.http@1.0.9/reactor.netty.http.server.HttpServer$HttpServerHandle.onStateChange(HttpServer.java:915) ~[reactor-netty-http-1.0.9.jar:na]
            at reactor.netty.core@1.0.9/reactor.netty.ReactorNetty$CompositeConnectionObserver.onStateChange(ReactorNetty.java:654) ~[reactor-netty-core-1.0.9.jar:na]
            at reactor.netty.core@1.0.9/reactor.netty.transport.ServerTransport$ChildObserver.onStateChange(ServerTransport.java:478) ~[reactor-netty-core-1.0.9.jar:na]
            at reactor.netty.http@1.0.9/reactor.netty.http.server.HttpServerOperations.onInboundNext(HttpServerOperations.java:517) ~[reactor-netty-http-1.0.9.jar:na]
            at reactor.netty.core@1.0.9/reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:93) ~[reactor-netty-core-1.0.9.jar:na]
            at io.netty.transport@4.1.66.Final/io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.66.Final.jar:na]
            at io.netty.transport@4.1.66.Final/io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.66.Final.jar:na]
            at io.netty.transport@4.1.66.Final/io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.66.Final.jar:na]
            at reactor.netty.http@1.0.9/reactor.netty.http.server.HttpTrafficHandler.channelRead(HttpTrafficHandler.java:208) ~[reactor-netty-http-1.0.9.jar:na]
            at io.netty.transport@4.1.66.Final/io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.66.Final.jar:na]
            at io.netty.transport@4.1.66.Final/io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.66.Final.jar:na]
            at io.netty.transport@4.1.66.Final/io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.66.Final.jar:na]
            at io.netty.transport@4.1.66.Final/io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) ~[netty-transport-4.1.66.Final.jar:na]
            at io.netty.codec@4.1.66.Final/io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324) ~[netty-codec-4.1.66.Final.jar:na]
            at io.netty.codec@4.1.66.Final/io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296) ~[netty-codec-4.1.66.Final.jar:na]
            at io.netty.transport@4.1.66.Final/io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) ~[netty-transport-4.1.66.Final.jar:na]
            at io.netty.transport@4.1.66.Final/io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.66.Final.jar:na]
            at io.netty.transport@4.1.66.Final/io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.66.Final.jar:na]
            at io.netty.transport@4.1.66.Final/io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.66.Final.jar:na]
            at io.netty.transport@4.1.66.Final/io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.66.Final.jar:na]
            at io.netty.transport@4.1.66.Final/io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.66.Final.jar:na]
            at io.netty.transport@4.1.66.Final/io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.66.Final.jar:na]
            at io.netty.transport@4.1.66.Final/io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.66.Final.jar:na]
            at io.netty.transport.epoll@4.1.66.Final-linux-x86_64/io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:795) ~[netty-transport-native-epoll-4.1.66.Final-linux-x86_64.jar:na]
            at io.netty.transport.epoll@4.1.66.Final-linux-x86_64/io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:480) ~[netty-transport-native-epoll-4.1.66.Final-linux-x86_64.jar:na]
            at io.netty.transport.epoll@4.1.66.Final-linux-x86_64/io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:378) ~[netty-transport-native-epoll-4.1.66.Final-linux-x86_64.jar:na]
            at io.netty.common@4.1.66.Final/io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986) ~[netty-common-4.1.66.Final.jar:na]
            at io.netty.common@4.1.66.Final/io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.66.Final.jar:na]
            at io.netty.common@4.1.66.Final/io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.66.Final.jar:na]
            at java.base/java.lang.Thread.run(Thread.java:831) ~[na:na]

    2021-08-06 10:38:20.468 ERROR 2804492 --- [or-http-epoll-2] o.s.w.s.adapter.HttpWebHandlerAdapter    : [51436638-1] 500 Server Error for HTTP GET "/tuple"

    org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'application/json' not supported for bodyType=java.util.LinkedHashMap<?, ?>
        at spring.webflux@5.3.9/org.springframework.web.reactive.function.BodyInserters.unsupportedError(BodyInserters.java:391) ~[spring-webflux-5.3.9.jar:na]
        at spring.webflux@5.3.9/org.springframework.web.reactive.function.BodyInserters.lambda$writeWithMessageWriters$11(BodyInserters.java:381) ~[spring-webflux-5.3.9.jar:na]
        at java.base/java.util.Optional.orElseGet(Optional.java:364) ~[na:na]
        at spring.webflux@5.3.9/org.springframework.web.reactive.function.BodyInserters.writeWithMessageWriters(BodyInserters.java:381) ~[spring-webflux-5.3.9.jar:na]
        at spring.webflux@5.3.9/org.springframework.web.reactive.function.BodyInserters.lambda$fromValue$1(BodyInserters.java:98) ~[spring-webflux-5.3.9.jar:na]
        at spring.webflux@5.3.9/org.springframework.web.reactive.function.server.DefaultServerResponseBuilder$BodyInserterResponse.writeToInternal(DefaultServerResponseBuilder.java:409) ~[spring-webflux-5.3.9.jar:na]
        at spring.webflux@5.3.9/org.springframework.web.reactive.function.server.DefaultServerResponseBuilder$AbstractServerResponse.writeTo(DefaultServerResponseBuilder.java:351) ~[spring-webflux-5.3.9.jar:na]
        at spring.boot.autoconfigure@2.5.3/org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler.write(AbstractErrorWebExceptionHandler.java:375) ~[spring-boot-autoconfigure-2.5.3.jar:na]
        at spring.boot.autoconfigure@2.5.3/org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler.lambda$handle$2(AbstractErrorWebExceptionHandler.java:328) ~[spring-boot-autoconfigure-2.5.3.jar:na]
        [--- truncated output all from reactor-core ---]
        at reactor.core@3.4.8/reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) ~[reactor-core-3.4.8.jar:na]
        at reactor.netty.http@1.0.9/reactor.netty.http.server.HttpServer$HttpServerHandle.onStateChange(HttpServer.java:915) ~[reactor-netty-http-1.0.9.jar:na]
        at reactor.netty.core@1.0.9/reactor.netty.ReactorNetty$CompositeConnectionObserver.onStateChange(ReactorNetty.java:654) ~[reactor-netty-core-1.0.9.jar:na]
        at reactor.netty.core@1.0.9/reactor.netty.transport.ServerTransport$ChildObserver.onStateChange(ServerTransport.java:478) ~[reactor-netty-core-1.0.9.jar:na]
        at reactor.netty.http@1.0.9/reactor.netty.http.server.HttpServerOperations.onInboundNext(HttpServerOperations.java:517) ~[reactor-netty-http-1.0.9.jar:na]
        at reactor.netty.core@1.0.9/reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:93) ~[reactor-netty-core-1.0.9.jar:na]
        at io.netty.transport@4.1.66.Final/io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.66.Final.jar:na]
        at io.netty.transport@4.1.66.Final/io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.66.Final.jar:na]
        at io.netty.transport@4.1.66.Final/io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.66.Final.jar:na]
        at reactor.netty.http@1.0.9/reactor.netty.http.server.HttpTrafficHandler.channelRead(HttpTrafficHandler.java:208) ~[reactor-netty-http-1.0.9.jar:na]
        at io.netty.transport@4.1.66.Final/io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.66.Final.jar:na]
        at io.netty.transport@4.1.66.Final/io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.66.Final.jar:na]
        at io.netty.transport@4.1.66.Final/io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.66.Final.jar:na]
        at io.netty.transport@4.1.66.Final/io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) ~[netty-transport-4.1.66.Final.jar:na]
        at io.netty.codec@4.1.66.Final/io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324) ~[netty-codec-4.1.66.Final.jar:na]
        at io.netty.codec@4.1.66.Final/io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296) ~[netty-codec-4.1.66.Final.jar:na]
        at io.netty.transport@4.1.66.Final/io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) ~[netty-transport-4.1.66.Final.jar:na]
        at io.netty.transport@4.1.66.Final/io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.66.Final.jar:na]
        at io.netty.transport@4.1.66.Final/io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.66.Final.jar:na]
        at io.netty.transport@4.1.66.Final/io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.66.Final.jar:na]
        at io.netty.transport@4.1.66.Final/io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.66.Final.jar:na]
        at io.netty.transport@4.1.66.Final/io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.66.Final.jar:na]
        at io.netty.transport@4.1.66.Final/io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.66.Final.jar:na]
        at io.netty.transport@4.1.66.Final/io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.66.Final.jar:na]
        at io.netty.transport.epoll@4.1.66.Final-linux-x86_64/io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:795) ~[netty-transport-native-epoll-4.1.66.Final-linux-x86_64.jar:na]
        at io.netty.transport.epoll@4.1.66.Final-linux-x86_64/io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:480) ~[netty-transport-native-epoll-4.1.66.Final-linux-x86_64.jar:na]
        at io.netty.transport.epoll@4.1.66.Final-linux-x86_64/io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:378) ~[netty-transport-native-epoll-4.1.66.Final-linux-x86_64.jar:na]
        at io.netty.common@4.1.66.Final/io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986) ~[netty-common-4.1.66.Final.jar:na]
        at io.netty.common@4.1.66.Final/io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.66.Final.jar:na]
        at io.netty.common@4.1.66.Final/io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.66.Final.jar:na]
        at java.base/java.lang.Thread.run(Thread.java:831) ~[na:na]

I am yet to figure out why Java module would disable a bean. Or maybe this' a bug and I should report it on GitHub?

Zubair Saif
  • 1,106
  • 1
  • 14
  • 29
Salathiel Genese
  • 1,639
  • 2
  • 21
  • 37
  • 1
    Because not everything is on the module path and thus not found. I suspect you would need to add the netty module as well for the `NettyByteBufEncoder` be available and injected (not sure if that is the one actually being used in the first place). But somehow a module is missing and thus the correct `Encoder` cannot be determined. – M. Deinum Aug 06 '21 at 07:09
  • It did work with Netty, and appropriate `Encoder` (whatever that implementation was) as is, without the module-info.java file – Salathiel Genese Aug 06 '21 at 07:13
  • 2
    Yes it did, but when you add a `module-info.java` there is a module path and no classpath and only classes available in the modules defined in `module-info` are readable. So if the module isn't there, the class isn't there (the nature of modules). – M. Deinum Aug 06 '21 at 07:39

1 Answers1

1

@M. Deinum comment got me to try something different. And lo...

My app starts and works great with the following module-info.java

module com.example.demospringwebflux {
    exports com.example.demospringwebflux;

    opens com.example.demospringwebflux;

    requires spring.boot;
    requires spring.boot.autoconfigure;
    requires spring.web;

    requires com.fasterxml.jackson.core; // ADDITION LINE
    requires reactor.core;
}

(I removed other modules to make sure they aren't needed and it still works.)

Thank you, sir!

Salathiel Genese
  • 1,639
  • 2
  • 21
  • 37