 Welcome everyone. I'd like to welcome you to our next session. Why you should be doing contract first API development. My name is Richard Stroop and I'll be your moderator today. It's my pleasure to introduce our speaker for this session, Devin Phillips. Devin is a senior architect at Red Hat and he's been doing software development for 30 years. So he's got a lot of experience that we can learn from. A few logistics before we get started. If you have any questions during this session, please just submit them in the chat. I'll be monitoring them there to either answer or to go over live at the end of our session. If we don't get to one of your questions, we'll actually make a point to reach out afterwards. So please don't worry. There'll also be a recording of this session on YouTube afterwards. You can watch it again for clarification or send it to your friends or colleagues that you think would benefit from this talk. We'll also be monitoring those comments. So if you think of something later, you can always ask there. With that, let me turn things over to Devin. Thank you, Richard. I appreciate the introduction. And thanks for joining us today. I look forward to having a chance to share a little bit of the 30 years of experience I've had. And I'm going to switch over to the slides, which we'll try to get through quickly so I can do a bit of a demo. So you're adopting DevOps microservices because you've heard that they promise to allow you to deliver value faster to your users, to your customers. But you're not seeing the gains you want to see. What you're trying to get to is things like continuous integration and pipelines and continuous testing and microservices. But that continuous delivery journey, which you're actually seeing in a lot of cases, are things like chaos. You're seeing integration issues. You're seeing misunderstandings across teams and a lot of waiting. You're getting bogged down with these teams being dependent on the progress of one another. So service A isn't done, so service B can't integrate with it. The UI needs all the services, so they can't even start until everything else is done. And you end up with weeks of back and forth of integration because what service A told the UI that they were going to produce was not what the UI folks understood, and so they have to go back and forth until they have a matching implementation. That's not how this is supposed to work. Now, many of us are familiar with writing code, which other people interface with. In C and C++, we used to use header files to tell people what our code can do for them. In Java, it might be an interface definition, and this works really well for compile time guarantees. But what do you do when you're writing services which work over a network or over the web? If you've ever written an API or a service which is consumed by others, even inside your own team, this should be obvious. Every time you make a change to your service, those external internal users are going to be annoyed because you just broke their code. Take that annoyance and then consider what happens when there's multiple, perhaps multitudes of services, and worse yet when those APIs are published in the public for your customers. Add into that the complexities of distributed systems and you could end up with a recipe for disaster. I love this quote from Jez Humble, and I think this is always important for people to keep in mind that microservices is something that a lot of people have tried to adopt without truly understanding what they mean. They've heard that their developer teams can achieve greater productivity, greater collaboration, greater isolation, and that their applications can get greater scalability. What they fail to consider in order to capitalize on those promises is that they must fundamentally change how their teams, their customers, their consumers, and their partners work together. Just implementing microservices is not going to achieve those goals. You need to figure out a way to coordinate that work across multiple teams, organizations, and if you don't have a way for those disparate groups to coordinate asynchronously, then you've got a major bottleneck. Your back-end devs are waiting on database schemas and provisioning. Your front-end devs are waiting on APIs to code against. Your customers and partners are waiting documentation. All of that slows things down, which is why it comes to the question of why you should be doing contract-first API development. Regardless of if you find code generation tools useful or not, having a simple format for sharing contracts for your services amongst all the users of that service is of significant value. Let's learn a little bit about how simple and expressive it is to write API contracts using something like OpenAPI. OpenAPI, by using that as a coordination point between various different service developers, customers, UI developers, it allows you to have those people work independently and they have a consistent view of what that API is going to look like, what they're developing against, and it's not ambiguous. It gives you strong guarantees about those service contracts. It allows you to collaborate. For example, if you're building out an API contract document, you can share that API contract with your customers, with your end-users, with other teams, and they can see immediately, hey, do I have the right endpoints? Is it returning the right data that I need to be able to make my application work or present to the user? That speeds things up significantly before you even ever have to write one line of code. And in addition to that, you can save a lot of time by using code generators and testing tools that are built around using those API contracts. So the traditional workflow looks a lot like this. It has a lot of bottlenecks which prevent efficient progress. Project planning is time-consuming and the process often creates documents that are either too vague or leave too much room for interpretation or by the time they get them into the hands of the developer, the business requirements have changed. The developers try to consistently implement code, which is defined in the project plan, but differences of understanding and terminology make it easy for separate teams to end up with incompatible implementations. And this results in a lot of time and iterations required to resolve those compatibility and integration issues at a point very far along in the development process. Lots of rework, lots of debugging, miscommunication. Wouldn't it be better if we could get faster feedback? Well, the workflow that I'm proposing is that there are multiple different ways to do contract first. And the first one we'll talk about is using something like OpenAPI. Versioned API circuit breakers, they're all pretty well known, but what seems to be less common is this contract first approach. The first step is to use something like OpenAPI to create a specification. OpenAPI is the successor to the very successful swagger, which is a tool originally designed to create API documentation from your living code. It has since evolved to work in either direction. You can write your OpenAPI spec first and then generate code for it, or you can write your service code and generate OpenAPI specs from it. When we publish our API specification somewhere that our teammates, other teams, customers, partners can access, once you have that specification, you can start coding against it because you know what the API will look like. It's a contract. And from that contract, we can generate implementation or stub code using a tool like OpenAPI Generator. One of the ways I really like to get started with OpenAPI is a tool called Epicureo that Red Hat supports the development of. It's a free tool. You can use it online, or you can download and install it locally, and it'll allow you to quickly get up to speed on building new OpenAPI contracts. So another potential workflow is to use a tool like GRPC. This is another form of a contract, and we can take GRPC code, we can publish that specification, get feedback, have people try it out, make sure that it meets their needs, and then we can generate code contracts using tools like Proto-C. And then all we have to do is fill in some business logic and we're done. These are two possible workflows, but there's so many other available contract-first approaches now with tools like RAML, RSDL, OData, API Blueprint, IODoc, Apache Avro, AsyncAPI, all of these are becoming popular and they have different use cases that allow you to do this contract-first approach. Now, normally here I would talk about the basics of an OpenAPI specification. I think there are better documents out on the web for you to go and look at. I highly recommend looking at the OpenAPI spec that is available from OpenAPI.org. So instead, today what we're going to do is a bit of a demo. I'm going to demonstrate for you how I typically use OpenAPI and contract-first to develop applications. So let's get started first by looking at an OpenAPI contract in Apicurio that I've pre-canned. And let me zoom in a little bit on this to make sure everybody can see. Oh, there we go, showing the wrong screen. So you'll see that I have a number of different endpoints and each of those endpoints may have one or more verbs associated with it. I also have a number of defined data types. And these are all really cool in that we can see quickly what data types and what fields and what types they are and the various interactions we can have with this API. And what's really cool about Apicurio is that we can quickly add new things. So let's say, for example, we wanted to add a new data type for our end users to maybe show their social media information, social media links. And we'll call this data type social media links and we could just put an example, Jason Block here. We could say, site is Facebook. Username is Infosec812. That's the username I use in a lot of places. Even though I don't use Facebook, we could have a link to my Facebook profile if I had one, so on and so forth. Now, I've just defined an example of what this API endpoint might return and Apicurio provides me this really nice little button here to generate a REST resource for that data type. And when I click save, not only does it take the example Jason and turn that into a type specification, but it also adds all of the endpoints and verbs to my API spec for me. And if I wanted to, I could go in and customize those or I could go down here and customize the data types and add more information or more detail, so on and so forth. So that's a really great way to get started. But once you have an initial API specification, it's really helpful to be able to quickly start using it. And let's imagine that we are a user interface developer. We're writing a React or a Vue.js front-end for an API that our company is producing. I'm going to show you a couple of tools that we could use. So you can see that this is a Vue.js project using Veet. And I've installed a couple of tools, specifically NPM Watch, which runs one or more processes and keeps them running and restarted based on configuration that I've set. And I've also installed this tool Prism. Prism takes an OpenAPI specification and produces a mock implementation, no code required. And then finally we have the OpenAPI Generator. OpenAPI Generator has tools for generating a number of different generator methods. If you want, you can go look at openAPI-generator.tech. Oh no, their website is down. That's crazy. I just looked at their website like 10 minutes ago and it was up. That is kind of unbelievable. Well, so what we can do instead is we can go to gethub.com forward slash openAPI-tools and we can look at the documentation there instead. Oh no, is gethub down too? Well, you just can't predict that for a demo. Well, suffice it to say OpenAPI Generator is capable of generating code from an OpenAPI specification for both client-side SDKs as well as server-side implementation code. And what I'm doing with it here is I've got my OpenAPI YAML file in my project here and I've set up NPM Watch to rerun the OpenAPI Generator every time I change my OpenAPI YAML file. It's going to keep Prism running while I have the application running in dev mode because Prism will automatically notice any changes in the file and update as well. And then finally I run my Vue.js application in dev mode and it looks to see if there's any changes in the package.json or the Quasar config or the package.lock file and it will restart dev mode if any of those files change. So when we do that we can say NPM run dev and we see that we have a server running on local host. This application I call it budget, which is a play on words. It's like a personal budget finance tracker. And you'll see that we actually have no data available and we got some errors because... Oh, I did run dev instead of run watch. That's my problem. So it didn't start up the Prism mock API which you can see these messages coming from here's OpenAPI Generator generating the client code for me. Up here we see that Prism is producing mock endpoints for all of our API endpoints. And then finally down here we see that our Prism application is handling requests already. And so you can see, oh, hey, we got mock data. I didn't write any code for the API yet. All I did was write an OpenAPI specification and we've already got data that we can start writing user interface code against, writing integration code against, testing things with. This is really great. So you'll see if I refresh this data, it's all just randomly generated data. And you'll see that we have amounts. We have a due date. We have whether or not it's been paid for a particular month or year. And what's really interesting about this is different OpenAPI tools have different extensions to the OpenAPI specification to allow you to add functionality. So one example that I'm going to show you is in our data types down here in our OpenAPI specification if we go and look at say new bill, right? Find new bill. We'll go down to the actual new bill data type definition. You'll see it's a type object. It has a description. It has some required fields. And there's some properties. But what's really interesting to me is these X dash properties. X dash in an OpenAPI specification means it's a vendor extension. So I've added a vendor extension that when I generate Java code from this data type, it's going to add JPA annotations, for example. There's also this X dash faker. And this is a special keyword that works with prism to tell prism a little bit more detail about the kind of fake data it should generate. And so it's saying that for this company name on this bill that it should be a company name instead of just Laura Mipsom data, which is what the normal would be. So if I were to, say, delete that string from here and save, you'll notice that prism reloads. And if I reload this data, we just see Laura Mipsom. But if we add it back, reload this data, we see something that looks like it might be a reasonable company name. Similar, we can add regular OpenAPI specification limits like minimum values, maximum values. We can add format information for like dates and times. And again, you're seeing that we're adding field annotations. We're adding class annotations for our generators. And if we were to go, say, look at the user data type down here. Actually, it's up. My mistake. So month, components, error, currency, period, errors, month. There is my user type. There it is. I should have searched for it in the first place. We've added this xfaker to say, hey, generate a full name for me. And we told OpenAPI that this is a string of format email, so it's going to generate actual email information. And we can actually see that if we were to click into, ooh, where did that link to? That's interesting. I have a bug, obviously. So if I click edit, oh, that was the link that it generated to go to pay your bill. That's what it was. That's not a bug. And so I can actually change this to US dollars and maybe make it 300 instead. I can actually submit this form and see if that submit form works. It doesn't actually persist the data in the mock API, but it does actually let me test it. And what's really great about this is I can iterate. Let's say, for example, I wanted to change the maximum minimum amounts on those bill values, right? I could go down here and I could say bill. I could go down here to the amount and I could maybe set the maximum to be, I don't know, 50,000 and the minimum to be $80. And now if I save that, I can immediately see that I have values all the way up to 50,000 but nothing lower than $80. I can immediately fast feedback, get realistic testable data on all of this information. I even have this tied into random user.me to pull in what looks like a real user profile. Interesting. There's another version of this code somewhere that I need to fix that actually gives you an avatar picture and stuff from random user.me. So that's really great and we can get fast feedback. We can show this prototype to our end users, to our customers, to our peers and get feedback and they can say, oh, yeah, this is really good but it would be great if you also supported, let's say, for example, pesos. Oh, we don't have pesos. Okay, let's go down here into our API spec. Let's find our currency type, which is an enum in here. So we've got great bridge pounds, US dollars. We've got euros. Let's add pesos. And now, if we refresh this, but we don't have a bit in our code here for a symbol for pesos. So we would need to go and add that to our code, so on and so forth, pages, bills. And we could go and add code for that into our VJS app. That's great. Now, we've iterated. We've gotten these feedback cycles. We've gotten information from our customers. We know that we've built something that actually needs their needs. So now we want to actually implement a real back-in and that's where we start to see some amazing value from something like OpenAPI and OpenAPI Generator. So what I've got down here is I've got a shell script and if I open that shell script, open file, go up one level. It's running an OpenAPI Generator command to generate a JaxRS application using the JaxRS spec generator and it's going to generate it for Quarkis version of JaxRS spec and we're telling it, hey, only generate interfaces. Here's our Java package names that we want you to use. This is the date Java library we want you to use. Here is where you can find the OpenAPI YAML file and I want you to output it to a directory called Budget Quarkis. So if I go and run GenQuarkis, boom, it generated the code and if I open up the Java code in VS Code for Java, what you'll see here is that under Source Gen API, there is this Bills API interface and it has all of our rest endpoints defined for us with all the swagger annotations and great, all we have to do now is implement this interface and add our specific business logic. Additionally, it created all of our pojo model files and added those annotations we were talking about or, oops, I needed to update, they changed the name of the X Java annotations recently in one of the OpenAPI versions so I need to fix that in here but it would have added the OpenAPI Java annotations or the Hibernate Java annotations in here for JPA and so what I can do now is I can go down here under Source Main Java, I can create a new class and call it Bills API Implementation.java and VS Code starts to fill that in and I say Implements Bills API and I tell it to add all of the unimplemented methods and then all I have to do is go in here and add my business logic. I don't have to worry about do I have all the annotations right? Do I have the types right? Do I have the field definitions right? I just write business logic. I write code that produces real business value instead of getting mired in boilerplate code that you write over and over and over a million times but beyond this we can actually take this a little bit further we could go down here and we could start writing tests that take advantage of our OpenAPI so if we go New Folder Test New Folder Java there is a library that I really like from Atlassian that integrates with Rest Assured and we could add that library here and that library allows you when you instantiate your Rest Assured testing client you can give it an OpenAPI specification and tell it which endpoint you're testing and when you make a request to that endpoint it will validate that the response and the request both exactly match your OpenAPI specification without you having to write very much code at all it's like two or three lines of Rest Assured code to make that work and Rest Assured is very well supported in say the Quarkus ecosystem and others to allow us to quickly gain value so if we think about this in terms of the tooling that can help us speed ourselves along there are a number of really great tools to help us we have documented a lot of this in a website that we produce called appdev.consulting.redhat.com under Tracks, Contract First we have videos and tutorials that you can walk through on your own to try all of this out so the default tutorial is for Spring and Spring Boot but there are tutorials for Quarkus for ASP.NET Core down here as well and some things that I'll point out in addition to what I've shown you we can do automated API testing with a tool like Schema Thesis Schema Thesis is based on a Python library called Hypothesis that uses machine learning techniques it reads our OpenAPI specification it generates a large number of tests based on the limits you put on it and it will exhaustively validate your implementation versus your contract and tell you whether or not you're meeting your contract you've got to be a little careful about the limits you put on it because if you just let it go it can run for hours doing really exhaustive testing and there are tutorials here to explain that to you Questions about the demo? Anybody? All of this code, by the way I will give you a link to but you can go to github.com forward slash info set 812 and you can search for budget, BUD, JET and you can access this code immediately unfortunately github is still down and you can try this out for yourself this works with React it works with Angular it works with SvelteKit you name it it doesn't really matter what really matters is that you're generating that client-side code that's what this little bit right here is doing the OpenAPI Generator and you'll see that it's generating this SDK folder it has all of the client code that I need and I just call that client code directly from my application so down here in my VGIS code I implement my unified store and my unified store has all of my code from my generated API code so bill, income, new income, user, new bill so on and so forth it integrates it with Axios or Fetch you name it, your preference and I just call it I don't actually have to worry about what's the URL, what's the endpoint what are the properties I just call code I just say hey give me all users and I get IntelliSense completion because of that and so on and so forth really really productivity improving with that let me switch back over to my slides real quick oh crap accidentally closed my tab switch back over to the slides real quick to wrap up so there are lots and lots of OpenAPI tools out there for us to use there are editors there are server implementations client implementations testing tools, mocking tools I've already talked to you a little bit about Epic Curio but there's also Swagger editor there's plugins for VS Code plugins for IntelliJ plugins for Eclipse you can implement server applications with tools like OpenAPI Generator but in certain runtimes in certain frameworks they have the ability to not have to generate code so for example Vertex WebAPI contract reads your OpenAPI file directly in the application and you just associate code with endpoints with what they call labels within the OpenAPI specification similarly there's a framework called MicroTS that does the same thing Smart Recruiters API first is a Node.js Express extension that does similar and then client implementations you can do OpenAPI Generator Vertex's WebAPI client can do the same thing you can read your OpenAPI spec and you just say get all users or get all bills something like that there's a tool called APImatic there's an OpenAPI client for Axios and then testing tools this is that Atlassian Swagger Request Validator this works with Spring rest assured packed on and on CHI OpenAPI Response Validator if you're working in the JavaScript world Hikaku is another automated testing tool for OpenAPI, Assertable and we've seen the demonstration already writing a specification server implementation client implementation testing, mocking and here is a link to that website that I was mentioning earlier that will let you run through a lot of these tutorials I highly recommend you check it out and with that I'll open the floor to more questions can't believe GitHub's down that's terrible and GitHub page is both well we don't have any current questions in the comments so for those of you watching live if you have questions now is the time throw them in the comments I'll read them out for Devin to go over I will say it is quite impressive that GitHub went down I assume that they went down and right as your video started so that people would stop coding and come check out your talk amazing timing on that isn't it it must be I was actually following their githubstatus.com and it took them just like five minutes ago to even realize they were down so it may still be a minute until they're up but that is quite impressive that you timed your demo exactly as they went down yeah exactly I do have a few questions for you while we wait absolutely fire away questions I'm gonna play Devil's Advocate for a second the tooling that you went over is great I've used a lot of it and I learned a few that I hadn't seen before but most of them look like they would work whether I was doing code first development or contract first development like if I really liked writing my code first I could generate a contract and then start from the same point and just not have it generate the code still generate the test well and that's actually one of the strategies we use when we're helping customers modernize their their legacy code let's say they did a code first implementation of a Jaxar SAPI but going forward they'd like to move faster or move toward microservices we can take that generated swagger or open API specification from their code first and then we could flip it so that any new development would be contract first to allow them to move faster to be able to integrate with more teams more readily and that gives us the ability to also break things apart let's say it's a huge monolith with hundreds of rest endpoints for various different business domains and we switch over to contract first we can use that to generate the interfaces or the API specifications like your C headers or your Java interfaces or your .NET interfaces and use that as the boundary to break off a new microservice so we can strangle that monolith for the items where it makes sense like for example the one case study that a lot of people talk about is like the catalog function of a site like Amazon that gets hit way more often than say the purchase or the payment handling and so that needs to scale elastically more readily than the rest of the application so if you generate that interface then you can generate the client code from that interface to talk to a microservice and that microservice could be written in any language that open API generator supports you can generate it in Go or Rust or JavaScript or Kotlin or whatever right but the interface looks the same on both sides so it looks like you're still calling the exact same local code even though you're now calling a remote API and it allows you to move to that microservices implementation more sustainably with less churn with less error prone yeah I like that it's cool that the tools don't kind of lock you in and let you shift a little easily absolutely how does that solve the problem you talked about at the very beginning and you even experienced a little yourself with the hibernate annotations if somebody makes a change you still have to go back and edit it whether you do contract first or code first if an update needs to be made to a contract if pesos need to be added that's going to cause some issues do any of these tools also work for like letting people know letting all the other teams hey there is a change coming or doing versioning so that you don't get broken until you make the change what are the tools that you were using or that were plugged in there that help with that issue absolutely so for smaller examples like adding pesos to our API that's not such a big deal you don't really need to version of your API because it won't break existing functionality but if you do need to change the contract specification in OpenAPI the way you would do that is either you would publish another OpenAPI specification that you would call v2 and you would keep both running until everybody migrates to the v2 or within the OpenAPI specification path you could prefix it with like v1 or v2 right so that you're versioning your APIs and only breaking changes would you be moving to a new implementation that's generally the way you see that people do API versioning so that you don't break legacy functionality at least until everybody's moved over and hopefully you've got some observability and metrics or tracing to say oh yeah nobody's using the v1 API anymore we can sunset that now or we have these users that are still using the legacy API let's notify them that hey we would like them to move to the new API in X time period so that they have time to do that migration and we no longer have to maintain legacy code but you can also use what's the word that's not coming to my mind feature flags to switch on and switch off new functionality as you're generating new code legacy and API specifications so for example instead of let's say I was going to make changes to this bills API to handle pesos inside of the endpoint for bills I could go down here I could change some of the parameters for we've got start date end date to grab all the bills we could add a parameter in here that is name updated currencies and we could add a feature flag right here to our open API specification that tells the back end whether or not to use those new currencies and regenerate the code for the most and we could actually in here we can specify in query required false false I can spell I really can but I can also say I can specify a default value of false and so even if I regenerate the code I don't actually have to change anything immediately I can take my time going to the back end or hand it off to the people that develop the back end and say hey I need this feature flag to handle these new currencies it's not even in my code already but it's not breaking anything when you guys get to it go for it that's really cool yep and even better yet one of the things this is true of both open API generator and a sync API generator it's based on mustache and handlebar templates which means if I want to customize the code that it generates I can let's say I want to customize the way the pojos are generated I can grab the template for the pojos from an open API generator pop it into my project customize the code that it generates in that template and when I run my generator I just pass it that directory and it will say oh you've overwritten the pojo.mustache file okay I'll use yours to generate that code instead of the one that's built in so you can implement your own coding standards in those templates you can override which is what we do a lot of very cool with that I think we're out of time so thank you Devin for that great presentation thank you for joining us thank you all for joining us we hope you enjoyed the session as a reminder this session and all the other ones today are going to be available on our red hat developer youtube channel so if you think of some questions later you can add comments there we will be monitoring it to answer those questions for you be sure to hang around here in this channel if you'd like to watch the next presentation it's going to be platforms and portals a book and it's cover or you can hop over to some of the other stages to check out the other sessions going on look forward to seeing you guys in those other sessions have a great day