Spring I/O

Spring for Rabbit Super Stream and SQL filters by Gregory Green @ Spring I/O 2026

48:07 · 13 Apr 2026 – 15 Apr 2026 · YouTube

About this talk

This talk covers the integration of Spring applications with RabbitMQ, focusing on messaging patterns and the new features of RabbitMQ streams and SQL filtering. The speaker, Gregory Green, explains the importance of using a messaging system like RabbitMQ to manage communication between publisher and consumer applications, highlighting its reliability and efficiency. He provides a deep dive into RabbitMQ streams, which allow for higher throughput and enable features like message replay through offsets and superstreams for scalability. The session includes a demonstration of how to implement these features in Spring applications, utilizing Spring Cloud Streams for abstraction. Additionally, SQL filtering capabilities introduced in RabbitMQ version 4.2 optimize message delivery by allowing consumers to receive only relevant messages without duplicating them. Green concludes by discussing the application of AI within this architecture, showcasing how real-time data processing can enhance application interactivity.

Full transcript

[music] >> session for on spring for RabbitMQ streams and SQL filters. Now, I'm going to get into what I mean by all of this stuff. What I want to start out with an introduction. My name is Gregory Green. It is an honor and a privilege to be with you today. When I found out my talk was accepted, I was so humbled and I'm I'm just so excited.

At my position as a solution architect at on the Tanzu division of VMware, which is part of Broadcom, I have the privilege of advocating for all of our data products and RabbitMQ is one of our data products, but I also have a lots of experience with spring. So, I love telling the story of how our data products can help with spring applications and that's pretty much our

agenda for today. I like to start out by when I'm talking about a technology, explaining what problem or what challenge is it trying to solve. And Rabbit is all about application messaging. So, if you have an application, suppose you have a publisher application and a consumer application and a consumer and a publisher needs to send some information to the consumer like, "Hey, the RabbitMQ session has started."

And what if the consumer application is um not available? Maybe it's distracted, maybe it's looking at its phone and it missed the message, right? Or it's just not running. Well, the end what if the publisher needs to send some important information like God forbid an emergency happens like a fire or something breaks out. So, it needs to send that emergency message to run. Now, if the publisher

app was not available, the the publisher can be nice and it can try to resend those messages and to retry. Now, and there are some frameworks in spring that make retrying easier, but you can't just keep retrying forever because you're an application. And what you have other information that you need to share and maybe there's a spike in messages, right? That needs to be sent. Maybe hundreds

of thousands or millions of messages that needs to be sent and this publisher application or this consumer application is not running. And what if you have another instance of the consumer application that comes later and it needs to get those messages? Especially the emergency message that it needs to run, right? So, instead of I always advocate instead of putting all of these application messages and concerns into

your applications, you should delegate it to a messaging system like RabbitMQ. And I'm going to get into RabbitMQ streams, but I want to start with Rabbit. So, Rabbit as I mentioned, it's a messaging system. I know we're not supposed to have favorites, but it is my favorite I also call it a message broker. It's been providing reliable delivery for a long time, right? Since 2007. Now, with

Rabbit, you have these traditional data types or this traditional topology, right? So, when you publish messages, you publish to an exchange, right? In other systems, you might call it a topic, right? And then the ultimately those messages are routed to a queue. And there'll be some routing rules on which messages are routed to which queues. Now, queues are sort of like the inbox for the applications. So,

when you send that message to a queue, it's first in first out. And when the consumer consumes that messages and it says, "Hey, Rabbit, thank you for the message. I've successfully processed it." Those messages are removed or it's destroyed. Now, but streams is a little bit different, right? Now, it's a newer technology, but it's not new, right? It was available in since RabbitMQ version 3.9. At at

the time of today's talk, the current version of Rabbit is 4.2, right? So, again, it's been about 5 years or so now. With a stream, when you publish a message, it's an append-only log, right? So, it's always publishing to the end and that's how it maintains the first in first out ordering, right? But, it supports higher throughput and when the consumer consumes those messages from the stream,

it's not a destructive consumption. So, the consumer can always reread those messages. So, in that case, you could kind of use Rabbit as another source of truth or as a data store. So, again, if you have on the same broker or the same messaging system, you can now add to your exchanges and your queues by introducing a stream. Now, for spring applications, it's super easy to get

started into incorporate streams into your apps. Just head over to start.spring.io and add these particular projects. In particular, the project spring for RabbitMQ streams, that's going to bring in the lower level APIs to work with Rabbit streams. But, by show of hands, how many of you are already using Rabbit for your spring applications? Okay, great. It looks like a lot of you are, there is a project

spring for Rabbit and that includes it's also known as spring AMQP. AMQP is it's a protocol. It's called the Advanced Message Queuing Protocol. It's the default protocol for RabbitMQ. And there's different versions of of that protocol. There's the 1.0.9 and there's also the 1.0 spec of that. So, spring for RabbitMQ, it basically provides some higher level abstractions so you don't need to use the lower level APIs,

but there's two other projects that I really love and it kind of hides the fact that you're even using a message broker. Like for example, spring cloud functions. How many of you are familiar with spring cloud functions? Okay, not a couple of you are. So, with spring cloud functions, you're basically just implementing a Java interface, right? So, it's a function interface. So, you at the end of

the day, all you are concerned about is receiving a message or returning receiving an object and returning an object or doing any combination of receiving and returning, right? And the fact that you're actually talking to a messaging system is totally abstracted to you. So, basically, when you have this function, then you'll have a binding, which is included in this spring cloud streams project, right? So, the spring

cloud streams will take your functions or your interfaces and it will allow you to talk to a messaging system like RabbitMQ. So, it's all super easy. I'm going to show you in a demo. But, how do streams help your spring applications, right? So, I'm going to start with replay, right? So, again, when that consumer application was distracted, it didn't get the message, right? Rabbit keeps track of

all of the messages that a particular consumer has processed, right? So, at the end of the day, there's something called an offset. Offset is just a number. You could think of it as an index to an array where the array is basically the stream, right? So, each consumer will have a name and will register its name with Rabbit. So, Rabbit will say, "Hey, for this stream, maybe

that particular consumer didn't process any messages, so it starts at zero." But, if it there were two messages in the stream and the consumer processed those two messages, then again, when that consumer starts up again, Rabbit will say, "Hey, I don't have any new messages for you." But, the good thing with replay, you can always as an application, you could tell Rabbit which offset you want to

start from. So, if you want to start from the first record or a specific offset, you can absolutely do that. Now, I'm going to show you how you would do that in some code. So, I have RabbitMQ running on my machine. I'm going to go ahead and log in. So, when you log, most of you who know have used Rabbit, default password guest guest. So, I have

one broker running on my laptop. You see everything's green, so it's all healthy. I have these default exchanges, right? So, these are just out of the box uh exchanges that you can use in your applications. But, if I click on uh queues and streams, I don't have any queues and I don't have any streams. So, I'm going to start out by uh starting my consumer application. So,

I have uh these two applications inside of my repository. I uh downloaded them from start.spring.io and I'm going to If I look at my consumer app, again, it I'm using Gradle. I got Again, if you're using Maven, you can absolutely uh use that. But, this was all created for me from and here it included the Spring for RabbitMQ project and also the Spring AMQP uh project and

some other uh projects that I'm the or dependencies that I'm using in this application. Um and also it was it generated this consumer app, so you know already know this is going to bootstrap Spring for me. So, if I wanted to put it my consumer logic, I'm going to go ahead into create a uh consumer. I'm going to have a config object and I'm going to add

some annotations and I'll bring in some Lombok. And all of my logic in this case, I'm going to put it into this consumer. So, again, this consumer is just part of Java util functions consumer interface, right? If I look at the implementation of this, again, this is just plain old Java where it has an accept method. And this accept message method is basically the message or the

payload. So, if I wanted to receive binary, then I can say I my input to my accept method is an array of bytes or if I wanted a string or I can use whatever object that I need, my domain object. So, in this case, I have this uh domain object which is a Java record. And it has these fields like the event, the session and the year,

