-
Notifications
You must be signed in to change notification settings - Fork 41.2k
RSocket components fail to load when using Webflux and Spring lazy initialization. #17964
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
Comments
See also #16615 |
Thanks for opening this, @ccellist. Much appreciated. |
Happy to help @wilkinsona. |
Hello. In my case i need to create new connections in runtime to some new hosts over RSocket. My solution was to create bean of type @wilkinsona maybe, if applicable, we can use reactive bean? |
In this particular case the bean that cannot be lazy is defined in user configuration. Here's the definition from the sample (updated to align with removal of MIME type from @Bean
public RSocket rSocket() {
return RSocketFactory
.connect()
.mimeType(WellKnownMimeType.MESSAGE_RSOCKET_ROUTING.toString(), MimeTypeUtils.APPLICATION_JSON_VALUE)
.frameDecoder(PayloadDecoder.ZERO_COPY)
.transport(TcpClientTransport.create(7000))
.start()
.block();
} The problem can then be avoided by adding @Bean
@Lazy(false)
public RSocket rSocket() {
… It may still make sense to exclude any |
After chatting with @wilkinsona , we've decided not to change the current behavior. Since 2.2.0.M5 Spring Boot improve its RSocket support, so your application could be improved with a few changes. You could delete the @Component
public class YourService {
private final Mono<RSocketRequester> requesterMono;
public YourService(MyCustomProperties properties, RSocketRequester.Builder builder) {
this.requesterMono = builder
.dataMimeType(MediaType.APPLICATION_CBOR)
.connectTcp(properties.getHost(), properties.getPort()).retry(5).cache();
}
public Mono<User> findUser(String login) {
return this.requesterMono.flatMap(req ->
req.route("find.user.{login}", login)
.retrieveMono(User.class));
} This is creating the connection lazily and you can also add retry/error handling/etc as reactor operators. In general, creating an RSocket as a bean might not be a good solution since you can't really handle errors/retries or even properly close the connection as part of the application lifecycle. Right now you can write a wide variety of RSocket applications with Spring Boot without creating such beans:
I'm closing this issue for now; we might reopen this issue in the future if we see that best practices or Spring Boot support evolve in that matter. Thanks! |
Version: Spring Boot 2.2.0.M5
Module: spring-boot-starter-rsocket
When enabling lazy initialization for spring beans (
spring.main.lazy-initialization=true
) rSocket components fail to load with the following exception (stack trace abbreviated):This happens specifically when
spring-boot-starter-webflux
is also a dependency. What's happening is Spring attempts to load the rSocket components inside of a non-blocking thread when someone hits the app using a webflux-enabled controller. This triggersSchedulers.isInNonBlockingThread()
to return true which throws the exception. Opening this issue at the request of Andy Wilkinson (@wilkinsona) who indicated RSocket components need to be marked as never lazy.Sample project can be found at https://github.com/ccellist/quickchat-rsocket. Build and run both client and server apps, then try hitting the client with
curl -XPOST -H 'Accept: application/json' -H 'Content-Type: application/json' http://localhost:8081/chat -d 'Hello'
to trigger the exception.The text was updated successfully, but these errors were encountered: