Tutorials

Tutorial: Reactive Spring Boot Part 10 – Spring Profiles to Switch Clients

In this lesson we use Spring Profiles to enable an application to determine which of our two clients (server-sent events via WebClient, or RSocket) to use to connect to our Kotlin Spring Boot price service.

This is the final part of our tutorial showing how to build a Reactive application using Spring Boot, Kotlin, Java and JavaFX.  The original inspiration was a 70 minute live demo.

This blog post contains a video showing the process step-by-step and a textual walk-through (adapted from the transcript of the video) for those who prefer a written format.

This tutorial is a series of steps during which we will build a full Spring Boot application featuring a Kotlin back end, a Java client and a JavaFX user interface.

Now we have an RSocket client that lets us connect to our RSocket server, we want to use this from our JavaFX application.

Creating the RSocketStockClient Bean

We intentionally have two implementations of our StockClient, one for connecting via RSocket and one via WebClient.  Our ClientConfiguration only exposes one of these, the WebClientStockClient, as a bean. If we want applications to be able to use the Rsocket client we need to add an RSocket client bean as well.

  1. Create a new @Bean method on ClientConfiguration in the stock-client module, called rSocketStockClient, which returns a StockClient.
  2. The body of this method needs to return a new RSocketStockClient, which will need to take an rSocketRequester as a constructor argument.
  3. Add an RSocketRequester as a method parameter to this rSocketStockClient method.
  4. (Tip: we can get IntelliJ IDEA to add the correct method parameter if we pass an unknown variable rSocketRequester into the RSocketStockClient constructor, press Alt+Enter on the unknown variable and select “Create parameter”.)
  5. (Tip: IntelliJ IDEA Ultimate will warn you that this parameter can’t be autowired because no beans match this type.)
  6. Create another @Bean method called rSocketRequester that returns an RSocketRequester.
  7. Declare an RSocketRequester.Builder parameter builder for the method. This should be wired in automatically by Spring.
  8. Use the builder’s connectTcp method and give it “localhost” and port 7000 (that’s where our Spring Boot RSocket server is running). Call block() to complete this connection.
@Configuration
public class ClientConfiguration {
    // WebClientStockClient bean method...

    @Bean
    public StockClient rSocketStockClient(RSocketRequester rSocketRequester) {
        return new RSocketStockClient(rSocketRequester);
    }

    @Bean
    public RSocketRequester rSocketRequester(RSocketRequester.Builder builder) {
        return builder.connectTcp("localhost", 7000).block();
    }

    // WebClient bean method...
}

Choosing which bean to use

If we go to our JavaFX ChartController (in the stock-ui module), this is the class that uses the StockClient to connect to the price service and display prices on the chart.  IntelliJ IDEA Ultimate shows a warning in this class that there’s more than one Bean that matches the StockClient type, our RSocket stock client and our WebClient stock client.  We need to figure out a way to specify which client we really want to use.  One way to do this is with Spring profiles.

  1. Add a @Profile annotation to the webClientStockClient method, passing in a value of sse (Server-Sent Events).
  2. Give the RSocketStockClient a @Profile of “rsocket”.
@Bean
@Profile("sse")
public StockClient webClientStockClient(WebClient webClient) {
    return new WebClientStockClient(webClient);
}

@Bean
@Profile("rsocket")
public StockClient rSocketStockClient(RSocketRequester rSocketRequester) {
    return new RSocketStockClient(rSocketRequester);
}

Selecting the active profile

If we’re using IntelliJ IDEA Ultimate, when we go to the ChartController we can see the error has gone away now.  But we still need to say which profile we want to use.

  1. Go to application.properties in the stock-ui module.
  2. Set the spring.profiles.active property to sse. This should give us the same bean and the same functionality that we had before.
# web-application and application title properties here...
spring.profiles.active=sse
  1. Re-run the application, the application should start up as expected and the chart should show two sets of prices as before.
  2. Note in the run window that the JavaFX application has started up with the sse profile.

Logging for debugging

If we want to be extra sure that we’re using the bean we think we’re using, we could go back to the clients and add some logging.

  1. In the pricesFor method of WebClientStockClient add an info-level log message to state that this is the WebClient stock client.
public Flux<StockPrice> pricesFor(String symbol) {
    log.info("WebClient stock client");
    return // create Flux here...
}
  1. Do something similar for the RSocketStockClient.
public Flux<StockPrice> pricesFor(String symbol) {
    log.info("RSocket stock client");
    return // create Flux here...
}
  1. Re-run the application, we should see two log messages that we’re using the WebClient stock client.

Getting prices via RSocket

Let’s finally use RSocket to get prices to display on our JavaFX line chart.

  1. Go back to the application.properties file in stock-ui and change the active profile to rsocket.
  2. Re-run the application, everything should still works the way we expect. This time we’re using the rsocket profile and connecting to the RSocket price server via the RSocketStockClient.
# web-application and application title properties here...
spring.profiles.active=rsocket

So there we have it.  A full end-to-end application with a JavaFX line chart that subscribes to a reactive stream of prices from a Kotlin Spring Boot application, and can be configured to get those prices either via server sent events or via the new RSocket protocol. Discover more about IntelliJ IDEA’s features for Spring here.

Full code is available on GitHub:

To learn more about the features for working with Spring in IntelliJ IDEA, visit this web page.

image description