right? So, at the end of the day, what's going to happen is when there is a message on the stream, Rabbit is going to push that message to my Spring application and the Spring project is going to convert this to this payload uh for me, right? Uh now Now, you notice that I don't have any reference to Rabbit inside of my um import statements, right? So, because

this is basically this This is what Spring Cloud functions does for me. I don't need to put in the lower-level references. But, I need to tell it something. So, uh I'll put all of the configuration details actually in my application properties. So, in this case, I'm specifying my application name um and the um port uh of zero, so it's going to generate a port for me. And

then here, again, this is Spring Cloud functions and I'm specifying the bean name that I'm exposing as a function. If I look go back here, if I kind of look at these uh side by side and I'll bring this a little bit um um over to the side. So, this is my bean and this is my bean name. And this matches that function definition. So, again, it's

just looking for that bean and it's going to expose it and it's going to create some bindings. So, the binding is basically says for that bean, I'll have an alias which is called input. Let me make this uh bigger. Close this. I have this alias called input and I have For this alias input, I have two things. I have a group and I have a destination. The

combination of the group and the destination, that's going to create a stream within RabbitMQ. So, let me go ahead and I'll start this application. I've got to start this instance of it in debug mode. So, when I start it up, this is going to establish a connection to RabbitMQ. Let me make this bigger. And if I go ahead and if I look at the management console, so

now we have one stream that was created. And I don't have any messages in the stream, so let's go ahead and let's populate some uh messages. So, I'll jump over to um close out all of this and I'll jump over to my consumer um app I mean my put my producer application, I should say. So, just like before, I have my Gradle and I have my dependencies.

I have Spring for RabbitMQ. I have the uh Spring Cloud Streams uh dependencies, Spring AMQP. And I have my um app. My publisher app that's going to So, I'm going to put my publisher logic in just like before into a configuration And I'll add in a configuration. I'll add in some Lombok again. Now, the first thing I'm going to do is I'm going to add in um

a um a Rabbit Streams template. Now, this is part of Spring AMQP. So, again, this is going to hide the low-level details to send uh data to Rabbit, but it's actually going to use uh streams, the streams protocol. Make this bigger. Um and Rabbit, when you send messages uh to Rabbit, the the the actual message is basically just a black box, right? It's just binary, right? So,

I can define how I want to serialize those particular messages. In this case, I'm using JSON. And I'm going to also include my application runner. So, my application runner, when it starts up, it's going to use the template. It's going to send this message uh welcome to the uh Rabbit uh the RabbitMQ session. So, when we go ahead and start this publisher application, All right. So, that

sent a message and if I go back to my consumer, now we see we've consumed that message. Now, if you look, the uh session in the year is not populated, right? So, let's go ahead and I'll I'll go ahead and I'll populate the session in the year. So, we'll say the session is uh rabbit >> [snorts] >> and the year is this year. And instead of uh

welcome to the welcome message, let's go ahead and let's send I'll send this uh emergency message. So, I'll say um emergency. Run. Fire. And then I'll be nice, please. >> Okay. So, when I restart this, and let's jump over to the consumer application. All right. So, I got these two two messages. If I go back to Rabbit, um I'll see that I have um the messages populated

into the stream. So, good. Everything's good. Uh but now, let's suppose what if I start up a new instance of the consumer app, right? So, if I start up a new instance of the consumer app, so I have this instance is running. I'm starting up a new instance. What happens? I don't have any messages, right? Because, again, Rabbit tracked for this instance of the app which is

using the same name, you've already processed the messages. So, I don't have any new messages for you. But, what I could do is like I like I like I said earlier, I can always specify the offset. So, I'm going to go back to Bigger. And I'll I'll specify an offset. So, in this case, uh ultimately, I'm specifying this offset specification, right? And I'm saying start from the

first or start from the beginning. If I look at the definition of the specification, there's different offsets that you can set. You can say uh uh no offset or the first or the last or the next or I can specify a number. Or I can specify a particular point in time, so you can allow you to time travel. So, a lot of flexibility here. So, again, since

I specified it, I'm starting at the first or the beginning, when I restart this particular instance of the application, let's see what happens. All right. So, uh I got my two my two apps, right? So, I was able to replay those messages from the stream, right? And any instance of my app now that I start up, it's just going to basically use the offset, right? So, when

