Services (Spring Boot)
The LabOps demo runs two backend services. Both follow the same shape — Spring Boot 3.4 / Java 17 / Maven — but are designed to demonstrate two distinct OAuth2 grant flows through APIM.
tickets-api
| Path | services/tickets-api/ |
| Purpose | Ticket CRUD; user-scoped via OIDC Auth Code + PKCE |
| Image | ghcr.io/zeshaq/wso2-demo-app/tickets-api |
| Listens | :8080 |
| DB | H2 in-memory (Postgres-compat mode) until #11 |
Endpoints
| Method | Path | Purpose | Future scope |
|---|---|---|---|
| GET | /health | Actuator health | Public |
| GET | /api/v1/tickets | List tickets | tickets:read |
| GET | /api/v1/tickets/{id} | One ticket | tickets:read |
| POST | /api/v1/tickets | Create | tickets:write |
| PUT | /api/v1/tickets/{id} | Update | tickets:write |
| DELETE | /api/v1/tickets/{id} | Delete | tickets:admin |
Ticket entity
id Long (auto)
title String (required, max 200)
description String (nullable, max 4000)
status enum OPEN | IN_PROGRESS | CLOSED (default OPEN)
assignee String (nullable)
createdAt Instant
updatedAt Instantassets-api
| Path | services/assets-api/ |
| Purpose | Lab asset CRUD; M2M write + user read |
| Image | ghcr.io/zeshaq/wso2-demo-app/assets-api |
| Listens | :8080 |
| DB | H2 in-memory (Postgres-compat mode) until #11 |
Endpoints
| Method | Path | Purpose | Future scope |
|---|---|---|---|
| GET | /health | Actuator health | Public |
| GET | /api/v1/assets | Paginated list | assets:read |
| GET | /api/v1/assets/{id} | One asset | assets:read |
| POST | /api/v1/assets | Create | assets:admin (M2M client_credentials) |
| DELETE | /api/v1/assets/{id} | Delete | assets:admin |
Asset entity
id Long (auto)
assetTag String (required, unique, max 64) e.g. "LB-RACK-01-PSU-2"
name String (required, max 200)
category enum COMPUTE | STORAGE | NETWORK | POWER | OTHER
location String (nullable, max 200)
serialNumber String (nullable, max 100)
inService boolean (default true)
createdAt Instant
updatedAt InstantWhy two services
The demo needs to show two OAuth2 grant shapes side-by-side through one APIM gateway:
tickets-api→ user-scoped, Authorization Code + PKCE via WSO2 IS, scopestickets:read|write|adminassets-api→ M2Mclient_credentialsfor partner systems, thelabops-cli, and thegitlab-syncMI flow; plus user-scoped read for the dashboard
Two services let one APIM deployment expose both shapes, and let us attach a response-transformation mediation policy to the assets-api so internal fields are stripped before they reach untrusted clients.
Build, run, test
sh
# from services/<service>/
mvn -B -ntp -DskipTests package # build the JAR
mvn -B -ntp test # run unit + integration tests
mvn spring-boot:run # run locally on :8080sh
# Container
docker build -t labops/<service>:dev .
docker run --rm -p 8080:8080 labops/<service>:devConfiguration
Phase 2 uses H2 with in-memory data. Future env vars (introduced incrementally):
| Variable | Phase | Purpose |
|---|---|---|
SPRING_DATASOURCE_URL | #11 | Postgres JDBC URL (templated by Helm) |
SPRING_DATASOURCE_USERNAME | #11 | DB user (from k8s Secret) |
SPRING_DATASOURCE_PASSWORD | #11 | DB password (external-secrets-managed) |
SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_ISSUER_URI | #18 | WSO2 IS issuer for JWT validation |
How the services fit in
React SPA / labops-cli
▼
APIM Gateway ◄── token issued by WSO2 IS (Key Manager)
▼
tickets-api / assets-api ◄── this page
▼
Postgres (spoke-dc)See Architecture for the full picture.