PROJECTS

Software Engineer

Java & Backend Projects

Java projects evolving from console workflows into a packaged desktop application with persistence (SQLite), search/sort UX, unit tests, and packaging.

Navigate by software-engineering skill:

Back to Projects

More Java & backend work

This tracker is built in stages (1–5). Each stage adds a concrete feature: persistence, UI, database, tests, and packaging.

Job Application Tracker

A staged Java project that progresses from a console tracker to a packaged desktop application.

  • Stage 1: Console CRUD + status workflow + CSV export.
  • Stage 2: CSV load/save persistence.
  • Stage 3: Swing desktop UI (Add/Update/Delete + filter + CSV controls).
  • Stage 4: SQLite persistence (JDBC + schema/init).
  • Stage 5: Search + sort controls, basic unit tests (JUnit 5).
Java 17+ Maven Swing UI SQLite (JDBC) JUnit 5 jpackage (DMG)

  • Architecture: UI/Entry → Service → Repository → Persistence (CSV → SQLite via JDBC).
  • Core stack: Java 17+, Maven, Swing UI, SQLite (sqlite-jdbc).
  • Data model: JobApplication + ApplicationStatus enum (typed workflow).
  • Quality: validation + clearer UI messaging; JUnit 5 tests for service/repository behavior.
  • Distribution: packaged for macOS using jpackage (DMG).

Helpdesk Ticket Triage System

A staged helpdesk ticketing project focused on backend fundamentals: a structured ticket lifecycle, repository patterns, and API design. Built in phases to evolve from a console workflow into a REST-backed system.

  • Stage 1: Console CRUD + ticket workflow + basic search + SQLite persistence.
  • Stage 2: Spring Boot REST API + Swagger/OpenAPI docs + in-memory repository + Bean Validation + centralized error handling + Bruno API testing.
  • Stage 3: Spring Data JPA persistence + H2 database + H2 Console + Actuator health endpoint (DB-backed CRUD).
Java 17+ Spring Boot Maven REST API Swagger / OpenAPI Bean Validation Bruno Spring Data JPA H2 Actuator

  • API Layer: Spring MVC TicketController exposes CRUD endpoints under /api/tickets.
  • OpenAPI: Swagger UI generated via springdoc OpenAPI for interactive endpoint documentation and testing.
  • DTO Mapping: Request/response DTOs mapped via TicketMapper to keep the domain model clean.
  • Workflow: Status + priority modeled with typed enums (TicketStatus, Priority).
  • Storage (Stage 2): TicketRepository + InMemoryTicketRepository for memory-backed storage.
  • Persistence (Stage 3): Spring Data JPA repository backed by an H2 database for real CRUD persistence.
  • H2 Console: Inspect the database directly at /h2-console (confirm rows exist / updates persist).
  • Validation: Bean Validation on request DTOs to reject invalid payloads early.
  • Error Handling: Centralized exception mapping via GlobalExceptionHandler returning consistent ApiError JSON.
  • API Testing: Bruno collection for repeatable local CRUD requests using a {{baseUrl}} environment variable.
  • Observability: Spring Boot Actuator health endpoint at /actuator/health.
OAuth2 Bookmark API — Spring Boot service that issues and validates its own JWTs

OAuth2 Bookmark API

A self-contained Spring Boot service that both issues and validates its own JWTs, built in stages from an open REST API into a secured, multi-user app — focused on OAuth2, the Bruno API client, and IntelliJ IDEA Ultimate.

  • Stage 1: REST API (CRUD) + in-memory store + Bean Validation + Bruno collection + JUnit/MockMvc tests.
  • Stage 2: Self-contained OAuth2 — Spring Authorization Server issues JWTs (client_credentials) + Resource Server protects the API by scope.
  • Stage 3: Spring Data JPA + H2 persistence (file mode) + bulk-create endpoint.
  • Stage 4: User login — authorization_code + PKCE, login page + users, per-user bookmark ownership.
  • Stage 5: Ship it — multi-stage Docker image, Kubernetes manifests, a Helm chart, and a live deploy to GKE Autopilot on Google Cloud.
  • Stage 6: The same container on Cloud Run — a public HTTPS service that scales to zero, so the demo below is permanently live.
Java 21 Spring Boot Spring Security Spring Authorization Server OAuth2 / JWT PKCE Spring Data JPA H2 Bean Validation JUnit 5 Bruno Maven Docker Kubernetes Helm GKE Cloud Run

Live demo sign-in: john / password (demo accounts, no real data). It scales to zero, so the first request may take a few seconds to wake.

  • Authorization Server: Spring Authorization Server issues signed JWT access tokens at /oauth2/token.
  • Resource Server: validates JWTs and maps scopes to authorities (SCOPE_bookmark.read / write).
  • Grants: client_credentials (app-to-app) and authorization_code + PKCE (browser user login).
  • Security chains: separate filter chains for the auth server, the stateless JWT API (/api/**), and browser form login.
  • Per-user ownership: each bookmark is owned by the token sub; every query is scoped to the caller (another user's id returns 404).
  • Persistence: Spring Data JPA + H2 (file mode), idempotent seeding, and a bulk-create endpoint with per-element validation.
  • API testing: git-versioned Bruno collection — token request, Bearer calls, and the authorization-code login flow.
  • Containerisation: multi-stage Dockerfile (Maven+JDK builds the jar, a slim Alpine JRE ships it), non-root numeric UID, and MaxRAMPercentage so the JVM respects the container's memory limit.
  • Kubernetes: raw Deployment/Service manifests first, then the same resources as a Helm chart — values.yaml, named-template helpers, and conditional Secret/HPA/Ingress templates.
  • Health probes: startup / liveness / readiness wired to Spring Boot Actuator's Kubernetes probe endpoints (/actuator/health/liveness and /readiness).
  • Deployed to GKE: image pushed to Artifact Registry and released to a GKE Autopilot cluster with helm upgrade --install; rollout and rollback verified via helm history.
  • Also on Cloud Run: the identical image runs as a public HTTPS service that scales to zero — chosen for the permanent demo because a Kubernetes cluster bills continuously while Cloud Run costs nothing idle.
  • Running behind a proxy: Cloud Run terminates TLS at the edge, so server.forward-headers-strategy is required — without it the OAuth2 issuer and discovery document advertise http:// on an https:// site and the browser login flow breaks.
  • Environment-driven OAuth: redirect URIs come from configuration rather than being hard-coded, so the same build serves localhost, Kubernetes, and Cloud Run.
  • Tooling: built and run in IntelliJ IDEA Ultimate (Maven, bundled JDK, Database tool for H2).