I start this instance of the app, again, I'm replaying those two Makes sense. So, let's uh move forward in the uh talk. now Now, you could with In addition to replaying, streams also helps your ass by providing higher throughput. Now, what do I mean by high throughput? Um for years, if you had maybe hundreds of thousands of messages per second, maybe a million or millions of messages

per second, uh typically, in the past, you wouldn't, um, um consider using RabbitMQ. You might use one of the competing technologies. But, the Rabbit product team, which I am a huge fan of, they did an outstanding job of, uh, developing not only this new data type, but also the protocol that's used to send it, and it's extremely optimized. So, now, you get really high throughput. So, I'm

going to show you what I mean by high throughput. Um, I actually want to hop over to another instance, uh, of an application. And, I'm going to walk through some code. First of, I'm going to uh, start this, uh, I'm going to start this And, then I'll walk through the code. Um, so, ultimately, what this is trying to do is this is trying to create 17 million,

uh, messages, right? and just like before, I'm using the, uh, template. And, is I'm customizing the template. So, there's something called a batch size, right? So, by default, when I send a message to a stream, uh, a Rabbit, the Rabbit client is going to use a default batch size, which is 100. So, it's going to send 100 messages at a time. So, I'm basically improving or increasing

that number. But, it also there's something called sub-batching, right? So, you can think about it not only sending an array, but an array of an array. And, when you have sub-batches, that's when you can also compress the messages, right? So, again, I'm just tuning these to send them as fast as possible. I'm I'm sending this message, uh, in this, uh, message, uh, the the payload is basically

this. This payload. And, um, I'm have this application runner, and this application runner is trying to calculate how fast I'm actually sending those, uh, messages. So, if I look at the the output, this basically sent over a million and a half messages per second. So, let's see if all of the messages actually got into, uh, RabbitMQ. So, again, I got all of the 17 million messages, right?

They were published at a million and a half messages per second. I don't know if that impresses you, but that's pretty fast, right? And, this is just my local laptop, right? So, again, if you had a more powerful machine, again, you can get more and more, uh, throughput from this, right? So, but also, now, building on the doing the fact that on my single laptop, I can

get over a million messages per second, right? Rabbit also supports, uh, a way for you to scale out streams. And, it uses something called superstreams, right? So, superstreams is basically a logical collection of streams. Uh, when you create a superstream, you specify a couple of things. You specify a partitioning count, or how many application instances you have. And, also, it's going to use something called a, um,

a partitioning strategy. So, that messages that have something called a routing key. You can think of a a routing key as some sort of like like primary key for the messages. So, every message that has the same primary key is basically going to be routed to the same stream. So, in this case, I have a stream of two partitions. Which are superstreams with two partitions, and this,

um, this equates to two streams. And, when I send a message, every [snorts] message with the same routing key is routed to the same stream. And, so, when I have my two instances of my application, each one of those applications will basically own one of those streams. Again, so, in the streams, they're keeping the order. So, that's how you maintain the first in first out, um, for

the message processing. Let me show you what all of that means by an example. So, I have I head back over to my application. I'll stop this, uh, publisher application, and I'll head back over to the, uh, uh, of my project. All right. So, I I'm already in my my consumer. Uh, the only thing I'm going to basically change with my, uh, I'm just going to delete

this, uh, All right. So, now, in order because of the beautiful abstraction layers of, in particular, Spring Cloud Streams, I basically do not need to make any coding changes in order to start using, uh, a superstream. Basically, what I need to do is put in, uh, my properties. So, in my properties, I'll go ahead and maximize this. So, again, just like before, I'm specifying my bean, specifying

an alias for the bindings, and I have, uh, the group is the same, but the destination is changed. And, I'm not just telling Rabbit I'm I'm using a stream, I'm also saying I'm using a superstream, and I have two instances of my app. So, when I restart this, uh, application, this instance of the application, and I'll restart the other instance of the application, too. So, go ahead

