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.
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