This codelab will help you get started with Spring Cloud Stream. We'll quickly cover some basic fundamentals before jumping in to actually creating some Spring Cloud Stream microservices to see the framework in action.

You'll learn:

Valuable Resources:

πŸ›  This page covers the setup needed to perform this codelab. πŸ› 

Spring Cloud Stream Requirements

βœ… Spring Cloud Stream just requires Java and Maven to use πŸš€

Create your Messaging Service

βœ… (1) Sign up for a free Solace Cloud account

Navigate to this link and fill out the required information. No credit card required! If you already have an account, skip right to #2.

βœ… (2) Create a messaging service

After you create your Solace Cloud account and sign in to the Solace Cloud Console, you'll be routed to the Solace Cloud Landing page.

Solace Cloud Event Mesh Page

Click on β€˜Messaging Services' and all the messaging services associated with your account will show up if you have any already created. To create a new service, click either button as depicted in the image below:

Solace Cloud Landing Page

Fill out all the details for your messaging service, and then click "Create" at the bottom of the page. Note: make sure you choose the "Developer" option for the Service Type

Create Solace Cloud Messaging Service

Your service should be ready to use in a few minutes

βœ… (3) Take note of the connection details

If your messaging service was created successfully, you'll be routed to the summary page of your new messaging service. From the service summary page, click on the "Connect" tab so we can take note of the connection details we'll need later.

Connect Tab Preview

After you click the "Connect" tab, click the "Solace Messaging" box, and then take note of the "Connection Details" section. We'll be using the "Secured SMF Host" URL.

Solace Web Messaging Tab

πŸš€ Setup complete! Let's get going! πŸš€

Cloud Stream Basics

Spring Cloud Stream is a framework for creating highly scalable, event-driven microservices connected by pluggable messaging services. Messaging services are pluggable via Binders that we'll cover in a bit. The framework is based on Spring Boot and Spring Integration.

Spring Cloud Stream has three different types of message exchange contracts as pictures below.

  1. Suppliers are sources of events
  2. Sinks are consumers of events
  3. Processors are both consumers and subscribers of events

Cloud Stream Intro

Message Exchange Contracts Map to Java Functions

As of Spring Cloud Stream v3 the preferred programming model is to use Java Functions to implement your cloud stream apps.

We just mentioned the 3 types of Cloud Stream message exchange contract are "Sources", "Sinks" and "Processors".
Those map to functions as follows:

Binders

Spring Cloud Stream Binders are really what make the framework useful. Binders provide an abstraction layer between your code and the messaging systems over which events are flowing. This allows you to write your code without having to worry about learning messaging APIs! When messages are sent or received from the messaging system they pass through the messaging system specific binder which knows how to communicate with that specific message broker.

As of the creation of this codelab the available Cloud Stream Binders are:

Today we're going to use the Solace PubSub+ Binder which supports publish subscribe and consumer groups.

Communication Models

Instead of having to learn Messaging APIs, developers just have to understand the communication models that Spring Cloud Stream supports. There are 3 supported models, but support varies per binder.

  1. Publish-subscribe: subscribers are independent from each other & receive events in order
  2. Consumer groups: fan-out and load-balancing across multiple consumers
  3. Stateful partitioning support: in-order processing for consistency and performance

πŸš€ So what are we waiting for!? Let's get started πŸš€

Use Spring Initializr to Generate your Project

πŸš€ First we're going to use Spring Initializr to generate our Spring Boot project for us.

  1. Open the Spring Tool Suite IDE.
  2. Choose File -> New -> Spring Starter ProjectSpring Starter Project
  3. On the first screen give your project a name of "springone" and click Next
  4. On the second screen search for "solace" under Available and choose both "Solace PubSub+" and "Cloud Stream"
    Add Dependencies
  5. Click Finish

βœ… You should see a new project named "springone" in your IDE!

If you look at the pom.xml file you'll see a few important things:

Pom File

Add Messaging Service Connection Info

Open the application.properties file under src/main/resources and enter the properties below substituting the connection information with your messaging services' connect info we got from the Solace Cloud Connect tab in the previous section.

