Generation Model

tapik generation starts from compiled endpoint contracts and produces only the outputs you explicitly enable.

Today that workflow is exposed through the Gradle task tapikGenerate.

What the task does

When you run tapikGenerate, tapik:

  1. scans compiled classes under the configured basePackage,

  2. discovers concrete API implementations,

  3. resolves their HttpEndpoint declarations into metadata,

  4. writes an endpoint scan report,

  5. invokes the enabled generators found on the classpath.

This matters because generators are not reading stale source docs or handwritten config. They are operating on the contract the code actually compiled to.

Built-in generators

Generator Module Output Enabled by

Spring RestClient client generator

dev.akif.tapik:spring-restclient

Generated Kotlin client interfaces

tapik { springRestClient { } }

Spring Web MVC server generator

dev.akif.tapik:spring-webmvc

Generated Kotlin server interfaces

tapik { springWebMvc { } }

Markdown documentation generator

dev.akif.tapik:common-plugin

API.md endpoint summary

tapik { markdownDocumentation { } }

Where generated files go

tapik writes to two output roots:

  • build/generated/sources/tapik/main/kotlin for generated Kotlin sources,

  • build/generated for non-source outputs such as API.md and tapik-endpoints.txt.

Generated Kotlin sources are added to the main Kotlin source set automatically by the Gradle plugin.

Naming controls

The root tapik extension controls the common naming surface:

tapik {
    basePackage("com.acme.catalog")
    generatedPackageName("generated")
    endpointsSuffix("Endpoints")

    springRestClient {
        clientSuffix("Client")
    }

    springWebMvc {
        serverSuffix("Server")
    }
}

Those settings affect:

  • which package segment generated Kotlin files use,

  • the name of the generated endpoint container interface,

  • the aggregate client and server interface names.

How extension works

tapik generators are discovered with Java ServiceLoader.

That keeps the extension boundary straightforward:

  • Kotlin generators can contribute generated endpoint contract members,

  • direct generators can write other artifacts such as Markdown,

  • other client, server, and documentation targets can be added without changing how endpoint discovery works.

A minimal direct generator looks like this:

package com.acme.tapik

import dev.akif.tapik.plugin.TapikDirectGenerator
import dev.akif.tapik.plugin.TapikGeneratorContext
import dev.akif.tapik.plugin.metadata.HttpEndpointMetadata
import java.io.File

class EndpointCountGenerator : TapikDirectGenerator {
    override val id: String = "endpoint-count"

    override fun generate(
        endpoints: List<HttpEndpointMetadata>,
        context: TapikGeneratorContext
    ): Set<File> {
        val output = context.outputDirectory.resolve("endpoint-count.txt")
        output.writeText(endpoints.size.toString())
        return setOf(output)
    }
}

Then register it under META-INF/services/dev.akif.tapik.plugin.TapikGenerator:

com.acme.tapik.EndpointCountGenerator

Once that module is on the classpath, tapik can discover it through ServiceLoader just like the built-in generators.

For the built-in outputs, continue with: