Search code examples
springspring-integrationspring-websocket

Why does my Spring Integration app just shutdown without listening?


I am trying to implement a Spring Integration app that listens to websocket messages from an external source and logs them to stdout. However as soon as I start my application it shuts down again, if I don't force it to keep running with a Scanner that waits for the user to enter the letter "q". What is the canonical way to keep the app listening?

This is my code:

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.support.AbstractApplicationContext;
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) {

        AbstractApplicationContext context = new AnnotationConfigApplicationContext(BinanceListenerApplication.class);
        context.registerShutdownHook();

        // Scanner scanner = new Scanner(System.in);
        // System.out.print("Please enter q and press <enter> to exit the program: ");

        // while (true) {
        //  String input = scanner.nextLine();
        //  if ("q".equals(input.trim())) {
        //      break;
        //  }
        // }
        // scanner.close();
        // context.close();
        // System.exit(0);

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

}

I would expect the app to keep listening based on this code, as I thought that the WebSocketInboundChannelAdapter should be a message-driven adapter.


Solution

  • Since you are not interested in the servlet container (or any other HTTP server), it is normal that your application shouts down without any scheduling.

    See this property: spring.main.keep-alive=true.

    There is not too much docs on the matter, but here is something: https://docs.spring.io/spring-boot/reference/features/spring-application.html#features.spring-application.virtual-threads