Create and publish OpenAPI Java clients using Gradle and Maven S3

Create and publish OpenAPI Java clients using Gradle and Maven S3

Many teams use OpenAPI to document and consume API services. Using OpenAPI tools we can generate strongly typed clients in a wide range of languages. We can then call other services without needing to maintain type definitions in multiple projects. With Gradle and Spring we can automate the generation and publication of Swagger codegen clients and distribute the packages via AWS S3. This will give us a private artifact repository that we can connect to in calling services.

Annotate your API endpoints

The first step in automating your API client generation is to annotate your API endpoints and generate an OpenAPI spec. In Spring we can use springdoc-openapi to describe our endpoints. In a build.gradle.kt file add:

dependencies {
    implementation("org.springdoc:springdoc-openapi-ui:1.6.11")
}

Then add annotations to your controllers:

@Operation(operationId = "deleteJob", summary = "Delete a scheduled job")
@ResponseStatus(HttpStatus.NO_CONTENT)
@DeleteMapping("/jobs/{groupId}/{jobId}")
fun deleteJob(@PathVariable("groupId") groupId: String, @PathVariable("jobId") jobId: String) {
    schedulerFactory.scheduler.deleteJob(JobKey.jobKey(groupId, jobId))
}

Generate an openapi.json spec

Next we can use gradle to generate a spec:

plugins {
	id("org.springdoc.openapi-gradle-plugin") version "1.4.0"
	id("org.openapi.generator") version "6.1.0"
}

Define a custom openApi task to start Spring and write the OpenAPI spec to the build directory.

openApi {
    customBootRun {
        args.set(listOf("--spring.profiles.active=openapi"))
    }
}

When we run ./gradlew generateOpenApiDocs an openapi.json file will be written to the build directory.

{
  "paths": {
    "/jobs/{groupId}/{jobId}": {
      "delete": {
        "tags": [
          "api-controller"
        ],
        "operationId": "deleteJob",
        "parameters": [
          {
            "name": "groupId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        }
      }
    }
  }
}

Generate a client

Now we can generate an OpenAPI client using a gradle task:

openApiGenerate {
	generatorName.set("java")
	version.set(System.getenv("CLIENT_VERSION"))
	id.set("yourid")
	groupId.set("yourgroup")
	inputSpec.set("$buildDir/openapi.json")
	outputDir.set("$buildDir/client")
	configOptions.set(mapOf(
		"dateLibrary" to "java8"
	))
}

Run the command like so ./gradlew openApiGenerate to write a client into the build/client directory. Next we will publish the client to maven via S3.

Create a maven S3 repository

Create an S3 bucket to use as your maven repository.

aws s3 mb s3://my.private.maven

Now we can publish to S3 with Gradle.

Publish to S3 using Gradle

We can now use a gradle init script to patch the generated gradle client and add a publishing method for our S3 bucket.

// for patching the generated client
// run in build/client with `./gradlew --init-script init-client.gradle publish`
allprojects {
    apply plugin: 'java'
    apply plugin: 'maven-publish'
    publishing {
        publications {
            mavenJava(MavenPublication) {
                from components.java
            }
        }
        repositories {
            maven {
                url "s3://my.private.maven"
                authentication {
                    awsIm(AwsImAuthentication)
                }
            }
        }
    }
}

Then to run:

cp init-client.gradle build/client/init-client.gradle
cd build/client && ./gradlew --init-script init.gradle publish && cd -

Voila

After this we have shown how to describe your API, generate a client, and publish to S3.

Ready to dive in?Start building email applications today.