spring-projects / spring-integration

Spring Integration provides an extension of the Spring programming model to support the well-known Enterprise Integration Patterns (EIP)
http://projects.spring.io/spring-integration/
Apache License 2.0
1.54k stars 1.1k forks source link

Application shuts down immediately after connecting to a websocket #9455

Open daniel-oelert opened 1 week ago

daniel-oelert commented 1 week ago

I wrote a simple Spring Integration app that connects to a websocket, using spring-integration-websocket.

Expected Behavior

The app connects to the websocket and keeps listening for new messages.

Current Behavior

Once connected the application shuts down immediately, since there is no non-daemon thread running, as pointed out by @artembilan on stackoverflow (https://stackoverflow.com/questions/78961574/why-does-my-spring-integration-app-just-shutdown-without-listening/) and the canonical way to keep this from happening is to use the property spring.main.keep-alive=true.

Context

It seems like a strange convention to keep this as the default. I think it would make sense to make the default the inverse of the current behavior.

A working example:

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.integration.channel.PublishSubscribeChannel;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.handler.LoggingHandler;
import org.springframework.integration.websocket.ClientWebSocketContainer;
import org.springframework.integration.websocket.inbound.WebSocketInboundChannelAdapter;
import org.springframework.messaging.MessageChannel;
import org.springframework.web.socket.client.standard.StandardWebSocketClient;

@SpringBootApplication
@EnableIntegration
public class BinanceListenerApplication {

    @Bean
    MessageChannel rawAggTradeChannel(){
        return new PublishSubscribeChannel();
    }

    @Bean
    IntegrationFlow logging(){
        return IntegrationFlow.from(rawAggTradeChannel()).handle(new LoggingHandler(LoggingHandler.Level.INFO)).get();
    }

    @Bean
    IntegrationFlow binanceWebsocketAggTradeStream() {
        var clientWebSocketContainer = new ClientWebSocketContainer(new StandardWebSocketClient(),
                "wss://stream.binance.com:9443/ws/avaxusdt@aggTrade");
        var websocketInboundChannelAdapter = new WebSocketInboundChannelAdapter(clientWebSocketContainer);
        return IntegrationFlow
                .from(websocketInboundChannelAdapter)
                .channel(rawAggTradeChannel())
                .get();
    }

    public static void main(String[] args) {

        SpringApplication application = new SpringApplication(BinanceListenerApplication.class);
        application.setWebApplicationType(WebApplicationType.NONE);
        application.run(args);
    }

}
artembilan commented 11 hours ago

Hi @daniel-oelert !

Would you mind confirming that you still use Java 17? Or that is only a problem starting with Java 21 and enabled virtual threads for your Spring Boot application? Thanks