and restart them. So, this is going to, again, take those, uh, the the properties from the application, uh, application.properties. If I head over to Rabbit, this created the stream, right? So, again, I said I had two, uh, instances of my app. It created two streams. If I look at Now, remember, the the superstreams is a is a combination I didn't mention this. It's a combination of an

exchange and the streams. So, I I do also have an exchange, and the exchange is basically this is sort of the internal internal details of how it's going to route for the same routing, uh, key to a particular stream. So, if I go back, I don't have to the streams for these two two streams, I don't have any messages. So, let's go ahead and let's populate some,

uh, So, I'll go to my publisher config, and I'll get rid of this code. And, I have a lot of template for, uh, publishing to the superstream. All right. So, in this case, I have a CSV file. Uh, the CSV file is located So, the first value in the CSV file is the event details, the next one's the session, and the next one is the year. So,

I have a couple of entries for Rabbit, Postgres, and some other entries, right? Uh, so, I'm saying, "Okay, read from the CSV file, uh, iterate over each one of the lines." For each one of the lines, I'm basically providing a supplier. So, this is going back to Spring Cloud Functions. So, again, the supplier interface, it just has a get method, right? So, again, whatever I want to

return, Spring is going to send that uh, publish that to RabbitMQ for me. So, in this case, I'm, um, parsing the lines, and I'm populating the value in the CSV file into the Spring IO event object, and just returning, uh, that. Now, if I look at the import statements, if I clean up my imports, um, after I clean up my imports, there's no real reference there's no

reference. Let me make this bigger. Uh, there's no reference to Rabbit in here, right? So, again, just like the consumer application, I'll put the Rabbit details in my application, uh, properties. So, I'll go to the consumer, I mean, the publisher properties. So, uh, here are the details here. So, just like before, I'm specifying the name of my function, which matches my bean name. I have an alias

for my bindings. Now, the group and the destination, they have to match, right? So, if I move this over to the side, and if I go back to the, uh, application uh, for the consumer, again, so, this destination will match this [snorts] destination, right? So, I'm publishing to the same, uh, to where the consumer is listening. So, now that I have all of this, I can I

can basically now send those messages. And, I'll start my publisher. So, it's going to read through and by default, um, the Spring Framework is going to call the get method of my, uh, publisher based on a schedule. So, the default schedule is it's sending it's calling the get method every second, right? So, every second it's going to be sending those messages to the stream. So, if I

look at this instance of the again, this instance of the application, looks like everything In this case, what I didn't explain is that one important detail about this particular application properties is it's also specifying the prefix. The um how many partitions we have. And this is what I'm using for the routing key. Right? So, the session is basically used as the routing key. So, every message that

has the same session is That is why every message that has the word rabbit is sent to this instance of the application. But, let's look at the other instance of the application. Looks like this one has everything that has Postgres um and GemFire. Right? So, again, that's how you maintain the ordering and you can scale by um partitioning these messages over different um different streams. So, that's

pretty much uh the how you use super streams. let's talk about filtering. So, with filtering now, suppose you have all of these messages in your uh streams. Maybe you have millions of messages. Maybe they are um broken over or they um um partitioned or charted across different streams. Now, but applications, they're interested in specific messages, right? So, but suppose I have one instance of my application and

maybe it's sending it to a user, right? So, in this case, this user is not really a person. It's a bunny. Uh this bunny name is Zen. Zen is a honorary member of the RabbitMQ team. Uh the owner of Zen is uh one of the engineers of Rabbit named Diana. She uh gave me permission. She gave me this picture. Now, Zen, when I send a message to

Zen Zen is not interested in GemFire and Postgres and all this other stuff. It's only interested in rabbit, right? So, I'm I should only send uh uh messages that have the the related to the rabbit session to Zen. But, my another one of my colleagues at Tanzu, Arul, Arul may be interested in in um information or events about Postgres or Data Flow. And Cora, who is part

of this Spring uh team, uh she might be interested in GemFire and uh Spring Modeler. And Vlad, Vlad is actually sitting in the audience right here. He's another one of my awesome colleagues. He's also in Spain, so you should connect with him after the uh session. Uh um Vlad is advanced and he might be interested in advanced topics like uh Valky or Kafka, right? So, again, how

