Topdown Polyglot Microservices with OpenAPI

In previous blogs, I took you on the journey to containerise a seemingly monolithic application called MedRec, which runs on the WebLogic Application Server. Since then, the strangely familiar, yet fictitious, development team behind the MedRec application have realised that the Physician and Patient components of the system are together starting to look more like a big ball of mud. It's becoming increasingly difficult to ship features to the Physicians without having to disrupt the Patients user base and vice versa. Further amplifying the situation, the teams are under pressure to increase the value of their offering through the interoperability of health wearables and the establishment of Public APIs. To address these concerns, the development team has been split into two Agile teams:

  • Physician Services
  • Patient Care

"Gather together those things that change for the same reason, and separate those things that change for different reasons." - Robert C. Martin

The teams are designed to be able to deliver autonomously and the team members are excited about what this may bring. Whilst it will take some time to chip away at the big ball of mud, the teams are seeing the restructure as an opportunity to deliver independently and focus on the technology that is fit for purpose rather than trying and failing to come up with an organisational standard.

The OpenAPI Specification

The OpenAPI Specification (formerly known as the Swagger Specification) provides machine-readable interface files for describing, producing, consuming and visualizing RESTful Web Services. Combined with the Swagger tooling and the associated API designer ecosystem such as apiary.io, the OpenAPI Specification makes it easy to generate interactive and discoverable API documents on the fly all from an easy to read YAML file as well as the ability to generate code stubs from the definitions.

At MedRec, one thing both agile teams agreed on is the need to adopt OpenAPI specification for API definition. Independently each team will use the Swagger tooling combined with apiary.io to perform Topdown design of their APIs.

Polyglot Microservices

The Physician Services development team are keen to utilise NodeJS for their API implementation. They have been building prototypes on this with any time they can get away from the Java development of their MedRec application and they want to take this to the next level. They believe it will help to move the Physician Microservice forward with faster, more stable and more valuable innovations to come.

The Patient Care development team are less driven to move away from Java, after all they had a big part in the redesign from J2EE to Spring. They won't be moving Patient Care to any different programming language any time soon, but they do see the importance of moving to an API-first architecture where the API are designed and delivered to provide agility to support multiple user experiences such as Web, Mobile, Partner Portal, Wearable Device and so on.

Fortunately, the choice of language doesn't really matter anymore for the MedRec organisation as long as the outcome is delivered. The teams are empowered to deliver independently and interconnect only by APIs when it makes sense to do so. A positive side effect of adopting the OpenAPI specification amongst the teams is that it allows for them to generate the stubs in whatever language they see fit. Let's explore this in detail by first installing Swagger locally and create two simple microservice prototypes - one in NodeJs, the other in Spring-flavoured Java.

We are going to create an API from scratch using the Topdown approach. To follow along with these steps you should have swagger installed locally. We can install that through npm as follows:

npm install -g swagger  

Alright let's do this thing!

Creating our initial NodeJS project using Swagger

We start by creating a new Swagger project for the Physician Services

swagger project create physicians  

You can see we are presented with an option to choose the framework that we wish to use. In our case we will choose the express option.

When we complete this step, it will generate for us a working a hello world application with the following structure.

└── physicians
    ├── README.md
    ├── api
    │   ├── controllers
    │   │   ├── README.md
    │   │   └── hello_world.js
    │   ├── helpers
    │   │   └── README.md
    │   ├── mocks
    │   │   └── README.md
    │   └── swagger
    │       └── swagger.yaml
    ├── app.js
    ├── config
    │   ├── README.md
    │   └── default.yaml
    ├── package.json
    └── test
        └── api
            ├── controllers
            │   ├── README.md
            │   └── hello_world.js
            └── helpers
                └── README.md

Let's start our Swagger project

swagger project start  

Hey cool! I can test this API with

curl http://127.0.0.1:10010/hello?name=Craig  

and here is our response

"Hello, Craig!"

Great! It's working. Let's move on to make it a real API for our Physician Services prototype.

Editing our API using the Swagger Web Editor

From a different window, let's open the swagger web editor.

swagger project edit  

When you do this it should automatically open a browser window at a URL like http://127.0.0.1:59542/#/edit

Using the edit is fairly straight forward. We make changes on the left and then we see our documentation on the right being automatically generated on the fly. Pretty neat!

Where did it save to?, since we previously created a Swagger project our changes to the YAML via the editor will end up in the file api/swagger/swagger.yaml. We can of course edit this file manually using any text editor but without the Swagger Editor we can't see the generated API documentation in real time.

Creating our Minimal Viable Product for Physician Services

Our initial Physician Services prototype will follow fairly standard RESTful API design principals.

  • GET /physicians to list all Physicians
  • POST /physicians to add a new Physician and return their ID.
  • GET /physicians/{id} to get a specific Physician record
  • PUT /physicians/{id} to update a specific Physician record
  • DELETE /physicians/{id} to delete a specific Physician record

If you are playing along at home, you can copy and paste our updated swagger.yaml from this link on github into the left hand panel in the Swagger Editor.