spring.cloud.stream.binders.solace.type=solace
spring.cloud.stream.binders.solace.environment.solace.java.host=tcp://localhost:55555
spring.cloud.stream.binders.solace.environment.solace.java.msgVpn=default
spring.cloud.stream.binders.solace.environment.solace.java.clientUsername=default
spring.cloud.stream.binders.solace.environment.solace.java.clientPassword=default
spring.cloud.stream.binders.solace.environment.solace.java.connectRetries=0
spring.cloud.stream.binders.solace.environment.solace.java.connectRetriesPerHost=0

Write the Java Function

Now to write some code!

Open the SpringoneApplication.java file. Unless you chose different settings when creating your project it should be under src/main/java/com/example/demo

When you open the project you'll see the basic skeleton of a Spring Boot app, including the @SpringBootApplication java annotation.

Let's go ahead and create a java.util.function.Function bean that takes in a String, changes is it to all uppercase and returns a String.
The code might look something like below:

@Bean
public Function<String, String> uppercase(){
   return v -> {
      System.out.println("Uppercasing: " + v);
      return v.toUpperCase();
   };
}

πŸš€ That's it! No Messaging code and we have an app that can retrieve a message, process it and publish a message!
πŸš€ Let's test it out.

Run your app by right clicking on your project, choosing "Run As" and "Spring Boot App" if using Spring Tool Suite. From the command line you can also run by entering mvn clean spring-boot:runRun App

βœ… In order to test your function open Solace Cloud, select the messaging service and navigate to the Try Me! tab

tryme

This page will allow you to send and receive messages to see if your function is working as expected.

To test your function perform the following steps:

  1. Click the Connect button for the "Subscriber"
  2. Type "uppercase-out-0" into the "Subscribe to a topic to receive direct messages" box and click Subscribe
  3. Click the Connect button for the "Publisher"
  4. Type "uppercase-in-0" as the topic to publish to.
  5. Type "Spring One is Awesome!" in the "Message Content" box and click Publish

πŸš€ You should see your application printed "Uppercasing: Spring One is Awesome!" in your IDE and the "Subscriber" in the "Try Me!" menu in Solace Cloud should show that a message was received that contained "SPRING ONE IS AWESOME!"

πŸŽ‰ Congratulations! You just created your first Spring Cloud Stream microservice!

Another powerful feature of Spring Cloud Stream is inherited from Spring Cloud Function, and that feature is the capability of doing Function Composition. This allows you to create simple functions as Spring Beans that can be individually tested, re-used and chained together to create a processing chain.

Instead of just talking about Function Composition let's try it out 😁.

In the same class where you already have your "uppercase" function let's create a "reverse" function that takes in a string and reverses the ordering. This function would like something like this:

@Bean
public Function<String, String> reverse(){
	return v -> {
		System.out.println("Reversing: " + v);
        return new StringBuilder(v).reverse().toString();
   };
}

Now that we have two functions Spring Cloud Stream won't just assume what bindings we want created so we need to go configure them in the application.properties file. Assuming we want to uppercase an incoming String and then reverse it we will add these properties to the file:

spring.cloud.function.definition=uppercase|reverse
spring.cloud.stream.function.bindings.uppercasereverse-in-0=input
spring.cloud.stream.function.bindings.uppercasereverse-out-0=output

βœ… We now have our function all wired up so go ahead and stop the app and restart it.

βœ… Navigate back to the "Try Me" menu in Solace Cloud (Refer to the steps in the "Test your Microservice" section if needed)

βœ… Add a subscription for "output" since that is what we called our output binding name. And publish a message to the "input" topic since that's what we called our input binding.

βœ… If you published "Hello world!" you should see that the subscriber received a message containing "!DLROW OLLEH" and your application printed the following to the terminal as it processed the message through the pipeline.

Uppercasing: Hello world!
Reversing: HELLO WORLD!

πŸ₯³ Woohoo we have now created a Spring Cloud Stream app that uses a pipeline of functions to process incoming messages!

βœ… Hopefully this codelab showed you how easy it can be to create event-driven microservices using Spring Cloud Stream. Note that you didn't have to learn any messaging APIs as the Cloud Stream Binder abstracts them from you!

βœ… Learn how to generate Cloud Stream apps using AsyncAPI here.

βœ… Learn how to publish to dynamic topics using Spring Cloud Stream by a sample here.

solly_wave

Thanks for participating in this codelab! Let us know what you thought in the Solace Community Forum! If you found any issues along the way we'd appreciate it if you'd raise them by clicking the Report a mistake button at the bottom left of this codelab.