Generate a Server

The server generator targets Spring Web MVC.

Use it when you want Spring controller interfaces to stay aligned with the same tapik contract that also drives clients and documentation.

Use dev.akif.tapik:spring-webmvc to enable it.

Enable the generator

dependencies {
    implementation("dev.akif.tapik:spring-webmvc:<version>")
}

tapik {
    springWebMvc { }
}

If you want a different generated suffix:

tapik {
    springWebMvc {
        serverSuffix("Api")
    }
}

What gets generated

The generator contributes Kotlin source files under:

  • build/generated/sources/tapik/main/kotlin/<package>/…​

For each source file of endpoint declarations, tapik generates:

  • an aggregate server interface such as CatalogApiServer,

  • one nested server contract per endpoint,

  • one generated response model per endpoint.

interface CatalogApiServer : CatalogApiEndpoints.GetProduct.Server

interface CatalogApiEndpoints {
    interface GetProduct {
        sealed class Response(open val status: Status) {
            data class Ok(
                val body: ProductView
            ) : Response(Status.Ok)

            data class NotFound(
                val body: ProblemDetails
            ) : Response(Status.NotFound)
        }

        interface Server {
            @org.springframework.web.bind.annotation.GetMapping(path = ["/api/v1/products/{productId}"])
            fun getProduct(
                @org.springframework.web.bind.annotation.PathVariable(name = "productId") productId: String,
                @org.springframework.web.bind.annotation.RequestHeader(name = "X-Request-Id") xRequestId: java.util.UUID
            ): Response
        }
    }
}

The exact generated code varies with the contract, but the behavior is consistent:

  • method and path come from the endpoint definition,

  • query parameters, headers, and request bodies map to the matching Spring annotations,

  • multi-output endpoints keep distinct response variants.

How Spring mapping is derived

The generator uses the endpoint contract to choose the mapping form:

  • standard verbs such as GET and POST use the corresponding Spring mapping annotations,

  • nonstandard verbs such as HEAD fall back to @RequestMapping with an explicit request method,

  • media types come from the declared input and output bodies,

  • fixed response headers and typed bodies are reflected in the generated response model.

Implement the generated contract

Your application still owns the controller implementation:

@org.springframework.web.bind.annotation.RestController
class CatalogController : CatalogApiServer {
    override fun getProduct(
        productId: String,
        xRequestId: java.util.UUID
    ): CatalogApiEndpoints.GetProduct.Response = TODO()
}

This keeps the transport contract generated while leaving your business logic, persistence, and orchestration code handwritten.

Boundaries

The server generator does not:

  • register controllers for you,

  • implement endpoint logic,

  • turn tapik into a full Spring application framework.

It generates the transport-facing interface and response model. Your application provides the actual behavior.