Exploring Contract First type of development of Microservices with OpenAPI spec

Luis Trigueiros
8 min readFeb 25, 2024

--

I have pitched recently to my team about the need to embrace contract first type of development for our microservices.

We use the Spring Cloud Microservices stack with already about nearly 50 microservices in our fleet.

In the current approach the different services expose their API’s via REST/OpenAPI with the API spec being auto generated by the annotations present in the code, so it is Code First not Contract First type of development.

As the footprint of microservices grows and the interdependencies between services and downstream applications expanded, it started to become more noticeable the need managing the API’s contracts specification as a first class citizen on its own right.

As you can see from the above a given service API can se consumed by :

  • MobileApp user
  • WebApp user
  • Batch Process user
  • Another API user

So I began looking for ways to have the contracts drive the generation of the services interfaces that conform to the declarative OpenAPI spec format.

Using Contract First type of approach there is the potential for huge gains in terms of productivity and consistency and improve quality of the final deliverable, since the code talk to that API contract can be generated both for the server implementation and the client.

Also using Contract First it is it becomes easier to develop in parallel for both the consumer and and provider once contract is drafted mocks or stubs can be generated and the usability and suitability of the API can be proven more quickly.

Also this make it easier to version and evolve the API because both client and server code are generated against that one source of true of what the contract should be.

I don’t see OpenAPI contract first approach as the final end game on the journey, as their are other formats that are equally valid like GraphQL or Protocol Buffers or even Apache Thrift, but rather as a good logical next step in where we are in our maturity journey.

Proving the concept

While exploring the idea I decided to undertake a small prove of concept to prove the idea.

There where a few questions that I needed to get answer before commit any further, questions like:

  • How would the code look like ? Would it look idiomatic since we would be pivoting from hand written code to a hybrid approach with some of the code being generated from the OpenAPI declarative contract spec.
  • Would there be any productivity and code quality gains ?
  • Would it make our lives easier or harder ?

There is nothing like doing a small concrete example to prove the concept and explore this questions in a concrete way.

I based the example in the course from PacktPub on SwaggerTools by “Praveenkumar Bouna” you can find both the video and source code at:

The course is short about 3 hours long and I highly recommend it as a good introduction to OpenAPI/SwaggerTools .

The image bellow is a screenshot from the structure view of OpenAPI spec file for this example and it allows us to have quick summary view and understanding of the use case.

This is represents the API of a university/college management system where we have “Course” and “Student” as main domain entities.

Having this example in mind now it time to narrow the search into the the tech stack and concrete implementation of the contract first approach to service implementation taking the above OpenAPI spec and used it as the input that will drive the generation of the service implementation.

Narrowing the search

There is more than one code generator from OpenAPI/Swagger to Java with SpringBoot in my case I need something that works well with :

  • OpenAPI3+, OpenAPI spec version 3 or above
  • Java17+, Java version 17 or above
  • SpringBoot3+, SpringBoot version 3 or above
  • Gradle7+ as the build tool, version 7 or above

So after some search decided to use the:

It above code generator is free and opensource and looks to be widely used and well maintained with very good documentation and many examples with support many languages with about 19K stars in GitHub so it looks to be a solid choice, below is the Git repository stats

As you can see from the above chart this can be considerer now a stable repository it exists since about 2012 it had to big peek of activities between 2015–2017 and 2020–2022 and this is kind of what you are generally looking for in an open source product that you are consider to use in your own product, the only cause for raising the eyebrows is the fact that it was a very high imbalance in the code contributions between the top contributor and second code top contributor.

Implementations details

The above mentioned code generator ships a Gradle plugin so integrating it into a Gradle based type of Java project build is easy just need to add plugin to the build in the plugins configuration block from the project generated of from Josh Long second favorite place in the internet Spring Initializr .

To keep the example simple a direct to the point I did not used a multi module build type of project but rather a single module project and configured the code generator to generate service interfaces under the “build/generated-server” directory and added this directory as a source directory so that I can use this as input the implementation of the service

The above screenshot is the code generator plugin settings to have it integrated with the Gradle project build, in the line 84 I make the compilation of Java source code depends this way it ensures that the project will always compile against the most up to date generated service interface.

Currently this code generator produces a Maven based type of project so in order to make it work in a Gradle based I had to do a once step manual extraction of the generated project dependencies into the build dependencies as you can see from the screenshot bellow

Depending of the set of features select for the SpringBoot code generation options this set of dependencies may vary.

I explored only a subset of the configuration option available for the plugin code generation for a detailed view of all the options check this page:

Documentation for the spring Generator | OpenAPI Generator (openapi-generator.tech)

The screenshot bellow is the example implementation of the generated CoursesApi .

In the above example you can see that the implementation is bread a butter idiomatic Spring MVC code with the added benefic and low levels of noise in terms of not having to add all the other annotations needed by the code first approach.

The example above you can see how you can also avail of security in the API implementation by having the controller marked as a request scope type of bean and by receiving the NativeWebRequest allow you to get hold of the user principal in controller logic and implement logic in the controller that it is security aware.

The above image you can see how it is possible to run and test the contract from within IntelliJ IDE, offering a really compelling developer experience.

The screenshot bellow shows how it is possible to do exploratory testing of the API using the HTTP Client tool that comes with IntelliJ

Conclusion

This approach allows to focus on the implementation of the API contract and testing and validation since the implementation cycle becomes shorter provided that you become familiar with the OpenAPI spec.

The generated code is also very clean an Java idiomatic with interfaces and default methods and validation of controller method parameters already built in.

Honestly the I found the contract first approach a substantial improvement from the code first approach currently using.

It is worth mentioning that IntelliJ IDE has excellent support for editing OpenAPI spec files with code completion a validation on the fly, not to mention the support you will also find in SwaggerHub in their free opensource and enterprise offerings .

Bellow screenshot is the view offered by IntelliJ when edit the OpenAPI spec YAML file

The screenshot below is the support offered by IntelliJ with the Endpoints tool able to discover the endpoints declared in the OpenAPI spec YAML file and also the integrated support with the HTTP test client tool that allows to craft requests based on the spec and perform exploratory type of testing of the service implementation within the IDE.

The code repository for this POC described in this article is available at:

luistrigueiros/contractfirst: Contract first example using OpenAPI sec with SpringBoot using Gradle (github.com)

In the code repository you will also find examples of automated testing of this API using Junit5.

--

--