Once we have done this we are ready to test our APIs and the neat thing is, we can do that straight from the Swagger Editor without writing a single line of code.

Testing our APIs using Mock Services

One really nice thing about Swagger is we can get it to generate mocks without any coding required. To do this, all we need to do is exit our existing project that we had previously started and restart it with the following

swagger project start -m  

The -m indicates we want mocks.

Now that we have mocks we can use the Swagger Editor page to actually interact with out API directly. Give it a go!

Let's click on Try this operation under GET /physicians. As this is a GET request we don't need to provide any payload, just click Send Request. Look ma a JSON payload!

The Physician Services team are delighted! By hardly lifting a finger they already have a working mock API that they can share with key stakeholders for feedback and they can even deliver it to the UI developers so they can get a jump start on development of the minimal viable product for the new user experience for Physicians.

Writing the initial NodeJS implementation code

Let's add the crypto package. We will need this to generate an ID for new Physician records.

npm install crypto --save  

Let's create the file config/db.js with the contents from this link. This will give us a basic implementation with no data persistence. Basically, it will store the changes in memory until we are ready to wire it up to a database.

Let's now create another file at api/controllers/physician.js with the contents from this link. This files creates all of the operations to support the implementation of our new Physicians RESTful API.

Testing our implementation using the Swagger Editor

It's the home stretch for the first Physicians API prototype. Let's restart this again, this time without the mocks. We want to test the real implementation.

swagger project start  

From the Swagger Editor have a go at creating, deleting, updating the records. You should now see that they are being persisted and updated in memory within the NodeJS application.

There you have it, a NodeJS API for physicians built top down. All we need now is some real data persistence. We'll look at that in a later blog :)

Generating our Java project for the Patients Microservice

Meanwhile in the Patient Care camp, the team have created their own RESTful API using a similar approach but they don't want the implementation to be in NodeJS. No worries! Swagger provides a language agnostic code generation framework. All we need is to install the swagger-codegen tool.

Multi-language code generation

When you run swagger-codegen without any arguments, it displays a list of all of the supported languages.

Available languages: [android, aspnet5, aspnetcore, async-scala, bash, cwiki, csharp, cpprest, dart, elixir, flash, python-flask, go, groovy, java, jaxrs, jaxrs-cxf-client, jaxrs-cxf, jaxrs-resteasy, jaxrs-resteasy-eap, jaxrs-spec, jaxrs-cxf-cdi, inflector, javascript, javascript-closure-angular, jmeter, nancyfx, nodejs-server, objc, perl, php, python, qt5cpp, ruby, scala, scalatra, finch, silex-PHP, sinatra, rails5, slim, spring, dynamic-html, html, html2, swagger, swagger-yaml, swift, swift3, tizen, typescript-angular2, typescript-angular, typescript-node, typescript-fetch, akka-scala, CsharpDotNet2, clojure, haskell, lumen, go-server, erlang-server, undertow, msf4j, ze-ph]  

Code Generation of JAX-RS

The Patients Care team have decided to settle on JAX-RS 2.x with CXF-RS as the REST framework. They can get their server side API stubs with a single command. Cool huh?!

swagger-codegen generate -i swagger.yaml -l jaxrs-cxf -o patients  

Closing Remarks

In less than an hour, both of our Agile teams have built their own RESTful APIs with a minimal viable implementation. Independently the teams can share their interactive API documentation hosted on Swagger with interested parties for feedback and the frontend and backend developers are empowered to take the implementation to the next level.

I hope you found this use case / tutorial useful and get a chance to try it out on one of your own projects. Rapid API prototyping skills is a great thing to have in your back pocket and with OpenAPI/Swagger we can be sure that whatever implementation we wish to use, we are covered.

Acknowledgements

I wanted to thank Samuele Zaza for his awesome blog at
https://scotch.io/tutorials/speed-up-your-restful-api-development-in-node-js-with-swagger. This blog provided some of the inspiration for this particular post of mine. Do check it out if you have some time!

Alternatively, if you want to move on to securing the web services that we just created, you can check out another useful blog on the same site - Authenticating a Node.js API with JSON Web Tokens
.

Come see us at Oracle Code

If you're in Sydney on Tuesday the 18th of July, you may be interested in the free Oracle Code event. I am doing a session with Arun Pareek titled Make your Microservices Sing! The Important role of Containers and DevOps. We will be talking specifically about the MedRec application and using it as an example demonstrating good practises for breaking down a Monolith into a Microservice. In addition, Rubicon Red will have an exhibit where we will be demoing a Microservice-based IOT solution for health based on the Oracle Cloud. If you're there, do come along and say hi, it's always great to chat Docker, Microservices and WebLogic Automation with like-minded people!

Craig Barr

I am a Software Engineer with a decade of experience empowering Enterprises in Banking, Logistics, Manufacturing with Service-Oriented Architecture, Microservices and Cloud Computing.

Brisbane, Australia https://twitter.com/craigbarrau

Subscribe to Oracle PaaS, Oracle Middleware and DevOps

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!