The first step on your Kotlin Multiplatform journey — changing your microservices.

Mark Ng
The Startup
Published in
5 min readApr 20, 2020

--

The mobile apps that we use today wouldn’t be very useful without APIs and the same can be said about APIs — without nice UIs the information from calling APIs isn’t very consumable. When I first started in mobile development many years ago I always had the dream of creating reusable SDKs for our internal APIs to make integration faster and easier on our apps. Just for clarity, our internal APIs are internet-facing however they can only be consumed using an authenticated token and by our own clients. So why couldn’t we provide SDKs just like the big tech companies provide for their public-facing APIs?

As it turns out creating and managing SDKs can be a very time consuming and expensive proposition especially when you have to support multiple platforms such as Web, Android, iOS and the JVM. The big tech companies have the resources and the money to do this but what can be done if you work in the enterprise or corporate world? Most corporates tend to use either Java or C# for their backend/APIs and if you happen to work a Java shop then you’re in luck. Fast forward to 2020 and a framework called Kotlinx Serialization now makes it a reality, you can easily build a partial SDK with little effort and start sharing it amongst your clients.

Now let’s jump back to the past for a while and look a previous attempt in my life to do something similar. I’ll also explain why I call it a partial SDK later on. A few years ago, Australia Post embarked on an ambitious project to create a product called Digital iD. The project involved building everything from scratch and working in a monorepo. The APIs would use Jackson to serialize/deserialize JSON and since the Android code and the APIs coexisted in the same repo it made it sense to share the same model classes. This worked really well, when the API developers changed the models it automatically flowed to the Android app. It was a great if you worked on the Android app but not so good for iOS. Back then it wasn’t technically possible to share java code with iOS so the iOS devs had to duplicate these models. It was also the first time I had worked on a monorepo which has some obvious benefits but what can you do if you not using a monorepo? As it turned out the use of the monorepo on the Digital iD project at Australia Post was the exception as most of our other teams and projects use a separate repo for each microservice.

Now coming back to the present since most of our backend developers had switched or are switching to Kotlin (some teams as early as 2016) and all our Android teams have been on Kotlin for a while, this alignment in technology meant the vision of using the same API model classes was now feasible in our organisation. As a spike we decided to take a simple Spring boot API contained in its own repo and see if we share the same model classes with any JVM based client. The prospect of sharing code means less defects, faster API integration and in these troubling times the ability to work smarter and do more with less.

We decided to take a simple microservice in this case the Geofenece API which also calls another API and make its model classes shareable. These are the steps we followed;

  1. We changed the serialization framework from Jackson to Kotlinx Serialization and converted the model classes to use @Serilizable annotation. Kotlinx Serialization also comes we a number of other annotations for using with inheritance and implementing your own serialisers. Although this model class is quite simple in reality most of our other model classes have 100s of attributes. Typos and spelling mistakes are quite common and tracking down these issues can be time consuming.

2. To make the model classes shareable we modularised the API code and split it into 2 separate modules, 1 module for the models and other for the Spring Boot API.

3. We also changed our CI job to publish the jar file to our Nexus repository using the Gradle release plugin.

./gradlew geofence-model:release

4. Then we added the shared model artefact as a dependency in our Android app for use in our code.

api "au.com.auspost:geofence-model:1.1.31"

5. Finally we changed the Retrofit client to also support the Kotlinx Serilzation by adding the Kotlinx Serilzation ConvertorFactory (it’s the 7th line in the code below). By design Retrofit supports multiple converters so it’s not an all or nothing proposition which means that your Gson code can co-exist with your Kotlinx Serilzation code. That’s extremely important because it means you don’t need to change any of your existing APIs which already use Gson.

The end result is that now the models can be shared whether it is API to API or client to API communication with very little work. Since our microservices were already using a JSON parser making the switch to another framework wasn’t really a big deal. Kotlinx Serilzation also provides other benefits of being a faster, Kotlin safe and more light weight than other serialization frameworks such as Gson or Jackson. Also, the fact that you now have a potential sharable artefact that could be used on multiple platforms is a win-win scenario. As a consumer of an API service would you prefer rich model classes with types, nullability and metadata or just a plain JSON document?

Although our spike didn’t include generating code for iOS, our other spikes have shown this is indeed possible. At the moment we are looking for a good solution for building iOS code in the cloud. We are getting pretty close to the dream of having a partial SDK for our all clients but we aren’t there yet. It’s only a partial SDK as it doesn’t provide exceptions, the URL paths or operations like PUT or GET, however if you use Retrofit it’s really easy and fast to add this stuff. In our teams we find that coding the models is the most tedious and error prone part. Our approach to adopting KMP is to leverage as much of our existing code and frameworks as possible, although we could move to Ktor to provide a complete API SDK we feel that this would introduce too much change.

If you liked this article, also check out this one — https://medium.com/@markchristopherng/kotlin-the-next-enterprise-language-547d2dec2a66

Btw, thanks to Karl Maul for helping with the spike and proof reading the article.

--

--