How to Integrate CoApi into Spring Boot Applications: A Step-by-Step Guide

Integrate CoApi into your Spring Boot applications by adding the coapi-spring-boot-starter dependency, annotating your main class with @EnableCoApi, defining HTTP interfaces with @CoApi, and injecting the generated clients as Spring beans.

CoApi is a zero-boilerplate auto-configuration library for Spring 6's HTTP Interface that lets you declare remote APIs as plain Kotlin or Java interfaces. This guide walks you through integrating CoApi (ahoo-wang/coapi) into existing Spring Boot applications to create type-safe, reactive or synchronous HTTP clients without writing implementation code.

Step 1: Add the CoApi Starter Dependency

Add the coapi-spring-boot-starter to your build configuration to pull in the necessary auto-configuration beans.

Gradle (Kotlin DSL):

implementation("me.ahoo.coapi:coapi-spring-boot-starter")

Gradle (Groovy DSL):

implementation 'me.ahoo.coapi:coapi-spring-boot-starter'

Maven:

<dependency>
    <groupId>me.ahoo.coapi</groupId>
    <artifactId>coapi-spring-boot-starter</artifactId>
    <version>${coapi.version}</version>
</dependency>

Step 2: Enable CoApi Auto-Configuration

Annotate your @SpringBootApplication or a @Configuration class with @EnableCoApi to trigger the auto-configuration mechanism. According to the source code in spring/src/main/kotlin/me/ahoo/coapi/spring/EnableCoApi.kt, this annotation imports EnableCoApiRegistrar, which scans the clients attribute and registers a CoApiDefinition for each interface.

import me.ahoo.coapi.spring.EnableCoApi
import org.springframework.boot.autoconfigure.SpringBootApplication

@EnableCoApi(clients = [GitHubApiClient::class, TodoClient::class])
@SpringBootApplication
class MyApplication

If you omit the clients attribute, Spring will scan for interfaces annotated with @CoApi automatically.

Step 3: Define a CoApi Interface

Create an interface annotated with @CoApi (or Spring's generic @HttpExchange) to declare your remote API. The CoApiDefinition.kt file handles the metadata extraction from these annotations, supporting both baseUrl configuration and serviceId for load balancing.

import me.ahoo.coapi.spring.CoApi
import org.springframework.web.service.annotation.GetExchange
import org.springframework.web.bind.annotation.PathVariable
import reactor.core.publisher.Flux

@CoApi(baseUrl = "\${github.url}")
interface GitHubApiClient {

    @GetExchange("repos/{owner}/{repo}/issues")
    fun getIssues(@PathVariable owner: String,
                  @PathVariable repo: String): Flux<Issue>
}

Configure the base URL in your application.yml:

github:
  url: https://api.github.com

Step 4: Inject and Use the Generated Client

Spring automatically creates a bean implementation of your interface. Simply constructor-inject it and call methods as if they were local service calls. The example/example-consumer-server/src/main/kotlin/me/ahoo/coapi/example/consumer/ConsumerServer.kt file demonstrates this pattern in practice.

import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController

@RestController
class GithubController(private val gitHubApiClient: GitHubApiClient) {

    @GetMapping("/issues")
    fun listIssues() = gitHubApiClient.getIssues("Ahoo-Wang", "CoApi")
}

How CoApi Works Behind the Scenes

The integration relies on two core components that handle client registration and mode selection.

AbstractCoApiRegistrar determines whether to create a reactive or synchronous client by reading the coapi.client-mode property (default is reactive). It then registers the appropriate HttpExchangeAdapterFactory—either ReactiveHttpExchangeAdapterFactory or SyncHttpExchangeAdapterFactory. This logic is implemented in spring/src/main/kotlin/me/ahoo/coapi/spring/AbstractCoApiRegistrar.kt.

CoApiDefinition holds the metadata for each client, including baseUrl and serviceId, derived from the @CoApi annotation and the Spring Environment. The registrar creates a bean definition for each interface based on this metadata, as defined in spring/src/main/kotlin/me/ahoo/coapi/spring/CoApiDefinition.kt.

Optional: Configure Load Balancing

To integrate with Spring Cloud LoadBalancer, specify a serviceId instead of a hardcoded URL:

@CoApi(serviceId = "github-service")
interface LoadBalancedGitHubClient {
    @GetExchange("repos/{owner}/{repo}/issues")
    fun getIssues(@PathVariable owner: String,
                  @PathVariable repo: String): Flux<Issue>
}

Add the LoadBalancer starter to your dependencies:

implementation("org.springframework.cloud:spring-cloud-starter-loadbalancer")

CoApi will now resolve the service via Spring Cloud LoadBalancer using the logical service name.

Summary

  • Add coapi-spring-boot-starter to your build file to enable auto-configuration.
  • Use @EnableCoApi on your main application class to trigger the registration process handled by EnableCoApiRegistrar.
  • Define HTTP clients as interfaces with @CoApi, specifying either baseUrl or serviceId.
  • Inject the generated beans directly into your controllers or services.
  • Configure coapi.client-mode to switch between reactive (default) and synchronous execution.
  • Enable Spring Cloud LoadBalancer support by adding the load balancer starter and using service IDs.

Frequently Asked Questions

What is the difference between CoApi and Spring's standard HTTP Interface?

CoApi provides zero-boilerplate auto-configuration for Spring 6's HTTP Interface. While Spring requires manual HttpServiceProxyFactory configuration, CoApi automatically registers client implementations as beans through AbstractCoApiRegistrar when you use @EnableCoApi, eliminating the need for explicit proxy creation.

How do I switch between reactive and synchronous client modes?

Set the coapi.client-mode property in your application.yml to sync or reactive. The default is reactive. The AbstractCoApiRegistrar reads this property and instantiates either SyncHttpExchangeAdapterFactory or ReactiveHttpExchangeAdapterFactory accordingly.

Can I use CoApi with Spring Cloud LoadBalancer?

Yes. Specify serviceId in your @CoApi annotation instead of baseUrl, and include spring-cloud-starter-loadbalancer in your dependencies. CoApi automatically integrates with Spring Cloud LoadBalancer to resolve logical service names to physical endpoints.

Which Spring Boot versions support CoApi?

CoApi supports Spring Boot 3.2+ for the current stable line. For CoApi 2.x releases, Spring Boot 4.x (when available) will be the target platform. Check the repository's compatibility matrix for specific version requirements.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →