From Contracts to Confidence: Spring Cloud Contract 5 in the Age of AI by Marcin Grzejszczak
About this talk
This talk is presented by Marcin Grzejszczak, the creator of Spring Cloud Contract, who discusses the latest updates and features in Spring Cloud Contract 5.1 and its relationship with AI. He outlines the transitions from previous versions, including significant adjustments like the removal of deprecated features and a migration to WireMock 3, highlighting the need for contract testing in microservices architecture. The speaker delves into how AI can enhance the development process by generating contracts, automating test validations, and improving the overall testing experience. Grzejszczak also introduces Stubborn, a platform he created to streamline contract testing and facilitate better communication between services. He emphasizes the importance of contracts as tools to enforce standards and reliability in code delivery.
Full transcript
[music] >> Listen to somebody talking about contract testing, like testing in general. That's already something. So, I I really really would like to thank you. Um so, um who am I? Uh my name is Marcin Grzejszczak. I have a terrible name to pronounce, the last name. But other than that, I'm the creator of Spring Cloud Contract. I used to work at the Spring team for 10 years.
so, if you're using So, who's using Spring Cloud Contract? Anybody? One person, great. Who knows about Spring Cloud Contract at all? Okay, good. Some people. Um who's using Micrometer tracing? Oh, okay, so. That's if if stuff is working, that's because of me. If there are bugs, it's the observability team. Uh I'm a Java Champion. Uh I've done over 150 presentations, workshops. And I'm here thanks to Hero
Devs. I'm uh working there now. Uh so, if you have old, sad projects that are using unloved open source projects that are out of support, talk to us because most likely we've already patched them. No CVs, you can use them. Uh and I'm blogging at toomuchcoding.com. Okay. Spring Cloud Contract 5, um that was a housekeeping release. So, when I quit um the Spring team, um it's interesting
because finally I had some time to work on this project because like, you know, observability was the the the critical thing. And finally I could spend some time on the on my baby because I I I, you know, created from from scratch. Uh it's also not a very young project. It's like 12 years old now because it used to be called Accurest before that. In general, um
you know, with in Spring we have this approach that uh when we have breaking changes, we can always only do them or we should only do them in major releases. So, it turned out that hey, there's a five coming up, so it's time to break. Um I didn't provide any features really. It was a maintenance release. Uh there are certain decisions I had to take which I
postponed for years. First of all, WireMock 3. So, in the meantime, you know, everybody had WireMock 2. Who knows WireMock? Okay, everybody, almost everybody. So, WireMock is a um a project, a Java project, that allows you to stub an HTTP server. And we had WireMock 2. That was like end of life. Uh there was WireMock 3. There were breaking changes and we couldn't upgrade. So, finally the
decision was there. We can we can finally do it. So, if you're migrating, remember the group ID for WireMock has changed. Java imports stay the same, which is why it was a little bit frustrating because, you know, there's like literally nothing theoretically blocking us from migrating. But there was, right? I mean, because of uh dependencies. Now, I believe, like I have this um approach in life that
it's absolutely fantastic to push my problems to somebody else. Why should I take care of my problems if somebody else can take care of them? So, since it turned out that WireMock has created an official Spring Boot's interaction, why should we have our own in Spring Cloud Contract? So, what we did is we removed the official I mean, official the Spring Cloud Contract's WireMock integration. So, you
used to do auto configure WireMock and now who is using Claude or any other tool like that to code? Okay, good. So, now if you say, "Hey, Claude, could you please create the Spring WireMock integration?" Or like, "I have a Spring project. I would like to test it some stuff with WireMock." It does the before. It should do the after because it's trained on the old stuff.
So, remember, tell it, "No, stop. Use the official uh WireMock uh thing from uh the WireMock team." Ah, the shade plugin. That was that was a mess. So, there is a module called Spring Cloud Contract Shade, which would be doing terrible stuff because it's creating a shaded jar. Shaded, you know, like it has dependencies, all the dependencies are repackaged. Uh and those dependencies were mainly Groovy and
other stuff because I needed to avoid conflict. Why? Because Spring Cloud Contract is a project basing on Boot. Boot brings the dependencies. However, Maven brings the dependencies and Gradle And Spring Cloud Contract has a Maven So, that was kind of a mess and uh we we couldn't really upgrade for years. So, the the the difference in the dependency was rising. At certain point, there was even a
problem because, you know, the baseline uh was uh JDK 17. Some projects in the shaded jar still were using libraries that weren't compatible with JDK 17. But actually we were not using those pieces of code. It was a mess. So, the best way to fix the mess is to remove it, which I did. So, I removed it. It turned out that everything works. We have a lot
of tests. Um it simplified things a lot, cleared uh a lot of the dependency trees. Gradle and property cleanup. Um I am, to say the least, not a Gradle fan. however, we have the Gradle plugin. until fairly recently, what we had was a the same approach to the folder structure. So, if you had contracts, they would land up in source test resources contracts. But for Gradle, apparently,
the best way to go is to have a special source set. So, now the special source set is source contract test and the old one is removed. And something that bothered the Spring Boot team since forever because, like I said, previously the project was called differently. Um so, it was called Accurest. But it was a Boot project as well. the initial properties were called, for example, stub
runner and that's it. But in all the other projects in Spring, you had the full name, like Spring Cloud Contract, whatever. So, finally with Spring Cloud Contract 5, I decided to fix this like 8-year-old problem and we have to migrate. So, if you used stub runner, now you have to use Spring Cloud Contract stub runner. It's a breaking change. What else? Uh there was this uh big
um initiative to remove the inject and named um uh support throughout the portfolio. So, Spring Cloud Contract also had to have that removed. That was aligning with the Jakarta EE migration. This is funny. Um who's using REST Assured? Nobody. So, if you use Spring Cloud Contract, you use REST Assured. Uh in general, REST Assured is a library used to um test the HTTP API. Thing is that
Johan, who is the uh maintainer of REST Assured, like he did his best to not release majors every time stuff changed in Spring. Uh because that was also a problem. Plus, there is a um cyclic dependency uses the MockMvc API. But Spring in REST Docs, for example, also used REST Assured, right? So, we have cyclic dependency. So, the idea was um like how can we fix it?
So, what Johan uh with a little bit of my help was uh that he released uh a major version of But that happened after we released Spring Cloud Contract 5. So, theoretically, we should release Spring Cloud Contract 6 to support the new major of REST Assured, which is not going to happen. since already before this whole situation, REST Assured supported Spring 5 and Spring 6, I said,
"Why not support 7?" all through reflection. So, the only problem was that um for 7, the return types of some methods were incorrect. So, I just changed them to object and they started to be correct because the type is correct. So, like that that was crazy, but it works. This is why a I think a minor was released of of REST Assured 5 5 something and we
could remain on the baseline of Spring Cloud Contract 5. I mean, it is what it is. Sometimes you have to go to the extremes to allow the community to benefit um uh not having to to to upgrade. Now, so that's history. I'm going to now talk a little bit about what's coming in Spring Cloud Contract 5.1 and then I'm I'm going to switch to the most interesting
topic right now, the hottest one, which is AI. So, in Spring Cloud Contract 5.1, um recently I I I was interviewed by the Go to Conference and I mentioned that there is a class in which literally in the in the Java docs it says, or Groovy docs actually, "I would like to apologize to anyone anyone reading this class." It's there. I'm not joking. And that class is
called JSON to JSON Path Converter. It's a mess, but it's a mess for a reason cuz JSON as a structure can be literally a lot, a list, a map, a single value, a just an array, a list of lists, a list of maps, you you you you get the drill. Um so, there's a pull request in which I've managed to finally with some help of AI to
rewrite this from Groovy to Java and make it much much cleaner. with Spring Cloud Contract there is a uh an assumption that there is no strict request matching, meaning we're not checking if the order of an array is exactly like this. Like if the array matches in general by any part of it, uh it matches the requirement, that's fine. Uh which was a like problem for some
people from the very beginning and that was a valid concern. Um but the prerequisite was to fix the JSON to JSON Path Converter to even think about doing this. So, when I did the first one, I managed to uh do the second one as well. So, it will be an option to turn on the feature of generating the strict assertions. And we have a gigantic Spring Cloud
Contract samples uh repository. Uh I updated it for Boot 4 and Spring Cloud Contract 5. I need to do a lot of cleanup there because like there's I don't know, like 60 60 projects out there. So, for those who don't know really Spring Cloud Contract, let me explain how it works today. And uh in a second I will explain like why do we even need So, right
now we have a situation where we have a producer of the API or of a producer of a message. from that side eventually we will um create stubs. But first, in order to create those stubs, we need a contract, so a definition of of a scenario of usage. Uh if we have that, then uh we are able to generate tests that will verify if you as a
producer are telling the truth. Because like imagine that you have an API and you say, "Well, yeah, I have a endpoint foo and if you send a get request there, I'm going to respond with bar." And it turns out you don't have it. It's quite sad, right? So, we don't trust you, right? Sorry. Um so, we're going to generate a test and say, "Okay, let's check it
out. Let's send a request foo and let's see if you're going to respond If you do, we're going to from the contract we're going to also generate stubs, WireMock stubs that you can use on the consumer side. Um you can have contracts on the producer side in a separate repo. There are different ways to do it. Uh the stubs, you can push them to get, you can
push them to Maven. Also, there are different ways to solve this. So, now you can ask like, "What? Why do I even need it?" So, without the contracts, let's imagine the following situation. Who of you has two services talking to each other? Two? Just Okay. Who has three? So, you two, you don't have any services, right? You don't have services. They don't talk to each other, right?
Okay, fine. So, one service. Anyways, when two are talking to each other over HTTP who of you is integration testing that? Integration testing? Okay. Fine. is using WireMock or something else to simulate the producer of the API? Okay, fantastic. would say there's 100% certainty that the stub you've done acts like the production server? Nobody? Good. There's none. So, the thing is if service A talks to service
B and you're using WireMock on the service A side, so you have a you have a class that uses RestTemplate or whatever as client, makes a call and if from that class you make a test and say, "Oh, spin up WireMock. If I send a request to foo, respond with a I mean, you you invented that. You can write whatever you want. The stub will be there.
Your tests will pass. So, what's better is service A talks to service B. Service B defines the contracts or has tests out of which, after passing the test, stubs are created, but only after we tested service B. Now, the stubs are published and then on service A side you say, "Oh, I'm not going to stub it myself. I want to fetch the stubs. I want to fetch
them. And then you're sure that the stubs are >> [snorts] >> Right? So, [clears throat] Spring Cloud Contract works but what if we could make it even better? Currently, as I said, we're storing contracts in the Git repo. You can run stubs from Maven. But maybe there is a way or maybe we could think about making it even more interesting, better to see how it looks like
in a in a broader spectrum. let's say that we have different apps, order service, payment service, user service, whatever the services are out Wouldn't it be great to have a single dashboard? So, we would see every contract, every verification, every deployment, right? Anybody heard of Pact? Pact? Okay. Pact Broker? Rings a bell? That's a cool thing, right? We don't have it for Spring Cloud Contract. It would
be great. So, for those those who don't know, Pact is a even older uh library than Spring Cloud Contract. Uh it's a contract testing framework as More focused on the consumer contract side. So, like I don't want to go into the details, but it's a fantastic framework. So, let's say how about we wouldn't need to go to all those five repositories to check the contracts, but have
them in one place. Often is the case that you can't even do it because uh security concerns. For example, in the banks, some repositories are not even visible to others, right? What if we had a feature called can I deploy? So, let's say order service version 1.2.0 wants to deploy. Wouldn't it be nice to see if can I deploy this? Like have my consumers verified against me?
In Spring Cloud Contract you can do something like this. It's [clears throat] called um stubs per consumer feature, which means that when you have contracts, you can organize them in folders that resemble the consumers. So, instead of putting them under source test resources contracts, you would do source test resources contracts payment service, notification service, inventory service. And then you would have a subfolder for 1.2.0, 1.2.1, whatever,
right? All those versions. Okay, but somebody can break the convention, right? So, maybe it would be nice from the point of view of order service to be able to verify this with one command. Branch awareness. We're in main. We have contracts. We have different versions of those contracts, meaning, you know, it it evolved. let's face it. We are using feature branches. I try and to have them
very short-lived, but sometimes you do not. And sometimes even if you have them short-lived, you would like to, for example, check before you merge if you don't break people, Uh so, this branch awareness would be nice to have like out of the box. In Spring Cloud Contract you could do it by on the branch having a different artifact maybe, right? And then fetch it, but it's it's
not ideal. So, what if the verification knew about those branches, right? It would be Dependency visibility. Let's say we have you know, different apps talking to each other somehow. We have observability. You like most of you raised a hand with my micrometer tracing knowledge. But what if we didn't have to wait till the production deployment and real-time flows? What if we could have it at the build
time? the defining the contracts and [snorts] fetching the contracts of um the producers of the API or or um producers of messages? What if that told us that application A uses application B at build time? That would be crazy, right? before we go to production, knowing who's calling who. Polyglot support. The elephant in the room with Spring Cloud Contract. >> [clears throat] >> We do support it,
but not natively. So, recently, sorry, I've been working a lot with uh uh the front end side, even the back end side written in in uh JavaScript. indeed, I mean, you can do it. So, with Spring Cloud Contract we have been so far up to version 5 uh because of technical reasons, we've been um pushing the Docker images so that the polyglot support would be possible. So,
what what this do is if you run this docker image inside the docker image, tests would be generated for the attached contracts. You can see to the bottom contracts uh are uh mounted as a volume. What would happen is the tests would run against the application base URL, so you'd have to start the node app. The tests would be run. If the tests are passing, there would
be an artifact published and pushed to artifact. The same on the consumer side. You can run the docker image. It would fetch the stops. It works. You can do it. But it's not native to the language. So, better polyglot support would be Now, AI. Let's talk about the AI. What if I could use an AI agent that would be able to natively speak the contract language, right?
So, we're using AI to generate services. But it would be great if the while generating the services, the AI tool would know that if A calls B, B has a contract. Right? Right? Then automatically I could I mean, I meaning Claude or whatever else could be able to already incorporate that the um the contract tests, right? After, you know, having done that, they can they could theoretically
publish the verification result. Hey, hey, I'm I'm fine. I I can talk to you. So, at this point, there's nothing machine friendly for Spring Cloud Right? No MCP server, no API for agents. What if we couldn't stop wasting CI? This is really interesting. Like, let's a couple of versions of the um of our code. It happens. We we release stuff. What if we didn't change any contracts?
Why should we run the tests? API didn't change. Contract tests are not about going end-to-end. So, if you've done things properly, so you have a controller, you have a contract tests, controller they get delegate work to service, service should be stopped. If you're doing it like this, there's no point in running the tests again. They have to pass if the contract didn't change. Right? Because contract tests
are about semantics. They're not about the features, right? It means like can we talk, will we be able to talk in production? That's what contract tests are about. So, if we have same content, why verify again? So, we could skip it. um we can use tools to generate the services in in in in minutes. The question is who verifies the specifications, who verifies the contracts, right? When
I'm teaching [clears throat] about testing, I've been doing that for for more than a decade now. especially now in the in the in the age of AI, nothing was more important than tests. I mean, always nothing was more important than tests, but now it's even more important. Um >> I think that, you know, generating code with AI, it's a little bit like you have a river, right?
The river's flowing. I mean, you can go inside the river and say like, you shall not pass. You can have a stick and try, you know, stopping it. I don't think it's going to work. But you can try to control the you know, where there goes left, right. So, that's the same thing with AI. AI is like a flood of non-deterministic stuff, but you can have guardrails.
Contract tests being one of them. And I have a course, by the way. Uh I a QR code to that course, generate break fix distributed systems in the AI area about this. So, with without the contracts, we already mentioned what the problem would be, right? If you don't have contracts, you can have tests that pass and production doesn't work. Now, with AI, if we have the contracts,
AI can create proper specifications of the communication even. Right? Because it knows the scenarios of It doesn't mean that all the Like let's say you do not replicate the business logic in the contracts. You should not But you can have specifications about how the communication should look like. And that can be taught from the contracts. Now, uh Tom Ackerst is an amazing fellow. So, he's the person
behind WireMock. He's the founder creator of WireMock. He had a fantastic fantastic presentation called Scaling API Independence at QCon. Uh this is the link to his um presentation. And what he said there is that he has this idea. He thought about like, how can WireMock better work with AI? So, he had this In production, you don't talk directly from A to B. You go for a proxy.
And now, that proxy is the WireMock proxy that captures the traffic. Of course, PII, we have to get rid of this data. [snorts] And it will create stops from production traffic. Which means I don't have to do it myself anymore. It's taken from production. Right? So, let's talk about that idea in terms of Spring Cloud Contract. And in general, Spring Cloud Contract and AI. Because we could
theoretically do the same. Now, um Contract as AI coding context. What if we had an AI agent? We're writing a new consumer. And now, AI agent can go to the MCP server and say, "What are the contracts for the order service? Because I'm going to consume that service, right?" you get back a proper contract. For example, right? So, that way contracts contracts become the AI's pair programming
partner because they describe And that's verifiable, right? So, the agent reads the contracts, generates the client basing on the uh and the verification against the provider can happen through MCP tools. We can do it. Another case, you have brownfield. You billions of spring controllers. So, you can say, "Oh, don't no problem. Just write tests." I mean, you know how it is. Like, who here I mean, we're
friends here. Everybody's, you know, about tests. Who always starts with the test? Okay, let me repeat. Who always starts with the test? Nobody? Okay. Uh neither do I. But we do write tests. But there are places, very dark places, where there are no tests. >> So, let's try to fix it. What about an AI agent reads the code, the spring controllers, reads the annotations, and from that
tries to generate a examples of usage and in a loop. Try it. Try it. Try it. Okay, now I have it. Try again. I have it. And that way, automatically you could create the So, we inverse the spec-based development. That's perfect for Another thing we could do is tweak it. For the controllers, ask AI to generate Mockito tests, from which, using Restdocs, you can generate stops. Spring
Cloud Contract allows you to do it. So, that way you would have tests. From the tests, you would have stops. And also, from you could generate It's possible. Okay. What about we had a such a situation? Use Claude or whatever else and you say, "Uh I need to do some serious work, uh some serious coding. How about I just talk to Claude and say, 'Hey, just create
a contract, you know, post this to you to orders. There's going to be product ID quantity. Get back 200 blah blah blah. Bye.' And then boom, you get the the contract with proper MCP approach, like the tools. That's absolutely feasible. So, for non-Java teams or anybody, really, you lower the barrier like completely. Um I know product owners and and you know, business uh people, business analysts that
talk JSON, right? They they literally Okay, that's interesting. Definitely, they're wearing contract tests here. Okay, what about contract drift? This is also also very interesting. Let's say that exactly in this part that you can't see, uh let's say that um we have some production traffic and we capture it all the time. So, there would be some sort of a proxy somewhere, right? And we do an analysis
of what we capture in prod versus what we have in the contracts. And then we say, "Oh, you know what? I see problem. Because in the contracts, we say there's for this case, there's 200. But I found that 15% are to 422. What do we do about this?" It can be done as well, right? So, contracts this because contracts always describe intent. But traffic is showing the
reality, right? So, we can have some intent and then verify it against the reality. So, AI I can be our pair programming partner saying, you know, there's a new field here that we didn't take into account. The status code, okay, most of the time is what you say, but there is an ongoing problem. Um so, we can see those patterns because before they become production incidents. Another
thing, somebody comes in the morning says, oh, it's a great day to delete something, that person hasn't listened to any of us for the last 20 years saying, don't touch the API if you don't have to. Somebody says, ah, this legacy ID field, I need to remove it. Okay. the agent said, you know what, it's a fantastic idea, but don't do it because there are free consumers
that use it in these versions, etc. This is exactly why we have spring we have contract tests. This is exactly the point. You can already have it right now without AI because if you do stop per consumer feature and you remove a field from the API and you run the contract tests, they're going to break and tell you, ah, the the field is missing. But what I
could do it before, like I'm going to describe the intent. I want to remove it and it's going to say, don't do it. the the one that Tom mentioned, can we do it? So, we have HTTP traffic, we have some sort of a Now, we have AI. So, let's say the proxy batches the request. Then AI takes the Of course, we have to remove the PII, the
so personal identification information. Uh we take those and from those we the contract. And now, somebody can say, yes, but AI can make mistakes. Fair enough. So, what's the solution for that? A But to do a loop, how can we say that the contract that the AI has generated is wrong? We can have an open API validator. So, let us assume A talks to B. Each of
the services describe their open API schema on an endpoint. /open API, for example. So, now AI generates the contract and using the spring spring contract open API validator, it can check if the generated contract is valid against the schema. If not, repeat and loop until it's done. Right? So, the schema is the source of truth, but schema does not provide uh testable scenarios in the in the
in the way that spring contract does. So, we can do both. So, if it's invalid, go back to AI and say, you know, these fields are wrong and it will loop loop loop until it's matching the spec. So, the full What is the full picture with contracts and AI the way I see it? So, AI can read the contracts. MCP server can help us. It can feed
the contracts as a context. Agents can generate proper client code. They do not have to guess anything. AI can write the contracts. It can read from the traffic also, right? It can capture the requests. AI validates the contracts in a in a way that is repeatable, deterministic. And AI can monitor the contract. So, impact analysis and drift detection. So, there's a lot we can do with AI.
So, in essence, contracts are the interface between humans and AI agents. So, what if all of these could be available in one place? So, central dashboard, connected play safety, branch awareness, dependency graph, polyglot SDK, content hash data, governance layer, and AI And now, ladies and gentlemen, you're I ordered that exactly at this point at that hour to witness something which is called Stubborn. Do you get it?
Thank you. >> I am so bad at bad jokes. So, what I did is I created Stubborn. As you version 010 is there. And maybe not every, but most of the the improvements at for sure every improvement in terms of the of the topic is there um in one product. You can go check out demo.stubborn.sh. It's there. Don't break it. Uh so, you have this completely invisible
for you central dashboard. So, you go in, you see the dashboard. By the way, it's not a sales pitch. I just want to show you that uh you can already benefit from some things. Plus, there's a like a I'm going to later describe why a separate org is required because of technical reasons. A dependency graph, I love it. So, it shows like impact the who is calling
who, who is failing, the the purple one and the blue one is showing messaging. So, it's saying that order service talks to the notification for service through order events. This is awesome. Can I deploy safety? So, you can say, hey, API gateway in version one at staging, can I deploy? No, because you didn't verify against payment service, notification service, and inventory AI proxy is there. So, you
can start the proxy. You have to provide some open AI key, for example. you have to send a request so that we know where to target it next, right? Um to the because you're going to talk through the proxy. So, an app will talk to the proxy and then the app has to say where the traffic has to go. Traffic is captured. We're batching the requests, converting
to SCC YAML. And Stubborn open AI open API, that's a project open source project, will do the validation against open API specs because spring contract for years now had a community project that allowed you define contracts within open API spec in the example section. So, I took it over to the org so that, you know, it's in And I've added a feature there to do the validation
of the against the open API And now, contracts can be pushed to because Stubborn allows to push the in various ways. Now, this is also nice. So, we had a proxy for messaging. That's for HTTP. What about messaging? What if we have For the for now, Kafka. I didn't have more time to do Rabbit. It's It's in in It's in in the plans. Let's say we have
Kafka a Kafka existing cluster. What we have What do we have a passive listener on consumer group not competing for messages, not acknowledging them, just just picking. It's looking at them and generating messaging contracts from the actual traffic in production. And they you can store them in in Stubborn. This verified piece will happen, but I didn't yet have time to properly do it because we would need
to have some sort of a schema for the messages. And there are ways to do it, right? Uh Avro, Protobuf, it can be done, right? Contract API guardrail. So, we have Stubborn open open AI API. Um you don't need to use the broker at all. It's It's there. So, what you can do is validate contracts versus open API. It will detect missing endpoints, wrong status codes, schema
mismatches. You can convert from open API to spring contract contracts. So, in other words, if you write the spring the the open API contract the way spring contract understands, all the benefits of spring contract. There's a JUnit 5 extension even if you drift, if the contracts drift, it can fail. And it becomes a proxy guardrail, as I mentioned. Polyglot. First of all, we have a dedicated plugin,
Stubborn publish publish contracts for Gradle. For me, already using Gradle is polyglot >> [laughter] >> uh but these are my personal problems. But what about Node? What about Node? Start publishing using Node native libraries. It's there. It's in in NPM. Uh you can say, I want to I am order service in this version contract, publish them. You want to use Brew? No problem. The CLI is out
there using Growl. You can do Brew install. There is Scoop as well for Windows, right? You can use it. So, if you want to locally say, hey, can I deploy? No problem. Use the CLI. The MCP server is also there. So, you can ask it like, check if order service can be deployed to production. So, how does it work with Node.js? So, in spring contract, you will
have at autoconfigure stub runner and it will fetch the stuff. So, in the Node world, I'm not a Node expert, by the way, but from my understanding, this is the way to go. So, you import set up stubs, turn down stubs. And you say, the broker is there. I want the stubs of that app in this version. And it will start them. So, this is an example
of of a test that tests if the Stubborn uh just um integration works fine. What about So, actually what I did is NPM understands WireMock. It can read it and run it properly. also, Node knows how to fetch Maven JARs and unpack them and and make them work. Now, on the producer side, you have the verify contracts. So, you have to provide some some And what happens
is that if the producer is not uh correct, you're going to have the assertion message like what is not correct on the producer side. >> And if it's correct, it's going to report the results back to the uh to the broker. What Stubborn What Stubborn can do is normally, let's say, the stubs JAR, the contracts are in Artifactory Nexus, so you can import them into Stubborn. And
then for Stubborn Runner, you can say, "Fetch the contracts from the broker." What you can do is literally point to Maven and say in Stubborn, "Just just download them." But the funny thing is that uh also Stubborn has the Maven API. So, literally for you is to just change uh the existing Artifactory to Stubborn and it will work. Right? So, one config change, stubs come from Stubborn
instead of Artifactory. This is the only change you change you have to do, assuming that you migrated So, you don't have to do a big bang migration, which is always a problem, never works, so you can do it gradually. So, you can get started. Um broker is there available as a Docker In my org, I I should have done it like not MGrzejszczak, I should have done
Marcin G. That would be easier, I guess. if any of this gets traction, I will have the financial opportunity to buy in Docker and org, but I don't yet. So, I'm For now, sorry. Um so, there are ways to start. why why why Stubborn? I am not a maintainer per se. I don't have commit rights to Spring Cloud Contract. I have to work for pull requests, uh
which is fine, but the Spring Cloud team has a lot of work. I I know it. I've been there for for decades. So, I thought that it's it's a good idea to have a faster lane, like like a like a quicker one, to see if stuff gets have traction. Because if they do and they're more mature, we can file a pull request to Spring Cloud Contract, right?
So, Stubborn will be the fast lane. I can ship stuff to Maven Central. We It gets feedback. It's more mature. Then I Contract. I can release every day, every week, every month. In case of, you know, Spring Cloud, we have to wait for the 5.1 release, which I have no idea when happens. And it's possible to be to to be found 6 months, maybe, right? Why wait,
right? And if we can test it in the meantime, then we can contribute back to open source. I I mean, AI is here to stay. AI is awesome, I love it, except when I tell it like, "Cloud, Maven clean install." This is literally what I said. Like I didn't write anything else. I just wrote, "Maven clean install." And what did Cloud do? It said, "No problem." And
I'm looking at the command, "Maven clean install skip tests." Like, "Where did you find it? Like I didn't write it." So, but anyways, AI is awesome. Uh so, we need the contract tests to be uh also available through for AI. And this is my personal opinion, contracts and all sorts of tests become more important than ever before. You With AI, we can generate so much different quality,
let's call it like Regardless of the quality, it needs to work fine. The guardrails are the critical piece. And contract tests are a very good guardrail. So, I'm how I'm I am working recently is I, for example, have an app that has front end and back end. I start with the back end. I do ATDD, acceptance test-driven development, and I tell whatever the LLM I'm using, "This
is the business case. Start with the API. Do mocking VC tests. Add Spring Cloud Contract. Start generating stubs." I go through the back end cycle. And then, when I do the front end, I say, "These are the stubs. Write in the whole front end from the business case against the stubs. You don't need the back end now." And it's super fast, because these are WireMock stubs. They
start in no time, almost certain that the communication will be fine. Of course, afterwards, I add also some end-to-end tests for the sake of checking if the Docker container is starting, et cetera, et cetera, but this is critical, because even for AI, the fast feedback cycle is also important, right? You don't want to wait until end-to-end tests fail, but already have the guardrail of uh contract tests.
That's it from my side. We have exactly 4 minutes for questions. Now, I leave you with a couple of links. To the left, you have stubborn.sh. To the right, if my is my Maven course, if you're interested in how to generate break and fix uh AI Uh there are the docs, docs.stubborn.sh as well, the demo, uh my blog, toomuchcoding.com, and there's the org, stubborn.sh, because of course,
somebody took the Stubborn one, so I had to do it with a dash. sh. Um okay. Any questions? Like, do you have a Do you have questions? Yeah, go ahead. Why is there a contract.yaml >> and an OpenAPI spec.yaml? Aren't they very similar? So, the question is why there is a option to have a Spring Cloud Contract YAML and an OpenAPI spec. Uh so, OpenAPI specification is
a It doesn't describe proper usage. Like, you can have examples, but it doesn't describe uh like how to use it, but what is there. If you think of consumer-driven contracts, if you have a consumer A that wants fields one, two, and you have consumer B that wants fields three, four, one doesn't care about the first two, the other doesn't care about the second two. So, the fact
that you have a schema that describes all of the options uh is unnecessary, I mean, to some extent. there's no problem in having the OpenAPI schema with the X-Contract extension, where you describe the the usage. So, you have the schema, you provide the usage, and then Spring Cloud Contract takes the usage and generates tests out of it. So, you can have either this or that. You know,
you shouldn't have both, really. That doesn't make sense. Like, if you have the schema, just extend it so the contract Spring Cloud Contract understood understands, and then you start benefit benefiting from Does it make sense? Yeah. >> I thought, "Okay, we have a lot of OpenAPI specs." Very good. And I thought maybe that's just enough to have a contract for the others or others can see how
my service works or what it offers. So, if you have So, the So, the comment was, "We have a lot of OpenAPI specs." So, if you take them and provide the X-Contract extension saying, "If I send this, I get that. If I send this, I get that." You're done. It will work. I mean, technically, you have to point there. You get the idea, right? I mean, you
have to you have to plan Spring Cloud Contract in it, but from the point of view of what we need in the OpenAPI spec, that's exactly it. Just tell us how to use your stuff, because we know what you have, but we don't know how to use it. Again, it's not a replication of features. So, let's say let's say we have a fraud detection app that verifies
given different things, verifies whether you're a fraud or not. Let's say from the business perspective, you can be a fraud for 100 reasons. I presume you would have two contracts. You're a fraud or not. Because I don't care like what is your business logic. I care about semantics. So, I understand I have to have those 10 fields, fine. And now, let's say, if my name is fraud,
then I I get like 401, but if my name is Smith, I get a 200. And you test those two things. Any more questions? No questions. Okay, so um we're exactly at the top of the hour. I mean, at the end of this presentation. So, thank you very much. If you have any questions, I'm still here, and uh I would say enjoy the rest of the conference
but that's not a lot of conference enjoy but still enjoy that part and enjoy Barcelona. Thank you.
More from this event
See all 38 talks →
Spring I/O 2026 Keynote
1:08:44
The Spring AI Ecosystem in 2026: From Foundations to Agents @ Spring I/O 2026
43:39
Breaching LLM-Powered Applications: Overcoming Security and Privacy Challenges by Brian Vermeer
48:40
New in Spring Security 7: MFA, OAuth2 and more by Daniel Garnier @ Spring I/O 2026
46:43