API First
- Anand Nerurkar
- Apr 18
- 4 min read
✅ Use Case: Customer Management Service (API First)
Step 1: Define API Contract (OpenAPI/Swagger)
Here’s an example openapi.yaml:
openapi: 3.0.1
info:
title: Customer API
description: API for managing customers
version: 1.0.0
servers:
- url: http://localhost:8080
paths:
/customers:
get:
summary: Get all customers
responses:
'200':
description: List of customers
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Customer'
post:
summary: Create a customer
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Customer'
responses:
'201':
description: Customer created
/customers/{id}:
get:
summary: Get customer by ID
parameters:
- name: id
in: path
required: true
schema:
type: string
responses:
'200':
description: Customer details
content:
application/json:
schema:
$ref: '#/components/schemas/Customer'
'404':
description: Customer not found
components:
schemas:
Customer:
type: object
properties:
id:
type: string
name:
type: string
email:
type: string
phone:
type: string
Step 2: Generate Code from OpenAPI
You can generate Spring Boot server stubs using OpenAPI Generator:
bash
openapi-generator-cli generate \
-i openapi.yaml \
-g spring \
-o customer-service \
--additional-properties=interfaceOnly=true
Step 3: Implement the Interfaces
In the generated code, implement the controller logic in classes like:
@RestController
public class CustomerApiController implements CustomerApi {
@Override
public ResponseEntity<List<Customer>> getCustomers() {
// Example data
List<Customer> customers = List.of(
new Customer("1", "Alice", "alice@example.com", "1234567890"),
new Customer("2", "Bob", "bob@example.com", "0987654321")
);
return ResponseEntity.ok(customers);
}
@Override
public ResponseEntity<Customer> getCustomerById(String id) {
Customer customer = new Customer(id, "Alice", "alice@example.com", "1234567890");
return ResponseEntity.ok(customer);
}
@Override
public ResponseEntity<Void> createCustomer(Customer customer) {
System.out.println("Creating customer: " + customer);
return new ResponseEntity<>(HttpStatus.CREATED);
}
}
Step 4: Test the API
Start the Spring Boot app
Use Swagger UI or Postman to test endpoints
Use SpringDoc OpenAPI for in-app Swagger UI:
xml
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.7.0</version>
</dependency>
Perfect! Let's now integrate the Spring Boot API-First Customer Service into a full Azure DevOps CI/CD pipeline, complete with Dockerization, deployment to Azure Kubernetes Service (AKS), and use of Azure Container Registry (ACR).
🔧 Step 1: Dockerize the Spring Boot Application
📄 Dockerfile
FROM openjdk:17-jdk-slim
VOLUME /tmp
ARG JAR_FILE=target/customer-service-0.0.1-SNAPSHOT.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
🏗️ Step 2: Azure DevOps Pipeline (YAML)
📄 azure-pipelines.yml
yaml
trigger:
branches:
include:
- main
variables:
dockerRegistryServiceConnection: 'AzureContainerRegistryConnection'
imageRepository: 'customer-service'
containerRegistry: 'myacr.azurecr.io'
dockerfilePath: 'Dockerfile'
tag: '$(Build.BuildId)'
stages:
- stage: Build
displayName: Build and Push Image
jobs:
- job: Build
displayName: Build
pool:
vmImage: 'ubuntu-latest'
steps:
- task: Maven@3
inputs:
mavenPomFile: 'pom.xml'
goals: 'clean package'
options: '-DskipTests'
- task: Docker@2
inputs:
containerRegistry: '$(dockerRegistryServiceConnection)'
repository: '$(imageRepository)'
command: 'buildAndPush'
Dockerfile: '$(dockerfilePath)'
tags: |
$(tag)
- stage: Deploy
displayName: Deploy to AKS
dependsOn: Build
jobs:
- deployment: Deploy
displayName: Deploy to AKS
environment: 'aks-env'
pool:
vmImage: 'ubuntu-latest'
strategy:
runOnce:
deploy:
steps:
- task: Kubernetes@1
inputs:
connectionType: 'Azure Resource Manager'
azureSubscription: '<Your Azure Subscription>'
azureResourceGroup: '<Your Resource Group>'
kubernetesCluster: '<Your AKS Cluster>'
namespace: 'default'
command: apply
useConfigurationFile: true
configuration: |
manifests/deployment.yaml
📦 Step 3: Kubernetes Deployment YAML
📄 manifests/deployment.yaml
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: customer-service
spec:
replicas: 2
selector:
matchLabels:
app: customer-service
template:
metadata:
labels:
app: customer-service
spec:
containers:
- name: customer-service
ports:
- containerPort: 8080
env:
- name: SPRING_PROFILES_ACTIVE
value: "prod"
---
apiVersion: v1
kind: Service
metadata:
name: customer-service
spec:
type: LoadBalancer
selector:
app: customer-service
ports:
- protocol: TCP
port: 80
targetPort: 8080
🔐 Step 4: Security & Integration
Component | Integration |
Azure AD | Use Spring Boot OAuth2 Client for auth with Azure AD |
ACR | Docker images pushed via Azure DevOps |
AKS + Istio | Secure mTLS, route policies, observability |
Secrets Management | Mount Azure Key Vault as volume or inject via env vars |
Monitoring | Use Azure Monitor, Prometheus, Grafana for AKS metrics |
✅ Optional Enhancements
Add SonarQube for code quality
Add JUnit + JaCoCo for test + coverage
Use Helm charts instead of raw YAML
Add a separate test stage with automated integration tests
Would you like me to:
Generate the complete Helm chart for this?
Add Spring Security config for Azure AD login?
Or create an architecture diagram including DevOps + AKS?
Let me know how deep you'd like to go!
You said:
how api deisgn is being used for testing contract
ChatGPT said:
Great question! In API-First Design, the OpenAPI contract (typically a .yaml or .json file) is the single source of truth — and this enables contract testing between frontend/backend or between services.
🧪 How API-First Design Enables Contract Testing
1. ✅ Consumer-Driven Contract Testing
Tools like Pact allow teams to:
Define how the consumer expects the provider to behave.
Test whether the provider adheres to that contract.
💡 Works great in microservices when a frontend or one microservice depends on another.
2. 🧾 Validation of Implementation Against OpenAPI
Use tools like:
Swagger Codegen / OpenAPI Generator to scaffold servers or clients.
Swagger Request Validator or Spring Cloud Contract to validate actual behavior against spec.
3. 🔧 Spring Boot + OpenAPI + Contract Validation
Let’s say you’ve defined your OpenAPI spec openapi.yaml.
✅ Example: Test Contract Using spring-cloud-contract
Step 1: Add Dependency
xml
CopyEdit
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-contract-verifier</artifactId> <version>4.0.1</version> </dependency>
Step 2: Create a Contract Stub (.groovy file)
groovy
CopyEdit
Contract.make { request { method 'GET' url '/customers/1' } response { status 200 body([ id: "1", name: "Alice", email: "alice@example.com" ]) headers { contentType(applicationJson()) } } }
Step 3: Generate Tests
bash
CopyEdit
./mvnw clean install
This will generate JUnit tests validating that your implementation matches the contract.
🔬 Additional Tools for Contract Testing
Tool | Purpose |
Pact | Consumer-driven contract testing |
Postman/Newman | Contract-based API testing from OpenAPI |
Dredd | Executes tests defined in OpenAPI spec |
RestAssured + OpenAPI Validator | Validates HTTP responses against OpenAPI |
Spring Cloud Contract | Stubs and verifies contract using Groovy DSL |
🧰 CI/CD Integration
In an Azure DevOps pipeline:
Validate OpenAPI syntax
Generate contract tests
Run them in a build step
Optionally publish stubs (e.g., Pact Broker) for consumers
Comments