Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error while serializing ServerSentEvent [SPR-14748] #19314

Closed
spring-projects-issues opened this issue Sep 26, 2016 · 3 comments
Closed

Error while serializing ServerSentEvent [SPR-14748] #19314

spring-projects-issues opened this issue Sep 26, 2016 · 3 comments
Assignees
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

@spring-projects-issues spring-projects-issues commented Sep 26, 2016

Jose Antonio Iñigo opened SPR-14748 and commented

After upgrading from Spring 5.0.0 M1 to M2 the following code has stopped working (I changed from SseEvent to ServerSentEvent class):

@RestController
public class StringsRestController {

    @GetMapping("/strings/sse/event")
    public Flux<ServerSentEvent<String>> sse() {
        return Flux.interval(Duration.ofMillis(100)).map(l -> {
            ServerSentEvent<String> event = ServerSentEvent.builder("foo").build();
            return event;
        }).take(2);
    }
}

I have uploaded a sample project at this URL (branch spring5-m2): https://github.com/codependent/spring5-playground/tree/spring-5-m2

To reproduce:

  1. Start the application with com.codependent.spring5.playground.Spring5PlaygroundApplication

  2. Call http://localhost:8080/strings/serversentsevent (com.codependent.spring5.playground.reactive.web.StringsRestController.sse())

This is the exception:

2016-09-26 08:50:10.966 DEBUG 10488 --- [nio-8080-exec-1] o.s.web.reactive.DispatcherHandler       : Processing GET request for [http://localhost:8080/strings/serversentsevent]
2016-09-26 08:50:10.997 DEBUG 10488 --- [nio-8080-exec-1] s.w.r.r.m.a.RequestMappingHandlerMapping : Looking up handler method for path /strings/serversentsevent
2016-09-26 08:50:11.002 DEBUG 10488 --- [nio-8080-exec-1] s.w.r.r.m.a.RequestMappingHandlerMapping : Returning handler method [public reactor.core.publisher.Flux<org.springframework.http.codec.ServerSentEvent<java.lang.String>> com.codependent.spring5.playground.reactive.web.StringsRestController.sse()]
2016-09-26 08:50:11.002 DEBUG 10488 --- [nio-8080-exec-1] o.s.b.f.s.DefaultListableBeanFactory     : Returning cached instance of singleton bean 'stringsRestController'
2016-09-26 08:50:11.407 DEBUG 10488 --- [        timer-1] o.s.w.s.h.ExceptionHandlingWebHandler    : Could not complete request

org.springframework.core.codec.CodecException: Error while writing the data; nested exception is com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class org.springframework.http.codec.ServerSentEvent and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)
	at org.springframework.http.codec.json.Jackson2JsonEncoder.encodeValue(Jackson2JsonEncoder.java:134) ~[spring-web-5.0.0.M2.jar:5.0.0.M2]
	at org.springframework.http.codec.json.Jackson2JsonEncoder.lambda$encode$2(Jackson2JsonEncoder.java:100) ~[spring-web-5.0.0.M2.jar:5.0.0.M2]
	at org.springframework.http.codec.json.Jackson2JsonEncoder$$Lambda$75.0000000013BE51F0.apply(Unknown Source) ~[na:na]
	at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:339) [reactor-core-3.0.2.RELEASE.jar:na]
	at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onNext(FluxConcatMap.java:232) [reactor-core-3.0.2.RELEASE.jar:na]
	at reactor.core.publisher.FluxTake$TakeSubscriber.onNext(FluxTake.java:136) [reactor-core-3.0.2.RELEASE.jar:na]
	at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:122) [reactor-core-3.0.2.RELEASE.jar:na]
	at reactor.core.publisher.FluxInterval$IntervalRunnable.run(FluxInterval.java:93) [reactor-core-3.0.2.RELEASE.jar:na]
	at reactor.core.scheduler.SingleTimedScheduler$TimedPeriodicScheduledRunnable.run(SingleTimedScheduler.java:383) [reactor-core-3.0.2.RELEASE.jar:na]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:522) [na:1.8.0-internal]
	at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:319) [na:1.8.0-internal]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:191) [na:1.8.0-internal]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305) [na:1.8.0-internal]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1153) [na:1.8.0-internal]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [na:1.8.0-internal]
	at java.lang.Thread.run(Thread.java:785) [na:1.8.0-internal]
Caused by: com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class org.springframework.http.codec.ServerSentEvent and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)
	at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:275) ~[jackson-databind-2.8.3.jar:2.8.3]
	at com.fasterxml.jackson.databind.SerializerProvider.mappingException(SerializerProvider.java:1110) ~[jackson-databind-2.8.3.jar:2.8.3]
	at com.fasterxml.jackson.databind.SerializerProvider.reportMappingProblem(SerializerProvider.java:1135) ~[jackson-databind-2.8.3.jar:2.8.3]
	at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:69) ~[jackson-databind-2.8.3.jar:2.8.3]
	at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:32) ~[jackson-databind-2.8.3.jar:2.8.3]
	at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:292) ~[jackson-databind-2.8.3.jar:2.8.3]
	at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1419) ~[jackson-databind-2.8.3.jar:2.8.3]
	at com.fasterxml.jackson.databind.ObjectWriter._configAndWriteValue(ObjectWriter.java:1147) ~[jackson-databind-2.8.3.jar:2.8.3]
	at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:977) ~[jackson-databind-2.8.3.jar:2.8.3]
	at org.springframework.http.codec.json.Jackson2JsonEncoder.encodeValue(Jackson2JsonEncoder.java:131) ~[spring-web-5.0.0.M2.jar:5.0.0.M2]
	... 15 common frames omitted

2016-09-26 08:50:11.407 DEBUG 10488 --- [        timer-1] o.s.h.s.r.ServletServerHttpResponse      : Can't set the status 500 because the HTTP response has already been committed
2016-09-26 08:50:11.407 DEBUG 10488 --- [        timer-1] o.s.h.s.r.ServletHttpHandlerAdapter      : Successfully completed request

Affects: 5.0 M2

Reference URL: http://stackoverflow.com/questions/39655499/spring-5-m2-reactive-error-while-serializing-serversentevent

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Sep 27, 2016

Sébastien Deleuze commented

The behaviour change you observed while upgrading from Spring Framework 5.0.0.M1 to M2 is due to the fact that SseEvent was a POJO while ServerSentEvent must be created via a builder and thus is not serializable by the regular Jackson writer. Please notice that in both cases, the issue occurs when you don't specify the text/event-stream media type but when requesting directly the SSE endpoint without any Accept header or with the */* one.

This fix treat ServerSentEvent as text/event-stream even if not specified and will be available in M3.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Sep 27, 2016

Sébastien Deleuze commented

I reopen this issue since the original fix introduced a regression (sadly not detected by our integration tests, I will add some tests to check this), because the SSE writer is now used by default even for those which not return a ServerSentEvent.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Sep 27, 2016

Sébastien Deleuze commented

Fixed by restoring writer registration order and refining Jackson codecs canEncode() and canDecode() methods.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants