A guided tour of our service template\n-------------------------------------\n\n!(https://hackernoon.com/hn-images/0*u87LOuYjWC-6kGJe)\n\nPhoto by [Ilnur Kalimullin](https://unsplash.com/@kalimullin?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) … Came up when I searched for ‘hexagon’. But surely more sides is better, so we’ll let it pass.\n\nIt happened the other day that a team I was working with felt the right answer to a question about which tech stack to use for a microservice was ‘Kotlin with Ktor using a ports and adapters architecture, building with as a multi-module Gradle project with the Kotlin Gradle DSL. Plus Guice for dependency injection.’\n\nOnly no-one on the internet seems to have implemented a microservice with that particular combination of structure and technology before. Or at least, no-one has talked about it. Each individual thing I mentioned, yes, there is _some_ information available — but putting the pieces together was a challenge.\n\nSo… are you listening web-spiders? Are you paying attention, page-rank? I said:\n\n* Kotlin with Ktor\n* Ports and Adapters\n* Gradle multi module project with the Kotlin DSL\n* Guice\n\nWhy these things?\n\n**Kotlin**: Because Kotlin is [awesome](https://kotlin.link/). Everyone [says so](https://hackernoon.com/9-fascinating-things-i-learned-while-coding-up-the-rules-of-a-board-game-81df3330b938).\n\n**Ktor**: Because if you need a [framework](https://spring.io/projects/spring-cloud) on top of a [framework](https://spring.io/projects/spring-boot) in order to simplify your [framework](https://spring.io/projects/spring-framework), something has probably gone wrong somewhere.\n\n**Ports and Adapters:** P&A, also known as ‘hexagonal architecture’, is an [incredibly powerful mental](https://hackernoon.com/demystifying-the-hexagon-5e58cb57bbda) tool for producing testable, [clean architecture](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html). I struggled for a long time to articulate why I found it so much more powerful than an ‘n-tiered architecture with DI’. I think it boils down to cementing the concept of ‘inside’ vs. ‘outside’. Business logic and the domain model goes ‘inside’. _Everything else_ is outside. I have no doubt with sufficient discipline you can accomplish the same thing with other architectural styles. But applying P&A gives you some strong conventions to help guide your thoughts.\n\n**Gradle:** Curiosity, mostly. I’ve used Maven extensively in the past and made my peace with it. But I’ve heard good things about Gradle and I was curious to use it ‘in anger’, as it were.\n\n**The Gradle Kotlin DSL:** Because Groovy and I have parted ways. Also, curiosity. Also, masochism.\n\n**Multi-modules:** Ahah. Well, now… I find the reaction to adding modules to a project, especially a relatively trivial microservice, quite mixed. Everything from, “It’s fine — the structure helps”, to “GET YOUR FILTHY STINKING MODULES AWAY FROM MY CODE.” (Well, the actual words were ‘What? No!’ — but my super-power is hearing what isn’t said.) It’s a surprisingly divisive issue! The reason I choose multi-modules is to manage dependencies. It helps keep you honest, helps you enforce your own rules. For example, ‘_Domain shouldn’t know anything about JSON because it’s a transport layer concern_’ or ‘_Controller can’t talk directly to the database_’. Sure, it adds some complexity and might feel unjustified for a small service. But if you’re producing multiple services you only take that complexity hit once — then you have a simple template to follow for all the rest. And, be honest, how often do your ‘micro’ services actually stay micro?\n\n**Guice**: Because it’s not Spring, we’re used to using Guice with Play, and there was some assistance on the ktor website.\n\nThe code is the truth. You can find our ‘hello world’ service template here:\n\n[https://github.com/sgerber-hyperanna/ktor-hexagonal-multi-module-template](https://github.com/sgerber-hyperanna/ktor-hexagonal-multi-module-template)\n\nLet’s do a quick walk-through of the different modules though, their dependencies and any challenges involved setting them up.\n\n### Module Layout\n\n!(https://hackernoon.com/hn-images/1*YemYbKoib8CKpb2YlIMeQA.png)\n\nModule diagram auto-generated by IntelliJ\n\nOur ports and adapters implementation has four modules: App, Domain, Ports, Adapters.\n\nBoth ‘Domain’ and ‘Adapters’ depend on ‘Ports’. ‘Domain’ and ‘Adapters’ cannot see each other. ‘App’ can see all the modules.\n\n### What Goes Where?\n\n#### Domain\n\nThe centre of the hexagon. Contains core business logic and the domain model. Importantly, contains no references to transport concerns like JSON, specific persistence technologies or _time._ Yes, time. `DateTime.now()` is an anti-pattern at the domain layer because it complicates testing and creates a degree of temporal coupling. Pass in dates and timestamps from the adapter layer if you need them.\n\n#### Adapters\n\nEverything outside the hexagon. Nothing related to business logic. Will contain things like JSON transformers, REST end-points, message handlers, event publishers, database repositories, scheduled events, and so forth\n\n#### Ports\n\nThe ports module contains interfaces and DTOs (which will be Kotlin data classes in our case). It should have no actual logic and therefore not really need any tests. There are varying ways people arrange and name their ports, but the structure I like is to subdivide into two categories: Required and Provided.\n\n**Required** ports are required by the ‘domain’ for the application to function. Hence they are i_mplemented by the adapter module_. Repositories, event publishers and API clients might be accessed through ‘required’ ports.\n\n**Provided** ports are provided by ‘domain’ for use by the adapter layer. Hence they are _implemented by the domain module_. Service classes called from your controllers, event handlers and scheduled tasks are the most typical examples of ‘provided’ ports.\n\n#### App\n\nThe ‘app’ module binds everything together and configures the framework being used to run the service. In this case it loads Guice modules and configures Ktor.\n\n### The guided tour:\n\n#### Domain logic\n\nThere’s not much in our toy domain. Just a `SimpleGreeter` that implements our `Greeter` interface (a ‘provided’ port) and is injected with a `GreetingsRepository` (a ‘required’ port).\n\nTesting this is easy, we can just mock the repository. In general when testing ‘domain’ we want to mock out the ‘adapter’ implementations. As an aside, I prefer using kotlintest assertions with JUnit5 and Mockito-kotlin.\n\n#### Adapter layer\n\nThe most interesting thing about the adapter layer is how to ‘inject’ domain services into Ktor routes. The first step is to assume we can inject our Ktor `Application` along with any ‘provided’ services and write a simple class that sets up the routes.\n\nYou can see above that once we inject the application class you can initiate the ktor routing DSL as per normal. We can also have multiple classes setting up routing. Effectively this lets our ‘route’ classes play the same role a Controller would in, say, a SpringMVC application.\n\nThe next step is to setup the rest of ktor, such as exception handling and content transformers. We do this in `ApplicationConfig.kt`\n\nThe final step is to create a Guice module that binds the application for injecting, then feeds it into the route and config classes. The key here is to use `asEagerSingleton` when binding the configuration and the routes. As the Javadoc says, “_Useful for application initialization logic”_\n\n#### Writing adapter tests\n\nThis is where things get interesting. When we write ‘domain’ tests we don’t need to worry about much plumbing or wiring. Adapter tests, however, are where you probably want to write some integration tests. Given our hexagonal architecture, we’re looking for a way to start a test Ktor application but wire in mocks for all the domain services.\n\nIn our toy example we don’t have a ‘real’ database, so we can write integration-like tests to demonstrate the concepts without actually needing to integrate Docker or similar to provide external dependencies.\n\n**Step 1: Create mocks for our core services**\n\nThere’s only one in our template, but it illustrates the point.\n\n**Step 2: Create a Guice injector**\n\nOn line 3 above we inject the **_real_** Adapter Module. This means we can test the actual-factual routes with confidence. We also inject our mocked domain services.\n\nThe `MainModule` here lets us inject our test application into the adapter module.\n\nAlso note that the `module` function on line 2 above is an extension function off Application.\n\n**Step 3: Setup/TearDown methods to create a test application**\n\nLine 6 above we use the Ktor testkit to create a test environment.\n\nLine 10 wires up the test application with our routes and mocks by calling the extension method from Step 2.\n\nLine 12 injects the test class itself with anything in the Guice context so that we can wire mocks up into our tests, as we shall see in the next step.\n\n**Step 4: Write a test**\n\nIn this step we subclass our test base to call a ktor route.\n\nWorth calling out here is that on lines 4/5 we inject the mocked domain service into our test class.\n\nLine 17 demonstrates a simple way to test a ktor route.\n\nThis adapter integration test gives us confidence that:\n\n1. The route works\n2. The service was called\n3. The HTTP call returned the expected status and content (so, for example, we could check JSON marshaling and unmarshaling was working)\n\n#### Wiring up the application\n\nOur ‘app’ module can see both ‘domain’ and ‘adapters’ and is responsible for wiring everything up and launching the application. There’s not much in here except for the actual main module and an entry point.\n\nHowever — if you feel compelled to write a true end-to-end integration test against a real running service — this is the module to do it in.\n\nI’m not sure if you should, though. If you trust the framework, and trust that your ‘layer crossing tests’ give you sufficient coverage that the adapters are calling the domain the right way and vice-versa, you can get away without needing to write any of these tests.\n\nOn the other hand, one or two ‘sanity tests’ that execute as part of an integration test phase probably wouldn’t hurt too much. You can find an [example](https://github.com/sgerber-hyperanna/ktor-hexagonal-multi-module-template/blob/master/app/src/test/kotlin/ApplicationTest.kt) in the GitHub repository, but there is not much to learn from reviewing a code-snippet here. It is very similar in appearance to the Adapter test. Just less setup, because everything is real.\n\n### And all the rest …\n\nWell that’s end of our tour! There is a little more to see if you care to explore the repository. You can see examples of how we managed to hack together a multi-module project with the Kotlin DSL. You can also see how we integrated some simple JWT authentication into our end-points.\n\nNow I realize that the amount of setup code and Gradle configuration drastically dwarfs the amount of actual application code in this toy application. This may understandably lead you feel that it’s all more hassle than it’s worth.\n\nI take your point, and I agree. But my counter-argument is that ports and adapters as an architectural style, as a _discipline_, really didn’t click for me until I’d built a couple of services with it and seen how cleanly, how beautifully, everything fell together. Please do give it a go, even if you are not feeling totally convinced.\n\nIf you happen to be using Kotlin and ktor, I hope this tutorial is of direct benefit! Most of this was figured out from scratch with little detailed knowledge of ktor or Kotlin. There might be better ways to achieve the same goals! Discussions and pull-requests against the service template in GitHub are welcome. If you are not currently using Kotlin, I hope it at least gives some insight into how you might organize your chosen technology stack into a ports and adapters structure.