This guide covers adding a new external API integration (e.g., Stripe, Twilio, GitHub API).
In backend/pom.xml add the client library or use Spring's RestClient:
<dependency>
<groupId>com.example</groupId>
<artifactId>example-client</artifactId>
<version>1.0.0</version>
</dependency>Or use Spring's built-in RestClient (no extra dependency needed).
Add settings to application.yaml:
integration:
example-api:
base-url: ${EXAMPLE_API_URL:https://api.example.com}
api-key: ${EXAMPLE_API_KEY}
timeout: 30sintegration/
└── exampleapi/
├── config/
│ └── ExampleApiConfig.kt # RestClient bean config
├── service/
│ └── ExampleApiService.kt # Service wrapping API calls
├── dto/
│ └── ExampleApiResponse.kt # Response DTOs
└── exception/
└── ExampleApiException.kt # Custom exceptions
@Configuration
class ExampleApiConfig(
@Value("\${integration.example-api.base-url}") private val baseUrl: String,
@Value("\${integration.example-api.api-key}") private val apiKey: String
) {
@Bean
fun exampleApiClient(): RestClient {
return RestClient.builder()
.baseUrl(baseUrl)
.defaultHeader("Authorization", "Bearer $apiKey")
.build()
}
}@Service
class ExampleApiService(
private val exampleApiClient: RestClient
) {
companion object {
private val LOGGER = KotlinLogging.logger {}
}
fun fetchData(id: String): ExampleApiResponse {
LOGGER.info { "Fetching data for $id" }
return exampleApiClient.get()
.uri("/data/{id}", id)
.retrieve()
.body(ExampleApiResponse::class.java)
?: throw ExampleApiException("No data returned for $id")
}
}Create a WireMock contract module (like google-contracts/):
- Create
example-contracts/pom.xml(copy fromgoogle-contracts/pom.xml) - Add WireMock mappings in
src/main/resources/mappings/ - Create a stub profile in
application-stub-example.yaml - Add module to root
pom.xml
@Component
class ExampleApiHealthIndicator(
private val exampleApiClient: RestClient
) : AbstractHealthIndicator() {
override fun doHealthCheck(builder: Health.Builder) {
val response = exampleApiClient.get().uri("/health").retrieve().toBodilessEntity()
if (response.statusCode.is2xxSuccessful) {
builder.up()
} else {
builder.down()
}
}
}Add handlers in GlobalExceptionHandler for timeout/connection issues.
Add to templates/docker/.env:
EXAMPLE_API_URL=https://api.example.com
EXAMPLE_API_KEY=your-api-key