{"id":16179147,"url":"https://github.com/jonashackt/spring-boot-openapi-kong","last_synced_at":"2025-03-16T10:31:35.183Z","repository":{"id":37023149,"uuid":"309600471","full_name":"jonashackt/spring-boot-openapi-kong","owner":"jonashackt","description":"Example project showing how to integrate Spring Boot microservices with Kong API Gateway","archived":false,"fork":false,"pushed_at":"2025-02-21T19:47:27.000Z","size":2571,"stargazers_count":26,"open_issues_count":8,"forks_count":16,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-02-21T20:31:57.801Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://blog.codecentric.de/en/2020/11/spring-boot-kong/","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jonashackt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-11-03T06:58:23.000Z","updated_at":"2024-12-20T19:27:00.000Z","dependencies_parsed_at":"2023-02-12T18:30:33.417Z","dependency_job_id":"437dea16-9ff0-4f17-baf8-6bbf54221121","html_url":"https://github.com/jonashackt/spring-boot-openapi-kong","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonashackt%2Fspring-boot-openapi-kong","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonashackt%2Fspring-boot-openapi-kong/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonashackt%2Fspring-boot-openapi-kong/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonashackt%2Fspring-boot-openapi-kong/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jonashackt","download_url":"https://codeload.github.com/jonashackt/spring-boot-openapi-kong/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243810861,"owners_count":20351602,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-10T05:25:37.363Z","updated_at":"2025-03-16T10:31:34.699Z","avatar_url":"https://github.com/jonashackt.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# spring-boot-openapi-kong\n\n[![Build Status](https://github.com/jonashackt/spring-boot-openapi-kong/workflows/openapi-to-kong-config-full-setup/badge.svg)](https://github.com/jonashackt/spring-boot-openapi-kong/actions)\n[![License](http://img.shields.io/:license-mit-blue.svg)](https://github.com/jonashackt/spring-boot-buildpack/blob/master/LICENSE)\n[![renovateenabled](https://img.shields.io/badge/renovate-enabled-yellow)](https://renovatebot.com)\n[![versionspringboot](https://img.shields.io/badge/dynamic/xml?color=brightgreen\u0026url=https://raw.githubusercontent.com/jonashackt/spring-boot-openapi-kong/main/weatherbackend/pom.xml\u0026query=%2F%2A%5Blocal-name%28%29%3D%27project%27%5D%2F%2A%5Blocal-name%28%29%3D%27parent%27%5D%2F%2A%5Blocal-name%28%29%3D%27version%27%5D\u0026label=springboot)](https://github.com/spring-projects/spring-boot)\n\n\nExample project showing how to integrate Spring Boot microservices with Kong API Gateway\n\n[![asciicast](https://asciinema.org/a/370557.svg)](https://asciinema.org/a/370557)\n\nBringing together Kong \u0026 Spring Boot. But wait, what is https://github.com/Kong/kong ?\n\n\u003e Kong is a cloud-native, fast, scalable, and distributed Microservice Abstraction Layer (also known as an API Gateway or API Middleware). \n\nThis project is also used as sample for this article:\nhttps://blog.codecentric.de/en/2020/11/spring-boot-kong \n\n## Table of Contents \n\n* [Idea \u0026 Setup](#idea--setup)\n* [Step by step...](#step-by-step)\n  * [The current problem with springdoc-openapi and WebFlux based Spring Boot apps](#the-current-problem-with-springdoc-openapi-and-webflux-based-spring-boot-apps)\n  * [Create a Spring Boot App with REST endpoints](#create-a-spring-boot-app-with-rest-endpoints)\n  * [Generate an OpenAPI spec with the springdoc-openapi-maven-plugin](#generate-an-openapi-spec-with-the-springdoc-openapi-maven-plugin)\n  * [Tweak the API information in the generated OpenAPI spec](#tweak-the-api-information-in-the-generated-openapi-spec)\n* [Import OpenAPI spec into Kong](#import-openapi-spec-into-kong)\n  * [Install Insomnia Desinger with Kong Bundle plugin](#install-insomnia-desinger-with-kong-bundle-plugin)\n  * [Import Springdoc generated openapi.json into Insomnia Designer](#import-springdoc-generated-openapijson-into-insomnia-designer)\n  * [Generate Kong Declarative Config from Openapi](#generate-kong-declarative-config-from-openapi)\n* [Docker Compose with Kong DB-less deployment \u0026 declarative configuration](#docker-compose-with-kong-db-less-deployment--declarative-configuration)\n* [Access the Spring Boot app through Kong](#access-the-spring-boot-app-through-kong)\n  * [Configuring the correct upstream in Kong (connect() failed (111: Connection refused) while connecting to upstream)](#configuring-the-correct-upstream-in-kong-connect-failed-111-connection-refused-while-connecting-to-upstream)\n* [Automating the OpenAPI-Kong import](#automating-the-openapi-kong-import)\n  * [Install Inso CLI](#install-inso-cli)\n  * [Inso CLI install problems on Mac](#inso-cli-install-problems-on-mac)\n  * [Use Inso CLI to generate Kong declarative config from OpenAPI spec](#use-inso-cli-to-generate-kong-declarative-config-from-openapi-spec)\n  * [Run the OpenAPI spec generation and Kong declarative config transformation inside the Maven build](#run-the-openapi-spec-generation-and-kong-declarative-config-transformation-inside-the-maven-build)\n  * [Integrate the full Maven build into Cloud CI](#integrate-the-full-maven-build-into-cloud-ci)\n  * [Fire up our Kong Docker Compose setup \u0026 testdrive the Spring Boot service access](#fire-up-our-kong-docker-compose-setup--testdrive-the-spring-boot-service-access)\n* [Links](#links)\n\n\n\n### Idea \u0026 Setup\n\nSome microservices to access with Kong... I once worked heavily with the Spring Cloud Netflix tooling.\n\nHere's the example project: https://github.com/jonashackt/cxf-spring-cloud-netflix-docker and the blog post I wrote back then https://blog.codecentric.de/en/2017/05/ansible-docker-windows-containers-scaling-spring-cloud-netflix-docker-compose\n\nThe goal is to rebuild the project using Kong https://github.com/Kong/kong\n\n\nagnostical! more pattern like\n\nSetup idea: Spring Boot REST --\u003e [generate OpenAPI spec yamls via springdoc-openapi-maven-plugin](https://www.baeldung.com/spring-rest-openapi-documentation) --\u003e Insomnia: Kong config file with [Kong Bundle plugin](https://insomnia.rest/plugins/insomnia-plugin-kong-bundle/) --\u003e import into Kong and run via decK (normal Kong gateway without EE)\n\nNothing really there right now:  https://www.google.com/search?q=openapi+spring+boot+kong\n\n* No change in Spring Boot dev workflow required, no custom annotations\n* elegant integration of Kong and Spring Boot services\n\nPLUS: CI process to regularly generate OpenAPI specs from Spring code -\u003e and automatically import into Kong, which is an enterprise feature - or it is possible via:\n\n\n\n\n## Step by step...\n\n\n### The current problem with springdoc-openapi and WebFlux based Spring Boot apps\n\nWhy didn't I go with a reactive WebFlux based app? \n\nWebFlux based Spring Boot Apps need some `springdoc-openapi` specific classes right now in order to fully generate the OpenAPI live documentation in the end. See the demos at\n\nhttps://github.com/springdoc/springdoc-openapi-demos\n\nAnd especially the webflux functional demo at: https://github.com/springdoc/springdoc-openapi-demos/blob/master/springdoc-openapi-spring-boot-2-webflux-functional where these imports are used:\n\n```java\nimport static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder;\nimport static org.springdoc.core.fn.builders.parameter.Builder.parameterBuilder;\nimport static org.springdoc.webflux.core.fn.SpringdocRouteBuilder.route;\n```\n\nI can't fully discourage to go with this approach, but for this project I wanted a 100% \"springdoc-free\" standard Spring Boot app, where the springdoc feature are __ONLY__ used to generate OpenAPI specs - and not rely onto some dependencies from springdoc. Since that would imply that every Spring Boot project that wanted to adopt the solution outlined here would need to integrate springdoc classes in their projects.\n\n\n\n### Create a Spring Boot App with REST endpoints\n\nThis is the easy part. We all know where to start: Go to start.spring.io and create a Spring REST app skeleton.\n\nAs I wanted to rebuild my good old Spring Cloud Netflix / Eureka based apps, I simply took the `weatherbackend` app from https://github.com/jonashackt/cxf-spring-cloud-netflix-docker/tree/master/weatherbackend\n\nHere's the [WeatherBackendAPI.java](weatherbackend/src/main/java/io/jonashackt/weatherbackend/api/WeatherBackendAPI.java) - nothing special here:\n\n```java\npackage io.jonashackt.weatherbackend.api;\n\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport io.jonashackt.weatherbackend.businesslogic.IncredibleLogic;\nimport io.jonashackt.weatherbackend.model.*;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.web.bind.annotation.*;\n\n@RestController\n@RequestMapping(\"/weather\")\npublic class WeatherBackendAPI {\n\n    private static final Logger LOG = LoggerFactory.getLogger(WeatherBackendController.class);\n\n    @PostMapping(value = \"/general/outlook\", produces = \"application/json\")\n    public @ResponseBody GeneralOutlook generateGeneralOutlook(@RequestBody Weather weather) throws JsonProcessingException {\n        ...\n        return outlook;\n    }\n\n    @GetMapping(value = \"/general/outlook\", produces = \"application/json\")\n    public @ResponseBody String infoAboutGeneralOutlook() throws JsonProcessingException {\n        ...\n        return \"Try a POST also against this URL! Just send some body with it like: '\" + weatherJson + \"'\";\n    }\n\n    @GetMapping(value = \"/{name}\", produces = \"text/plain\")\n    public String whatsTheSenseInThat(@PathVariable(\"name\") String name) {\n        LOG.info(\"Request for /{name} with GET\");\n        return \"Hello \" + name + \"! This is a RESTful HttpService written in Spring. :)\";\n    }\n}\n```\n\n\n\n### Generate an OpenAPI spec with the springdoc-openapi-maven-plugin\n\nSee the docs at https://github.com/springdoc/springdoc-openapi-maven-plugin on how to use the springdoc-openapi-maven-plugin.\n\n\u003e The aim of springdoc-openapi-maven-plugin is to generate json and yaml OpenAPI description during build time. The plugin works during integration-tests phase, and generates the OpenAPI description. The plugin works in conjunction with spring-boot-maven plugin.\n\nBut in order to successfully run the springdoc-openapi-maven-plugin, we need to add the [springdoc-openapi-ui](https://github.com/springdoc/springdoc-openapi) plugin (for Tomcat / Spring MVC based apps) or the [springdoc-openapi-webflux-ui](https://github.com/springdoc/springdoc-openapi#spring-webflux-support-with-annotated-controllers) plugin (for Reactive WebFlux / Netty based apps) to our [weatherbackend/pom.xml](hellobackend/pom.xml):\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eorg.springdoc\u003c/groupId\u003e\n    \u003cartifactId\u003espringdoc-openapi-ui\u003c/artifactId\u003e\n    \u003cversion\u003e1.4.8\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nOtherwise the `springdoc-openapi-maven-plugin` will run into errors like this (as described [in this so answer](https://stackoverflow.com/a/64677754/4964553)):\n\n```\n[INFO] --- springdoc-openapi-maven-plugin:1.1:generate (default) @ hellobackend ---\n[ERROR] An error has occured: Response code 404\n[INFO]\n[INFO] --- spring-boot-maven-plugin:2.3.5.RELEASE:stop (post-integration-test) @ hellobackend ---\n[INFO] Stopping application...\n2020-11-04 10:18:36.851  INFO 42036 --- [on(4)-127.0.0.1] inMXBeanRegistrar$SpringApplicationAdmin : Application shutdown requested.\n```\n\nAs a sidenote: if you fire up your Spring Boot app from here with `mvn spring-boot:run`, you can access the live API documentation already at http://localhost:8080/swagger-ui.html\n\n![openapi-swagger-ui](screenshots/openapi-swagger-ui.png)\n\nNow we can add the `springdoc-openapi-maven-plugin` to our [hellobackend/pom.xml](hellobackend/pom.xml):\n\n```xml\n\t\u003cbuild\u003e\n\t\t\u003cplugins\u003e\n\t\t\t\u003cplugin\u003e\n\t\t\t\t\u003cgroupId\u003eorg.springframework.boot\u003c/groupId\u003e\n\t\t\t\t\u003cartifactId\u003espring-boot-maven-plugin\u003c/artifactId\u003e\n\t\t\t\t\u003cexecutions\u003e\n\t\t\t\t\t\u003cexecution\u003e\n\t\t\t\t\t\t\u003cid\u003epre-integration-test\u003c/id\u003e\n\t\t\t\t\t\t\u003cgoals\u003e\n\t\t\t\t\t\t\t\u003cgoal\u003estart\u003c/goal\u003e\n\t\t\t\t\t\t\u003c/goals\u003e\n\t\t\t\t\t\u003c/execution\u003e\n\t\t\t\t\t\u003cexecution\u003e\n\t\t\t\t\t\t\u003cid\u003epost-integration-test\u003c/id\u003e\n\t\t\t\t\t\t\u003cgoals\u003e\n\t\t\t\t\t\t\t\u003cgoal\u003estop\u003c/goal\u003e\n\t\t\t\t\t\t\u003c/goals\u003e\n\t\t\t\t\t\u003c/execution\u003e\n\t\t\t\t\u003c/executions\u003e\n\t\t\t\u003c/plugin\u003e\n\t\t\t\u003cplugin\u003e\n\t\t\t\t\u003cgroupId\u003eorg.springdoc\u003c/groupId\u003e\n\t\t\t\t\u003cartifactId\u003espringdoc-openapi-maven-plugin\u003c/artifactId\u003e\n\t\t\t\t\u003cversion\u003e1.1\u003c/version\u003e\n\t\t\t\t\u003cexecutions\u003e\n\t\t\t\t\t\u003cexecution\u003e\n\t\t\t\t\t\t\u003cphase\u003eintegration-test\u003c/phase\u003e\n\t\t\t\t\t\t\u003cgoals\u003e\n\t\t\t\t\t\t\t\u003cgoal\u003egenerate\u003c/goal\u003e\n\t\t\t\t\t\t\u003c/goals\u003e\n\t\t\t\t\t\u003c/execution\u003e\n\t\t\t\t\u003c/executions\u003e\n\t\t\t\u003c/plugin\u003e\n\t\t\u003c/plugins\u003e\n\t\u003c/build\u003e\n``` \n\nAs you see we also need to tell the `spring-boot-maven-plugin` to start and stop the integration test phases.\n\nIn order to generate the Open API spec we need to execute Maven with:\n\n```\nmvn verify\n```\n\nThe output should contain something like that:\n\n```\n...\n[INFO] --- springdoc-openapi-maven-plugin:1.1:generate (default) @ hellobackend ---\n2020-11-04 10:26:09.579  INFO 42143 --- [ctor-http-nio-2] o.springdoc.api.AbstractOpenApiResource  : Init duration for springdoc-openapi is: 29 ms\n...\n```\n\nThis indicates that the OpenAPI spec generation was successful. Therefore we need to have a look into the `weatherbackend/target` directory, where a file called [openapi.json](weatherbackend/target/openapi.json) should be present now (you may need to reformat the code inside you IDE to not look into a one-liner ;) ):\n\n```json\n{\n  \"openapi\": \"3.0.1\",\n  \"info\": {\n    \"title\": \"OpenAPI definition\",\n    \"version\": \"v0\"\n  },\n  \"servers\": [\n    {\n      \"url\": \"http://localhost:8080\",\n      \"description\": \"Generated server url\"\n    }\n  ],\n  \"paths\": {\n    \"/weather/general/outlook\": {\n      \"get\": {\n        \"tags\": [\n          \"weather-backend-controller\"\n        ],\n        \"operationId\": \"infoAboutGeneralOutlook\",\n        \"responses\": {\n          \"200\": {\n            \"description\": \"OK\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"type\": \"string\"\n                }\n              }\n            }\n          }\n        }\n      }\n}}}\n```\n\n### Tweak the API information in the generated OpenAPI spec\n\nI really don't wanted to change much here in the first place. But as I came into more details regarding the Kong integration, I wanted to configure at least some information in the generated `openapi.json`.\n\nEspecially the `\"title\": \"OpenAPI definition\"`, which is then used as the Kong service name, should be optimized :)\n\nTherefore we can [use the @OpenAPIDefinition annotation](https://github.com/springdoc/springdoc-openapi#adding-api-information-and-security-documentation) to configure the service info.\n\nSo let's create a class [OpenAPIConfig.java](weatherbackend/src/main/java/io/jonashackt/weatherbackend/api/OpenAPIConfig.java) and specify some info:\n\n```java\npackage io.jonashackt.weatherbackend.api;\n\nimport io.swagger.v3.oas.annotations.OpenAPIDefinition;\nimport io.swagger.v3.oas.annotations.info.Info;\nimport io.swagger.v3.oas.annotations.servers.Server;\n\n@OpenAPIDefinition(\n        info = @Info(\n                title = \"weatherbackend\",\n                version = \"v2.0\"\n        ),\n        servers = @Server(url = \"http://weatherbackend:8080\")\n)\npublic class OpenAPIConfig {\n}\n```\n\nWith that we can generate our `openapi.json` again by running `mvn verify -DskipTests=true` and should have the new information propagated:\n\n```json\n{\n  \"openapi\": \"3.0.1\",\n  \"info\": {\n    \"title\": \"weatherbackend\",\n    \"version\": \"v2.0\"\n  },\n  \"servers\": [\n    {\n      \"url\": \"http://weatherbackend:8080\",\n      \"variables\": {}\n    }\n  ],\n  \"paths\": {\n    \"/weather/general/outlook\": {\n      \"get\": {\n        \"tags\": [\n          \"weather-backend-api\"\n        ],\n        \"operationId\": \"infoAboutGeneralOutlook\",\n        \"responses\": {\n          \"200\": {\n            \"description\": \"OK\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"type\": \"string\"\n                }\n              }\n            }\n          }\n        }\n      },\n```\n\n\n### Import OpenAPI spec into Kong\n\nFirst we start the manual process in order to test drive our solution.\n\n### Install Insomnia Desinger with Kong Bundle plugin\n\nOn a Mac simply use brew (or have a look at https://insomnia.rest):\n\n```\nbrew cask install insomnia-designer\n```\n\nThen go to https://insomnia.rest/plugins/insomnia-plugin-kong-bundle and click on `Install in Designer` \u0026 open the request in Insomnia Desinger:\n\n![insomnia-designer-kong-bundle-plugin](screenshots/insomnia-designer-kong-bundle-plugin.png)\n\n\n### Import Springdoc generated openapi.json into Insomnia Designer\n\nNow let's try to import the generated [openapi.json](weatherbackend/target/openapi.json) into our Insomnia Designer by clicking on `Create` and then `Import from / File`:\n\n![insomnia-designer-import-openapi-json](screenshots/insomnia-designer-import-openapi-json.png)\n\nThat was easy :) Now you can already interact with your API through Insomnia.\n\n\n\n### Generate Kong Declarative Config from Openapi\n\nThe next step is to generate the Kong configuration from the OpenAPI specification. Therefore we need to click on the `Generate Config` button:\n\n![insomnia-designer-kong-declarative-config](screenshots/insomnia-designer-kong-declarative-config.png)\n\nAnd voilà we have our Kong declarative configuration ready:\n\n```yaml\n_format_version: \"1.1\"\nservices:\n  - name: weatherbackend\n    url: http://weatherbackend:8080\n    plugins: []\n    routes:\n      - tags:\n          - OAS3_import\n        name: weatherbackend-path-get\n        methods:\n          - GET\n        paths:\n          - /weather/general/outlook\n        strip_path: false\n      - tags:\n          - OAS3_import\n        name: weatherbackend-path_1-post\n        methods:\n          - POST\n        paths:\n          - /weather/general/outlook\n        strip_path: false\n      - tags:\n          - OAS3_import\n        name: weatherbackend-path_2-get\n        methods:\n          - GET\n        paths:\n          - /weather/(?\u003cname\u003e\\S+)$\n        strip_path: false\n    tags:\n      - OAS3_import\nupstreams:\n  - name: weatherbackend\n    targets:\n      - target: weatherbackend:8080\n    tags:\n      - OAS3_import\n```\n\nFor now let's save this yaml inside the [kong/kong.yml](kong/kong.yml) file.\n\n\n\n\n### Docker Compose with Kong DB-less deployment \u0026 declarative configuration\n\nI have two goals here: First I want a simple deployment solution. If I could avoid it then I don't want to have multiple services only for the API gateway. I want to start small and you as a reader should be able to easily follow.\n\nAs [the official Docker Compose file](https://github.com/Kong/docker-kong/blob/master/compose/docker-compose.yml) has two (!!) database migration services, one database service and one service for Kong I was really overwhelmed at first.\n\nWhat I learned in my years in the IT industry: Every component you don't have is a good component. So there must be a way to deploy Kong without that much \"hassle\". And I found one:\n\n \nThe documentation at https://docs.konghq.com/2.2.x/db-less-and-declarative-config/ \u0026 https://docs.konghq.com/install/docker says, that DB-less mode is possible since Kong 1.1 and has a number of benefits:\n\n* reduced number of dependencies: no need to manage a database installation if the entire setup for your use-cases fits in memory\n* it is a good fit for automation in CI/CD scenarios: configuration for entities can be kept in a single source of truth managed via a Git repository\n* it enables more deployment options for Kong\n\nBut be aware that are also some drawbacks. [Not all plugins support this mode]https://docs.konghq.com/2.2.x/db-less-and-declarative-config/#plugin-compatibility) and [there is no central configuration database](https://docs.konghq.com/2.2.x/db-less-and-declarative-config/#no-central-database-coordination) if you want to run multiple Kong nodes. But for our simple setup we should be able to live with that. \n\n\nBut there's another advantage: we don't need to use [decK](https://github.com/Kong/deck) here as my colleague [already outlined](https://blog.codecentric.de/en/2019/12/kong-api-gateway-declarative-configuration-using-deck-and-visualizations-with-konga/) is used with Kong for declarative config handling.\n\nThis is only needed, if you use Kong with a Database deployment! If you choose the DB-less/declarative configuration approach, your declarative file is already everything we need! :)\n\n\n\nSo let's do it. I'll try to setup the simplest possible `docker-compose.yml` here in order to spin up Kong. I'll derive it [from the official one](https://github.com/Kong/docker-kong/blob/master/compose/docker-compose.yml), the one my colleague Daniel Kocot [used in his blog posts](https://github.com/danielkocot/kong-blogposts/blob/master/docker-compose.yml) and others [like this](https://medium.com/@matias_azucas/db-less-kong-tutorial-8cbf8f70b266). \n\n```yaml\nversion: '3.7'\n\nservices:\n  kong:\n    image: kong:2.2.0\n    environment:\n      KONG_ADMIN_ACCESS_LOG: /dev/stdout\n      KONG_ADMIN_ERROR_LOG: /dev/stderr\n      KONG_ADMIN_LISTEN: '0.0.0.0:8001'\n      KONG_DATABASE: \"off\"\n      KONG_DECLARATIVE_CONFIG: /usr/local/kong/declarative/kong.yml\n      KONG_PROXY_ACCESS_LOG: /dev/stdout\n      KONG_PROXY_ERROR_LOG: /dev/stderr\n    volumes:\n      - ./kong/:/usr/local/kong/declarative\n    networks:\n      - kong-net\n    ports:\n      - \"8000:8000/tcp\"\n      - \"127.0.0.1:8001:8001/tcp\"\n      - \"8443:8443/tcp\"\n      - \"127.0.0.1:8444:8444/tcp\"\n    healthcheck:\n      test: [\"CMD\", \"kong\", \"health\"]\n      interval: 10s\n      timeout: 10s\n      retries: 10\n    restart: on-failure\n    deploy:\n      restart_policy:\n        condition: on-failure\n\n  # no portbinding here - the actual services should be accessible through Kong\n  weatherbackend:\n    build: ./weatherbackend\n    ports:\n      - \"8080\"\n    networks:\n      - kong-net\n    tty:\n      true\n    restart:\n      unless-stopped\n\nnetworks:\n  kong-net:\n    external: false\n```\n\nI litterally blew everything out we don't really really need in a DB-less scenario! No `kong-migrations`, `kong-migrations-up`, `kong-db` services - and no extra `Dockerfile` [as shown in this blog post](https://medium.com/@matias_azucas/db-less-kong-tutorial-8cbf8f70b266).\n\nI only wanted to have a single `kong` service for the API gateway - and a `weatherbackend` service that is registered in Kong later.\n\nAs stated [in the docs for DB-less deployment](https://docs.konghq.com/install/docker/?_ga=2.266755086.1634614376.1604405282-930789398.1604405282) I used `KONG_DATABASE: \"off\"` to switch to DB-less mode and `KONG_DECLARATIVE_CONFIG: /usr/local/kong/declarative/kong.yml` to tell Kong where to get the `kong.yml` we generated with the Insomnia Designer's Kong Bungle plugin.\nTo have the file present at `/usr/local/kong/declarative/kong.yml`, I used a simple volume mount like this: `./kong/:/usr/local/kong/declarative`. No need to manually create the Volume as described in the docs - or to create another Dockerfile solely to load the config file into the Kong container. Simply nothing needed instead of this sweet volume!\n\nNow this thing starts to make fun to me :)\n\n \nNow let's fire up our Kong setup with `docker-compose up`\n\n```\n$ docker-compose up\nStarting spring-boot-openapi-kong_kong_1           ... done\nStarting spring-boot-openapi-kong_weatherbackend_1 ... done\nAttaching to spring-boot-openapi-kong_weatherbackend_1, spring-boot-openapi-kong_kong_1\nkong_1            | 2020/11/04 14:21:11 [notice] 1#0: using the \"epoll\" event method\nkong_1            | 2020/11/04 14:21:11 [notice] 1#0: openresty/1.17.8.2\nkong_1            | 2020/11/04 14:21:11 [notice] 1#0: built by gcc 9.3.0 (Alpine 9.3.0)\nkong_1            | 2020/11/04 14:21:11 [notice] 1#0: OS: Linux 5.4.39-linuxkit\nkong_1            | 2020/11/04 14:21:11 [notice] 1#0: getrlimit(RLIMIT_NOFILE): 1048576:1048576\nkong_1            | 2020/11/04 14:21:11 [notice] 1#0: start worker processes\nkong_1            | 2020/11/04 14:21:11 [notice] 1#0: start worker process 22\nkong_1            | 2020/11/04 14:21:11 [notice] 1#0: start worker process 23\nkong_1            | 2020/11/04 14:21:11 [notice] 1#0: start worker process 24\nkong_1            | 2020/11/04 14:21:11 [notice] 1#0: start worker process 25\nkong_1            | 2020/11/04 14:21:11 [notice] 23#0: *2 [lua] cache.lua:374: purge(): [DB cache] purging (local) cache, context: init_worker_by_lua*\nkong_1            | 2020/11/04 14:21:11 [notice] 23#0: *2 [lua] cache.lua:374: purge(): [DB cache] purging (local) cache, context: init_worker_by_lua*\nkong_1            | 2020/11/04 14:21:11 [notice] 23#0: *2 [kong] init.lua:354 declarative config loaded from /usr/local/kong/declarative/kong.yml, context: init_worker_by_lua*\nweatherbackend_1  |\nweatherbackend_1  |   .   ____          _            __ _ _\nweatherbackend_1  |  /\\\\ / ___'_ __ _ _(_)_ __  __ _ \\ \\ \\ \\\nweatherbackend_1  | ( ( )\\___ | '_ | '_| | '_ \\/ _` | \\ \\ \\ \\\nweatherbackend_1  |  \\\\/  ___)| |_)| | | | | || (_| |  ) ) ) )\nweatherbackend_1  |   '  |____| .__|_| |_|_| |_\\__, | / / / /\nweatherbackend_1  |  =========|_|==============|___/=/_/_/_/\nweatherbackend_1  |  :: Spring Boot ::        (v2.3.5.RELEASE)\nweatherbackend_1  |\nweatherbackend_1  | 2020-11-04 14:21:13.226  INFO 6 --- [           main] io.jonashackt.weatherbackend.WeatherBackendApplication  : Starting WeatherBackendApplication v2.3.5.RELEASE on 209e8a7cbb36 with PID 6 (/app.jar started by root in /)\nweatherbackend_1  | 2020-11-04 14:21:13.239  INFO 6 --- [           main] io.jonashackt.weatherbackend.WeatherBackendApplication  : No active profile set, falling back to default profiles: default\nweatherbackend_1  | 2020-11-04 14:21:15.920  INFO 6 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)\nweatherbackend_1  | 2020-11-04 14:21:15.958  INFO 6 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]\nweatherbackend_1  | 2020-11-04 14:21:15.960  INFO 6 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.39]\nweatherbackend_1  | 2020-11-04 14:21:16.159  INFO 6 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext\nweatherbackend_1  | 2020-11-04 14:21:16.163  INFO 6 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2714 ms\nweatherbackend_1  | 2020-11-04 14:21:16.813  INFO 6 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'\nweatherbackend_1  | 2020-11-04 14:21:18.534  INFO 6 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''\nweatherbackend_1  | 2020-11-04 14:21:18.564  INFO 6 --- [           main] io.jonashackt.weatherbackend.WeatherBackendApplication  : Started WeatherBackendApplication in 7.188 seconds (JVM running for 8.611)\nkong_1            | 172.19.0.1 - - [04/Nov/2020:14:25:16 +0000] \"GET / HTTP/1.1\" 404 48 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:82.0) Gecko/20100101 Firefox/82.0\"\n```\n\nA crucial part here is that Kong successfully loads the declarative configuration file and logs something like `[kong] init.lua:354 declarative config loaded from /usr/local/kong/declarative/kong.yml`\n\n\nIf your log looks somehow like the above you can also have a look at the admin API by opening http://localhost:8001/ in your browser. [As the docs state](https://docs.konghq.com/2.2.x/db-less-and-declarative-config/#setting-up-kong-in-db-less-mode) everything should be ok, if the response says `\"database\": \"off\"` somewhere like:\n\n![docker-compose-db-less-deploy-database-off](screenshots/docker-compose-db-less-deploy-database-off.png)  \n\nWe can also double check http://localhost:8001/status , where we have a good overview of Kong's current availability.\n\n\n\n### Access the Spring Boot app through Kong\n\nThe next thing we need to look at is how to access our `weatherbackend` through Kong. Specifically we need to have a look into the configured Kong services, if the OpenAPI spec import worked out in the way we'd expected it in the first place.\n\nWithout using Kong's declarative configuration [we need to add services and routes manually through the Kong admin API](https://blog.codecentric.de/en/2019/09/api-management-kong-update/). But as we use declarative configuration, which we generated from the OpenAPI spec, everything is taken care for us already.\n\n\nTherefore let's have a look into the list of all currently registered Kong services at http://localhost:8001/services \n\n![kong-admin-api-services-overview](screenshots/kong-admin-api-services-overview.png)\n\nYou can also access the Kong routes of our Spring Boot-backed service with this URL:\n\nhttp://localhost:8001/services/weatherbackend/routes\n\n\n\n### Configuring the correct upstream in Kong (connect() failed (111: Connection refused) while connecting to upstream)\n\nIf you run into problems like this:\n\n```\nkong_1            | 2020/11/04 18:56:05 [error] 24#0: *14486 connect() failed (111: Connection refused) while connecting to upstream, client: 172.19.0.1, server: kong, request: \"GET /weather/Jonas HTTP/1.1\", upstream: \"http://127.0.0.1:8080/weather/Jonas\", host: \"localhost:8000\"\nkong_1            | 2020/11/04 18:56:05 [error] 24#0: *14486 connect() failed (111: Connection refused) while connecting to upstream, client: 172.19.0.1, server: kong, request: \"GET /weather/Jonas HTTP/1.1\", upstream: \"http://127.0.0.1:8080/weather/Jonas\", host: \"localhost:8000\"\nkong_1            | 172.19.0.1 - - [04/Nov/2020:18:56:05 +0000] \"GET /weather/Jonas HTTP/1.1\" 502 75 \"-\" \"insomnia/2020.4.2\"\n```\n\nwe should have a look at the `upstreams` configuration of our generated Kong declarative config:\n\n```yaml\nupstreams:\n  - name: weatherbackend\n    targets:\n      - target: localhost:8080\n    tags:\n      - OAS3_import\n```\n\nAs with our setup here Kong needs to access the weatherbackend from within the Docker network. So the `upstreams: target` to `localhost` will not work and lead to the error `connect() failed (111: Connection refused) while connecting to upstream`.\n\nSo we need to think about a working `host` configuration. [Daniel did the trick](https://blog.codecentric.de/en/2019/09/api-management-kong-update/) to simply use `host.docker.internal` as host name in his post and I also remember it from my last work with Traefik.\n\nComing from this solution I thought about my [post about the Spring Cloud microservice setup](https://blog.codecentric.de/en/2017/05/ansible-docker-windows-containers-scaling-spring-cloud-netflix-docker-compose) back in 2017: There I simply used the Docker (Compose) service names, which I aligned with the names of the microservices.\n\nSo having a look into our [docker-compose.yml](docker-compose.yml) it would be easy to simply use `weatherbackend` as the host name, since that one should be also available inside the Docker network. And: We can enrich this later by using a DNS resolver and so on...\n\nIn order to configure another host name inside Kong, we need to tweak our [OpenAPIConfig.java](weatherbackend/src/main/java/io/jonashackt/weatherbackend/api/OpenAPIConfig.java) with another configuration option called `servers`:\n\n```java\n@OpenAPIDefinition(\n        info = @Info(\n                title = \"weatherbackend\",\n                version = \"v2.0\"\n        ),\n        servers = @Server(url = \"http://weatherbackend:8080\")\n)\npublic class OpenAPIConfig {\n}\n```    \n\nNow doing the OpenAPI spec and Kong declarative config generation again, our setup should come up with a working configuration to access our Spring Boot service through Kong!\n\n\nFinally we can use Postman, Insomnia Core or the like to access our Spring Boot app with a GET on http://localhost:8000/weather/MaxTheKongUser\n\n![service-access-postman-success](screenshots/service-access-postman-success.png)\n\nLooking into our Docker Compose log we should also see the successful responses from our `weatherbackend` service:\n\n```shell script\nweatherbackend_1  | 2020-11-05 07:54:48.381  INFO 7 --- [nio-8080-exec-1] i.j.controller.WeatherBackendController  : Request for /{name} with GET\nkong_1            | 172.19.0.1 - - [05/Nov/2020:07:54:48 +0000] \"GET /weather/MaxTheKongUser HTTP/1.1\" 200 133 \"-\" \"PostmanRuntime/7.26.1\"\nweatherbackend_1  | 2020-11-05 07:54:59.951  INFO 7 --- [nio-8080-exec-2] i.j.controller.WeatherBackendController  : Request for /{name} with GET\nkong_1            | 172.19.0.1 - - [05/Nov/2020:07:54:59 +0000] \"GET /weather/MonicaTheKongUser HTTP/1.1\" 200 136 \"-\" \"PostmanRuntime/7.26.1\"\nweatherbackend_1  | 2020-11-05 07:55:06.573  INFO 7 --- [nio-8080-exec-3] i.j.controller.WeatherBackendController  : Request for /{name} with GET\nkong_1            | 172.19.0.1 - - [05/Nov/2020:07:55:06 +0000] \"GET /weather/MartinTheKongUser HTTP/1.1\" 200 136 \"-\" \"PostmanRuntime/7.26.1\"\n``` \n\n\n\n### Automating the OpenAPI-Kong import\n\nWe need to also import the OpenAPI spec everytime the code changes, since otherwise the configuration in Kong will differ with every commit!\n\nAdditionally we want to be able to run our process on our CI servers as well, since we're in 2020 and want to be sure everything runs even after code changes.\n\nAnd there's a way maybe: Inso CLI https://github.com/Kong/insomnia/tree/develop/packages/insomnia-inso\n\nBecause there we have a [openapi-2-kong functionality](https://github.com/Kong/insomnia/tree/develop/packages/insomnia-inso#-inso-generate-config-identifier) - see also https://www.npmjs.com/package/openapi-2-kong:\n\n\u003e Similar to the Kong Kubernetes and Declarative config plugins for Designer, this command can generate configuration from an API specification, using openapi-2-kong.\n\n\n### Install Inso CLI\n\nSo let's try Inso CLI! (did I say that this starting to get really cool :D )\n\nInstall it with:\n\n```shell script\nnpm i -g insomnia-inso\n```\n\n#### Inso CLI install problems on Mac\n\nI ran into the following error\n\n```\nnode-pre-gyp WARN Using request for node-pre-gyp https download\n  CXX(target) Release/obj.target/node_libcurl/src/node_libcurl.o\nclang: error: no such file or directory: '/usr/include'\n```\n\nThis is a problem, since [MacOS command line tools do not add `/usr/include` folder by default anymore](https://stackoverflow.com/questions/64694248/node-libcurl-installation-fails-on-macos-catalina-clang-error-no-such-file-or/64694249#64694249) (OMG!).\n\nIn order to fix that problem, you need to install `node_libcurl` (which has the above problem and is needed by insomnia-inso) first and use the environment variable `npm_config_curl_include_dirs` to show the installation process the new location of `/usr/include` which is `$(xcrun --show-sdk-path)/usr/include`. The command must also include `insomnia-inso`:\n\n```\nnpm_config_curl_include_dirs=\"$(xcrun --show-sdk-path)/usr/include\" npm install -g node-libcurl insomnia-inso\n```\n\n### Use Inso CLI to generate Kong declarative config from OpenAPI spec\n\nAs we want to go from `openapi.json` to `kong.yml`, we need to [use the `inso generate config` command as described in the docs](https://github.com/Kong/insomnia/tree/develop/packages/insomnia-inso#-inso-generate-config-identifier).\n\nWe should also use option `--type declarative`, since the output should result in a Kong declarative configuration file.\n\nAlso our OpenAPI spec file at `weatherbackend/target/openapi.json` could be directly passed to Inso CLI. \n\nThe last part is to tell Inso where to output the Kong declarative configuration `--output kong/kong.yml`.\n\n```\ninso generate config weatherbackend/target/openapi.json --output kong/kong.yml --type declarative --verbose\n```\n\nIf you want to see a bit more of an info what the inso CLI is doing, you can add `--verbose` to the command.\n\nIf your node/npm installation is broken like mine, you can add the `node_modules/insomnia-inso/bin` directly to your `.bash_profile`, `.zshrc` etc. like that:\n\n```\nexport PATH=\"/usr/local/Cellar/node/15.1.0/lib/node_modules/insomnia-inso/bin:$PATH\"\n```\n\n\n### Run the OpenAPI spec generation and Kong declarative config transformation inside the Maven build\n\nEverytime we change our Spring Boot app's code, we should initialize a re-generation of our Kong declarative config in our `kong.yml` file, since the API could have changed!\n\nPlaying with different possibilities where to put the generation (Docker, Compose, CI server) I found a really simple solution to bind the step to our standard build process:\n\nI just used the [exec-maven-plugin](https://www.mojohaus.org/exec-maven-plugin/usage.html) to execute the `inso CLI`. Although the XML syntax may look a bit strange at first sight,\nit makes totally sense to have the generation of our `kong.yml` also directly coupled to our build process. Therefore let's have a look at our [weatherbackend/pom.xml](weatherbackend/pom.xml):\n\n```xml\n\t\t\t\u003cplugin\u003e\n\t\t\t\t\u003cgroupId\u003eorg.codehaus.mojo\u003c/groupId\u003e\n\t\t\t\t\u003cartifactId\u003eexec-maven-plugin\u003c/artifactId\u003e\n\t\t\t\t\u003cversion\u003e3.0.0\u003c/version\u003e\n\t\t\t\t\u003cexecutions\u003e\n\t\t\t\t\t\u003cexecution\u003e\n\t\t\t\t\t\t\u003cid\u003eexecute-inso-cli\u003c/id\u003e\n\t\t\t\t\t\t\u003cphase\u003everify\u003c/phase\u003e\n\t\t\t\t\t\t\u003cgoals\u003e\n\t\t\t\t\t\t\t\u003cgoal\u003eexec\u003c/goal\u003e\n\t\t\t\t\t\t\u003c/goals\u003e\n\t\t\t\t\t\u003c/execution\u003e\n\t\t\t\t\u003c/executions\u003e\n\t\t\t\t\u003cconfiguration\u003e\n\t\t\t\t\t\u003cexecutable\u003einso\u003c/executable\u003e\n\t\t\t\t\t\u003carguments\u003e\n\t\t\t\t\t\t\u003cargument\u003egenerate\u003c/argument\u003e\n\t\t\t\t\t\t\u003cargument\u003econfig\u003c/argument\u003e\n\t\t\t\t\t\t\u003cargument\u003etarget/openapi.json\u003c/argument\u003e\n\t\t\t\t\t\t\u003cargument\u003e--output\u003c/argument\u003e\n\t\t\t\t\t\t\u003cargument\u003e../kong/kong.yml\u003c/argument\u003e\n\t\t\t\t\t\t\u003cargument\u003e--type\u003c/argument\u003e\n\t\t\t\t\t\t\u003cargument\u003edeclarative\u003c/argument\u003e\n                        \u003cargument\u003e--verbose\u003c/argument\u003e\n\t\t\t\t\t\u003c/arguments\u003e\n\t\t\t\t\u003c/configuration\u003e\n\t\t\t\u003c/plugin\u003e\n```\n\nUsing `mvn exec:exec` we are now able to execute `inso CLI` through Maven:\n\n```\n$ mvn exec:exec\n[INFO] Scanning for projects...\n[INFO]\n[INFO] ------------\u003c io.jonashackt.weatherbackend:weatherbackend \u003e-------------\n[INFO] Building weatherbackend 2.3.5.RELEASE\n[INFO] --------------------------------[ jar ]---------------------------------\n[INFO]\n[INFO] --- exec-maven-plugin:3.0.0:exec (default-cli) @ weatherbackend ---\nConfiguration generated to \"kong/kong.yml\".\n[INFO] ------------------------------------------------------------------------\n[INFO] BUILD SUCCESS\n[INFO] ------------------------------------------------------------------------\n[INFO] Total time:  1.671 s\n[INFO] Finished at: 2020-11-05T14:05:04+01:00\n[INFO] ------------------------------------------------------------------------\n```\n\nAs you can see the `inso CLI` logging `Configuration generated to \"kong/kong.yml\".` is part of the output.\n\nAnd we can push the integration into our build process even further: As [mentioned from Pascal at stackoverflow](https://stackoverflow.com/a/2472767/4964553) we can even bind the execution of the `exec-maven-plugin` to the standard Maven build.\n\nUsing the `\u003cphase\u003e` tag we bind the execution to the `verify` phase, where the generation of the OpenAPI spec also takes place already:\n\n```xml\n\u003cexecutions\u003e\n    \u003cexecution\u003e\n        \u003cid\u003eexecute-inso-cli\u003c/id\u003e\n        \u003cphase\u003everify\u003c/phase\u003e\n        \u003cgoals\u003e\n            \u003cgoal\u003eexec\u003c/goal\u003e\n        \u003c/goals\u003e\n    \u003c/execution\u003e\n\u003c/executions\u003e\n```\n\nThis is marvelous since with this addition a normal `mvn verify` does every needed step for us to generate a Kong declarative config file at [kong/kong.yml](kong/kong.yml)! \n\n```shell script\n$ mvn verify\n...\n[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 3.822 s - in io.jonashackt.weatherbackend.api.WeatherBackendAPITests\n2020-11-05 14:07:49.261  INFO 66585 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'\n[INFO]\n[INFO] Results:\n[INFO]\n[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0\n[INFO]\n[INFO]\n[INFO] --- maven-jar-plugin:3.2.0:jar (default-jar) @ weatherbackend ---\n[INFO] Building jar: /Users/jonashecht/dev/spring-boot/spring-boot-openapi-kong/weatherbackend/target/weatherbackend-2.3.5.RELEASE.jar\n[INFO]\n[INFO] --- spring-boot-maven-plugin:2.3.5.RELEASE:repackage (repackage) @ weatherbackend ---\n[INFO] Replacing main artifact with repackaged archive\n[INFO]\n[INFO] --- spring-boot-maven-plugin:2.3.5.RELEASE:start (pre-integration-test) @ weatherbackend ---\n[INFO] Attaching agents: []\n\n  .   ____          _            __ _ _\n /\\\\ / ___'_ __ _ _(_)_ __  __ _ \\ \\ \\ \\\n( ( )\\___ | '_ | '_| | '_ \\/ _` | \\ \\ \\ \\\n \\\\/  ___)| |_)| | | | | || (_| |  ) ) ) )\n  '  |____| .__|_| |_|_| |_\\__, | / / / /\n =========|_|==============|___/=/_/_/_/\n :: Spring Boot ::        (v2.3.5.RELEASE)\n\n2020-11-05 14:07:50.978  INFO 66597 --- [           main] i.j.w.WeatherBackendApplication          : Starting WeatherBackendApplication on PikeBook.fritz.box with PID 66597 (/Users/jonashecht/dev/spring-boot/spring-boot-openapi-kong/weatherbackend/target/classes started by jonashecht in /Users/jonashecht/dev/spring-boot/spring-boot-openapi-kong/weatherbackend)\n2020-11-05 14:07:50.981  INFO 66597 --- [           main] i.j.w.WeatherBackendApplication          : No active profile set, falling back to default profiles: default\n2020-11-05 14:07:51.657  INFO 66597 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)\n2020-11-05 14:07:51.665  INFO 66597 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]\n2020-11-05 14:07:51.665  INFO 66597 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.39]\n2020-11-05 14:07:51.735  INFO 66597 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext\n2020-11-05 14:07:51.736  INFO 66597 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 715 ms\n2020-11-05 14:07:51.889  INFO 66597 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'\n2020-11-05 14:07:52.292  INFO 66597 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''\n2020-11-05 14:07:52.300  INFO 66597 --- [           main] i.j.w.WeatherBackendApplication          : Started WeatherBackendApplication in 1.585 seconds (JVM running for 1.978)\n[INFO]\n[INFO] --- springdoc-openapi-maven-plugin:1.1:generate (default) @ weatherbackend ---\n2020-11-05 14:07:52.764  INFO 66597 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'\n2020-11-05 14:07:52.764  INFO 66597 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'\n2020-11-05 14:07:52.768  INFO 66597 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 4 ms\n2020-11-05 14:07:52.936  INFO 66597 --- [nio-8080-exec-1] o.springdoc.api.AbstractOpenApiResource  : Init duration for springdoc-openapi is: 148 ms\n[INFO]\n[INFO] --- spring-boot-maven-plugin:2.3.5.RELEASE:stop (post-integration-test) @ weatherbackend ---\n[INFO] Stopping application...\n2020-11-05 14:07:52.989  INFO 66597 --- [on(4)-127.0.0.1] inMXBeanRegistrar$SpringApplicationAdmin : Application shutdown requested.\n2020-11-05 14:07:53.052  INFO 66597 --- [on(4)-127.0.0.1] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'\n[INFO]\n[INFO] --- exec-maven-plugin:3.0.0:exec (execute-inso-cli) @ weatherbackend ---\nConfiguration generated to \"../kong/kong.yml\".\n[INFO] ------------------------------------------------------------------------\n[INFO] BUILD SUCCESS\n[INFO] ------------------------------------------------------------------------\n[INFO] Total time:  11.185 s\n[INFO] Finished at: 2020-11-05T14:07:54+01:00\n[INFO] ------------------------------------------------------------------------\n```\n\nWith that our Spring Boot app is build \u0026 tested, then the `openapi.json` gets generated using the `springdoc-openapi-maven-plugin` and then transformed into `kong.yml` by the `Inso CLI` executed by the `exec-maven-plugin` :))) \n\n\n### Integrate the full Maven build into Cloud CI\n\nAs we want to make sure everything works as expected every time code changes we need to include the build into a CI system.\n\nNow that we depend on `Inso CLI` installation, which depends on Node.js/NPM and Maven at the same time, we need go with a very flexible CloudCI solution.\n\nAs we probably also need Docker Compose on our CI system I decided to go with GitHub Actions since here we have a full-blown virtual machine to do everything we want.\n\nSo let's create a [.github/workflows/openapi-to-kong-config-full-setup.yml](.github/workflows/openapi-to-kong-config-full-setup.yml) to execute our Maven build (and don't forget to add `--no-transfer-progress` to the Maven command, since otherwise our build logs get polluted with downloads):\n\n```yaml\nname: openapi-to-kong-config-full-setup\n\non: [push]\n\njobs:\n  build:\n\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions/checkout@v2\n\n      - name: Install Node/npm for Inso\n        uses: actions/setup-node@v2\n        with:\n          node-version: '14'\n\n      - name: Install Java \u0026 Maven\n        uses: actions/setup-java@v1\n        with:\n          java-version: 15\n\n      - name: Install Inso and run Maven build, that'll generate OpenAPI spec and Kong declarative config later needed for Docker Compose\n        run: |\n          echo \"Install insomnia-inso (Inso CLI) which is needed by our Maven build process later\"\n          npm install insomnia-inso\n\n          echo \"Show Inso version\"\n          node_modules/insomnia-inso/bin/inso --version\n\n          echo \"Build Spring Boot app with Maven\"\n          echo \"This also generates OpenAPI spec file at weatherbackend/target/openapi.json and the Kong declarative config at kong/kong.yml from the OpenAPI spec with Inso CLI\"\n          mvn clean verify --file weatherbackend/pom.xml --no-transfer-progress -Dinso.executable.path=node_modules/insomnia-inso/bin/inso\n```\n\nI also ran into another problem. GitHub Actions couldn't find the `inso` executable (see this build) and produced the following error:\n\n```\nERROR] Failed to execute goal org.codehaus.mojo:exec-maven-plugin:3.0.0:exec (execute-inso-cli) on project weatherbackend: Command execution failed.: Cannot run program \"inso\" (in directory \"/home/travis/build/jonashackt/spring-boot-openapi-kong/weatherbackend\"): error=2, No such file or directory -\u003e [Help 1]\n```\n\nSo I thought about directly defining the full path to the `inso` executable inside our Maven build. But using the `exec-maven-plugin` - and not the command line directly - this isn't that easy anymore.\n\nBut maybe we can define a default - and override it on Travis? I looked [at this so q\u0026a](https://stackoverflow.com/questions/34746347/pom-xml-environment-variable-with-default-fallback) and finally [at this answer](https://stackoverflow.com/a/13709976/4964553).\n\nSo let's try it! We alter our [weatherbackend/pom.xml](weatherbackend/pom.xml) slightly to use a new property called `${inso.executable.path}`:\n\n```xml\n\u003cproperties\u003e\n    ...\n    \u003cinso.executable.path\u003einso\u003c/inso.executable.path\u003e\n\u003c/properties\u003e\n...\n\u003cplugin\u003e\n    \u003cgroupId\u003eorg.codehaus.mojo\u003c/groupId\u003e\n    \u003cartifactId\u003eexec-maven-plugin\u003c/artifactId\u003e\n    \u003cversion\u003e3.0.0\u003c/version\u003e\n...\n    \u003cconfiguration\u003e\n        \u003cexecutable\u003e${inso.executable.path}\u003c/executable\u003e\n        \u003carguments\u003e\n...\n```\n\nWith this change we should be able to run our normal `mvn verify` locally - and a special `mvn verify -DskipTests=true -Dinso.executable.path=inso-special-path` on GitHub Actions like this:\n\n```\nmvn clean verify --file weatherbackend/pom.xml --no-transfer-progress -Dinso.executable.path=node_modules/insomnia-inso/bin/inso\n```\n\nNow [our build works like a charm](https://travis-ci.com/github/jonashackt/spring-boot-openapi-kong/builds/198466347) :)\n\nAt the end we also look into the generated [kong/kong.yml](kong/kong.yml):\n\n```yaml\n  echo \"Show kong.yml\"\n  cat kong/kong.yml\n```\n\n\n### Fire up our Kong Docker Compose setup \u0026 testdrive the Spring Boot service access\n\nAs we only start Kong through Docker Compose, we should finally ensure, that every `docker-compose up` starts with the latest API definition!\n\nTherefore it would be great to initialize a Maven build every time we fire up our Compose setup.\n\nAs we now have a CI server, we can also use it to fire up our Compose setup every time the full chain was build and generated!\n\nAll we have to do here is to fire up our setup - and curl Kong with the correct service path. So let's add both to our [.github/workflows/openapi-to-kong-config-full-setup.yml](.github/workflows/openapi-to-kong-config-full-setup.yml):\n\n```yaml\n    - name: Fire up Docker Compose setup with Kong \u0026 do some checks\n      run: |\n        docker-compose up -d\n\n        echo \"Let's wait until Kong is available (we need to improve this)\"\n        sleep 10\n\n        echo \"Also have a look into the Kong \u0026 Spring Boot app logs\"\n        docker ps -a\n        docker-compose logs kong\n        docker-compose logs weatherbackend\n\n        echo \"Have a look at the /services endpoint of Kong's admin API\"\n        curl http://localhost:8001/services\n\n        echo \"Verify that we can call our Spring Boot service through Kong\"\n        curl http://localhost:8000/weather/MaxTheKongUser\n\n        echo \"Again look into Kong logs to see the service call\"\n        docker-compose logs kong\n```\n\nRight after starting `docker-compose up` we need to wait for the containers to spin up. Currently [I use `sleep` here](https://stackoverflow.com/a/47439672/4964553) - it's dead simply, but it works right now :)\n\nWe then also have a look into the Kong \u0026 Spring Boot app logs with `docker-compose logs kong` \u0026 `docker-compose logs weatherbackend`.\n\nAfter checking the service admin API with `curl http://localhost:8001/services` we finally curl for our service through Kong with `curl http://localhost:8000/weather/MaxTheKongUser`. \n\n\n\n## Links\n\nhttps://blog.codecentric.de/en/2017/11/api-management-kong/\n\nhttps://docs.konghq.com/hub/\n\n\n#### Spring \u0026 OpenAPI\n\nhttps://github.com/springdoc/springdoc-openapi-maven-plugin\n\nhttps://stackoverflow.com/questions/59616165/what-is-the-function-of-springdoc-openapi-maven-plugin-configuration-apidocsurl\n\nhttps://www.baeldung.com/spring-rest-openapi-documentation\n\n\n#### Insomnia (Core) \u0026 Insomia Designer\n\n\u003e Insomnia (Core) is a graphical REST client - just like postman\n\nhttps://blog.codecentric.de/2020/02/testen-und-debuggen-mit-insomnia/\n\nSince 2019 Insomnia (Core) is part of Kong - and is the basis for Kong Studio (Enterprise)\n\nhttps://github.com/Kong/insomnia\n\n\n\u003e Insomnia Designer is a OpenAPI / Swagger Desktop App\n\nhttps://blog.codecentric.de/en/2020/06/introduction-to-insomnia-designer/\n\n\u003e you can preview your specification using Swagger UI\n\nhttps://medium.com/@rmharrison/an-honest-review-of-insomnia-designer-and-insomnia-core-62e24a447ce\n\n\nWith https://insomnia.rest/plugins/insomnia-plugin-kong-bundle/ you can deploy API definitions into Kong API gateway\n\nTo see the integration in action, have a look on https://blog.codecentric.de/en/2020/09/offloading-and-more-from-reedelk-data-integration-services-through-kong-enterprise/ \n\nhttps://github.com/codecentric/reedelk-bookingintegrationservice\n\n\n\n\n#### decK\n\n\u003e declarative configuration and drift detection for Kong\n\nhttps://blog.codecentric.de/en/2019/12/kong-api-gateway-declarative-configuration-using-deck-and-visualizations-with-konga/\n\nhttps://github.com/Kong/deck\n\n\n\n#### Deployment incl. Konga\n\nOfficial Kong docker-compose template: https://github.com/Kong/docker-kong/blob/master/compose/docker-compose.yml\n\nhttps://blog.codecentric.de/en/2019/09/api-management-kong-update/\n\nhttps://github.com/danielkocot/kong-blogposts/blob/master/docker-compose.yml\n\n\nFirst question: What is this `kong-migration` Docker container about? [Daniel answers it](https://blog.codecentric.de/en/2019/09/api-management-kong-update/):\n\n\u003e the kong-migration service is used for the initial generation of the objects in the kong-database. Unfortunately, the configuration of the database is not managed by the kong service.\n\n\n\nIdea: Database-less deployment possible for showcases?\n\n\n\n\u003e Konga: graphical dashboard\n\nhttps://github.com/pantsel/konga#running-konga\n\nhttps://blog.codecentric.de/en/2019/12/kong-api-gateway-declarative-configuration-using-deck-and-visualizations-with-konga/\n\nKonga with it's own DB: https://github.com/asyrjasalo/kongpose/blob/master/docker-compose.yml\n\nKonga on the same DB as Kong: https://github.com/abrahamjoc/docker-compose-kong-konga/blob/master/docker-compose.yml\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonashackt%2Fspring-boot-openapi-kong","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjonashackt%2Fspring-boot-openapi-kong","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonashackt%2Fspring-boot-openapi-kong/lists"}