do I get these um these these applications or these users just the messages that they need? And the answer to that is RabbitMQ streams, right? So, RabbitMQ streams, I'm sorry, RabbitMQ uh SQL filtering was introduced in Rabbit version 4.2. Right? And what it allows you to do is you can specify when you register your you can specify a SQL filter, right? So, every message that that matches

a particular SQL filter is going to be sent to your application. And this is a broker-side filtering. So, for example, other technologies, when you specify maybe a SQL operation, it will create multiple copies of the messages that match your particular uh criteria. In in the case of Rabbit, Rabbit is basically uh doing all of the filtering server-side for you. So, it's optimized in terms of the storage.

It's not creating multiple copies of the messages. It is also uh optimized in terms of the network because it's only sending you the messages that you're interested in, right? So, let me show you this in in an example. So, in this case, I'm going to have I'm going to I can uh do a SQL filter against a individual stream or multiple streams, right? So, again, I'm going

to do this This is an example of the SQL filter. It's basically the where clause of a SQL uh of a SQL statement. So, let's let's look at the code. All right. So, I'll hop over to I'll start out with my publisher application. And pretty much I mean, my consumer application. So, pretty much my code is going to remain the same. But, what I'll do is I'm

going to change I'm just trying to find my uh my alias. There you go. So, in this case, I'm creating a new destination. This is going to create a new streams for for me. Uh I'm still using a super stream and I still have my instance count of two. So, I'll go ahead and we'll start this restart this application and we have these uh new application properties.

Again, this is I just wanted to do this so I have a fresh stream, an empty stream so I can start showing you the SQL how to use the SQL filter. So, if I go back to the the uh the dashboard to RabbitMQ, again, I see I have these these new streams and everything's empty for these particular uh streams. So, I'm going to publish some messages to

that stream. Um and in this case I'm going to keep everything the same. I'm going still reading from the CSV file. I'm still iterating to it to it. But, the in order to implement the filtering, I need to add metadata about the applications. So, in order to add the uh metadata uh what I need is I'm going to wrap this in a message. So, this is a

Spring message. Right? The Spring message is going to allow me to add additional headers. So, the header that I'm adding is the session in the year. So, everything I add as a header is a candidate to be used in the where clause of my SQL filter. So, again, I'm using the session uh in the in the year. But, I also need to make sure that I change

my application properties so that I'm pointing for the uh publisher that I'm sending to the right uh stream. now I'm using the stream that has the word filtering in it. So, when I go ahead and uh restart this So, just like before, it is uh reading messages from the stream. Now, this one is a little faster uh because I I set the poll rate so they're sent

uh basically every 20 uh 20 milliseconds. So, if I look at my applications, again, this instance of the application, this one got uh messages about Postgres and And just like before, this one got uh messages um about um uh rabbit so on and so forth, right? So, again, they were partitioned. But, now I want to introduce my SQL filter, right? So, in introduce my SQL I'm going

to go back to my consumer And I'm going to change uh this code. So, in this case, I'm not going to use the interface. I'm going to start using the lower level uh details. All right. So, I have my live template. So, in this case, I have these various SQL statements, right? So, this is um again, this is what Zen, the bunny, is interested in, right? With

information related to uh rabbit in this year. If I go back to the um to the RabbitMQ console, you'll see that again, I have these various messages that have partition been partitioned based on the sessions. I'm going to query against both of those streams, right? So, for for this stream and for this stream I have something called an environment object, right? So, the environment object is almost

like a connection pool. So, and and in that environment object, I have a connection. And I'm setting up this consumer. I'll have two consumers over these two And I'll pass in the SQL filter. And then, when I get a message that matches that SQL filter, this is what I'm doing to it. I'm basically just uh logging it out to the uh to the um to the screen.

What I also want to do is I want to get rid of the application properties because again, I'm using the low-level APIs in this case and I don't want spring to get confused. And let's go ahead and restart this app. And I'm I'm actually going to stop when you have one instance of this app, so I'm going to stop stop one of the apps. And we'll restart

