# Spring Boot Demo An interactive portfolio application demonstrating how I build a modern Spring Boot system from browser page to database. It replaces the original third-party API experiment with a self-contained demo: a Thymeleaf landing page, a live feature tour, secured REST APIs, JPA persistence, cache metrics, validation, error handling, and tested behaviour. ## Live pages | URL | Purpose | | --- | --- | | `/` | Thymeleaf landing page based on my Spring portfolio content, with developer profile and contact details. | | `/showcase` | Interactive jQuery AJAX tour. It calls the running controllers, shows JPA query results, creates a database record, reads a post twice, and displays live cache statistics. | | `/api/posts` | Public paginated/searchable REST read API; `POST`, `PUT`, and `DELETE` require the `EDITOR` role. | | `/api/showcase/cache` | Read-only Caffeine cache statistics for the feature tour. | | `/actuator/health` | Public health check. | ## Run it Requires JDK 21+. ```powershell cd D:\app\springboot-jsonplaceholder-demo ./mvnw.cmd spring-boot:run ``` Open [http://localhost:8080](http://localhost:8080). The local profile uses an in-memory H2 database and automatically loads three sample posts for the feature tour. The local editor account is intentionally a non-secret demo account: ```text username: demo-editor password: changeit ``` The showcase form never pre-fills or stores credentials; it sends them only to the same local application for the authenticated request. Override them through `APP_EDITOR_USERNAME` and `APP_EDITOR_PASSWORD`. ## What the feature tour proves 1. **Thymeleaf & MVC** — `HomeController` renders `/` and `/showcase`; the index uses a server-side model for contact values. 2. **jQuery AJAX & REST controllers** — the browser calls `GET /api/posts`, `POST /api/posts`, `GET /api/posts/{id}`, health, and cache-stat endpoints. Responses and errors are displayed directly in the page. 3. **Spring Data JPA** — `PostRepository` provides pagination and case-insensitive title search; `PostService` owns read/write transaction boundaries. 4. **Caching** — individual post reads use bounded Caffeine caching. The “Read twice” button produces real cache activity, then requests the cache-stat endpoint. 5. **Security** — public portfolio pages and read APIs are open; data mutations require the `EDITOR` role with BCrypt-backed, stateless HTTP Basic authentication. 6. **Validation & error handling** — request records validate input at the boundary and `ApiExceptionHandler` returns consistent RFC-style problem documents. 7. **Safe concurrent updates** — the JPA `@Version` field makes an outdated update return a conflict instead of silently overwriting a newer change. 8. **Configuration management** — typed cache and security settings live in application configuration. The `prod` profile uses PostgreSQL and requires database/editor environment variables with no committed production secrets. ## Build and test ```powershell ./mvnw.cmd test ./mvnw.cmd package ``` The integration test verifies the rendered Thymeleaf pages, unauthenticated versus editor-only API access, validation responses, search, and cache metrics. ## Project layout ```text com.hoelee.demo ├── config typed cache and security configuration ├── post REST contract, JPA entity, repository, and service layer ├── support consistent API error mapping └── web Thymeleaf pages, cache metrics, and local demo data ``` Each Java file has a compact learning note in the author/version comment format used by the larger reference application. The source uses 2024 timestamps in the requested evening window; the Git commits themselves retain their real creation times. ## Production profile `SPRING_PROFILES_ACTIVE=prod` selects PostgreSQL and requires: ```text APP_DB_URL APP_DB_USERNAME APP_DB_PASSWORD APP_EDITOR_USERNAME APP_EDITOR_PASSWORD ``` For production, use a managed secret store and add Flyway or Liquibase migrations before setting `ddl-auto` to `validate`.