this one. So remember, the stream has our data about rabbit, has Postgres, it has lots of other messages in here. But again, this particular app, it only gets the the messages that match my SQL filter, right? So you see got ones about rabbit. This is all about rabbit. If I wanted to change to maybe get data about the other or get the messages for the other conditions,

I'll just use one for example. It's just as easy as changing this my SQL filter, restarting my app. And again, just now just as easy as I can query data in a table, now I can query these these messages in a stream, right? And this is a real-time query, meaning that if I have new messages, so let's actually I'll just publish some new So I have this

other I have another And this other CSV file basically just has some more events. So I'm just going to restart this. So it's sending more and more events. And those are those new events are basically picked up in real-time from my SQL filter. So again, you can you can look use use it as sort of like a database also as a real-time querying engine all using streams.

All right, great. Let's go back to the slides. So I always feel like no talk is complete without some mentioning artificial intelligence and our AI in some way, shape, or form. So I had to do it, right? So in this case, what I'm going to do is I'm using spring AI. How many of you are familiar and have played around with spring AI? So if you're not

familiar with it, haven't played around with it, it's basically an abstraction layer to be able to talk to a model, right? So I have I'm not going into details about it, but I have a model running on on my machine. I have something called Olama, which provides an interface for my spring application to ask my model a question. And the model is going to ask my my

app is going to ask the model a question based on the data related to the rabbit session, what does it think about this talk, right? So it's giving me a survey. It's going to think was it good, was it bad, or was it okay? And it's going to try to match all of the records that are in this in in the stream and again return the results.

So let's look at the code. So I'll go back to my consumer I'll get rid of this code and I have a And I'll walk through the code in this Again, just like before, we're querying Well, first of all, I have a prompt. So this is what I'm going to ask the model, right? Basically, what is its opinion about today's talk, but it's going to use the

data from the streams. It's going to match records in this the I have my environment object. I have my connections. I have my consumers. Now this is new. So this is a chat model. So this is spring AI. This is going to allow me to interact with a model Um and when I get data, this is it's going to call this handler. And I'm going to call

this subscriber. And what is the subscriber doing? The is basically adding these events into a list. And once it gets and I'll start while continue to work through it. And once it gets eight messages in the list, it's going to ask it's going to ask the model what does it think about this talk? And it's going to into this record. So this record is a survey object.

It has an opinion. It has a rating of whether it was good, bad, or okay. Let's look at the output. So this is the verdict. So this model think thought that this talk was neutral engagement and they thought it was okay. So I don't know if you agree with the model, but that's pretty much all I had to cover today. So I pray I hope that if

you are able to connect with me, the best way to connect with me is on LinkedIn and also check out my website where I'm publishing these examples and lots of other information about rabbit. But we do have time for some questions. So if you have any questions, I'm here. Yes, sir. Um oh, yes. So my question is in general, when you're using the streams, does the producer

need to be aware of the fact that that they're sending something to a stream or is it just really like an exchange and rabbit manages the the routing? Yes. So great question. Um you do not have to. So remember, I started out with by using the rabbit streams template. So in the name of the template, that's directly to a stream. But later on, I showed you the

The supplier was talking to a stream, but again, the spring framework is had hiding the fact that it was actually talking to a stream. So you can get abstract as you want and that's really the beauty of a stream. But there's sometimes you need to get more lower level, right? Especially maybe some advanced features of streams that may not be supported in in spring, so you can,

but you don't need to. >> Yeah, so so just checking, but that means that existing producers that may already live in connected to a rabbit cluster could be made to also publish to a stream. Yes, and that is an excellent point because what I didn't mention is streams is just a type. The the in application today, whether they're using the legacy protocols like AMQP, any version of

AMQP, there's also MQTT, there's only these different protocols that rabbit supports. For all of these protocols, you can send data to a stream and you'll get an improvement in performance, but you'll also get the replay capabilities. So yes, you can take those existing apps with minor changes and just start using streams. Great question. Thank you for the Any other questions? All right, if there's no other questions,

again, thank you, thank you, thank you for your time and have a great rest of your day. >> [applause]

From event

Spring I/O

13 Apr 2026 – 15 Apr 2026

All event videos
Back to Watch