Skip to main content

Scenario: Spring Boot Enterprise with AEEF Standards

This walkthrough shows how to apply AEEF production standards together on a Spring Boot enterprise application. It follows an entire feature from prompt to production, demonstrating how the standards create a governed delivery pipeline — with specific attention to layered architecture, Spring Security, and the testing pyramid with Testcontainers.

Time required: 60-90 minutes (reading + doing) Prerequisites: Familiarity with Java 21+, Spring Boot 3, and basic AEEF concepts from the Startup Quick-Start.

Composite Scenario

This is a realistic composite scenario showing how standards apply together. Adapt the specifics to your stack — the governance workflow is universal.


The Project

An enterprise multi-tenant document management system built with:

  • Framework: Spring Boot 3.3 with Java 21
  • Database: PostgreSQL via Spring Data JPA (Hibernate 6)
  • Security: Spring Security 6 with JWT + role-based access
  • Search: Elasticsearch for full-text document search
  • Storage: S3-compatible object storage for files
  • Testing: JUnit 5 + Mockito + Testcontainers + MockMvc
  • CI: GitHub Actions with SpotBugs + OWASP Dependency-Check
  • Build: Gradle with Spring Boot plugin

The team has 20 engineers across 4 squads and has completed the CI/CD Pipeline Starter and Policy Templates.

The Feature

User story: As an organization admin, I can define document retention policies so that documents are automatically archived or deleted after the retention period expires.

This feature touches:

  • Database schema (retention policy entity, document metadata update)
  • REST API (CRUD for retention policies)
  • Scheduled job (nightly scan for expired documents)
  • Audit trail (log all retention actions for compliance)
  • Authorization (only org admins can define policies; deletion must be approved by two admins)
  • Event-driven: publish events when documents are archived/deleted

Phase 1: Prompt Engineering (PRD-STD-001)

Step 1.1: Structured Prompt for REST Endpoint

Using the Java Secure REST Endpoint template (prompt-library/by-language/java/secure-endpoint.md) combined with the Spring Boot Endpoint Implementation template (prompt-library/by-framework/spring-boot/endpoint-implementation.md):

You are a senior Spring Boot engineer building production-grade REST endpoints.

**Context:**
- Spring Boot 3.3 with Java 21 (records, sealed interfaces, pattern matching)
- Database: Spring Data JPA with Hibernate 6, PostgreSQL
- Security: Spring Security 6 with JWT, role hierarchy (VIEWER < EDITOR < ADMIN < ORG_ADMIN)
- Validation: Jakarta Bean Validation
- API docs: springdoc-openapi (OpenAPI 3.1)
- Build: Gradle

**Task:** Create CRUD endpoints for document retention policies.

**Requirements:**
1. RetentionPolicy entity: org_id, name, document_category, retention_days,
action (ARCHIVE/DELETE), requires_approval (boolean), created_by, active
2. Only ORG_ADMIN role can create, update, or delete policies
3. Any authenticated user can list policies for their org
4. Policies with requires_approval=true need a second ORG_ADMIN to approve deletion actions
5. Unique constraint on (org_id, document_category) — one policy per category per org
6. Soft-delete with deactivation timestamp (never hard-delete policies for audit trail)

**Constraints:**
- DTOs as Java records — never expose JPA entities
- @Valid on ALL @RequestBody parameters
- Constructor injection — no field injection
- @Transactional(readOnly = true) on read operations
- @PreAuthorize("hasRole('ORG_ADMIN')") on mutation endpoints
- Error responses via RFC 9457 ProblemDetail
- @Version for optimistic locking on policy updates
- Use @EntityGraph to prevent N+1 on policy-document associations

Step 1.2: Structured Prompt for Scheduled Job

You are implementing a scheduled retention enforcement job.

**Context:**
- Spring Boot 3.3, @Scheduled with ShedLock for distributed locking
- Runs nightly at 02:00 UTC

**Task:** Implement the document retention scanner.

**Requirements:**
1. Find all active policies where documents exceed retention_days
2. For ARCHIVE action: move document metadata to archive table, move file to cold storage
3. For DELETE action with requires_approval=false: hard-delete file, soft-delete metadata
4. For DELETE action with requires_approval=true: create approval request, notify ORG_ADMINs
5. Batch processing: process 100 documents per batch to avoid memory pressure
6. Audit log every action: policy_id, document_id, action, timestamp, initiated_by="system"
7. Stop processing if error rate exceeds 5% in a batch (circuit breaker)

**Constraints:**
- Use ShedLock to prevent duplicate runs across instances
- Use @Transactional per batch, not per entire job
- Publish ApplicationEvent for each action (ArchiveEvent, DeleteEvent, ApprovalRequestEvent)
- Side effects (email, S3 operations) happen AFTER_COMMIT via @TransactionalEventListener
- Log structured context: job_run_id, batch_number, documents_processed, errors
- Never delete files before metadata is committed (metadata first, file second)

Step 1.3: Record Prompt References

AI-Usage: claude
AI-Prompt-Ref: by-language/java/secure-endpoint + by-framework/spring-boot/endpoint-implementation (retention CRUD),
by-framework/spring-boot/component-implementation (scheduled job)
AI-Confidence: high — CRUD endpoints, medium — batch job with approval workflow

Phase 2: Human-in-the-Loop Review (PRD-STD-002)

Step 2.1: Review AI Output Against Checklist

Using the Java PR Risk Review prompt (prompt-library/by-language/java/pr-risk-review.md):

Critical items for this feature:

CheckWhat to VerifyStatus
Auth bypassIs @PreAuthorize on every mutation endpoint? Is org_id filtered from JWT claim?
Missing @ValidDoes every @RequestBody have @Valid? (The #1 AI mistake in Spring Boot)
Entity exposureAre JPA entities absent from controller signatures? Using record DTOs?
SQL injectionAll @Query methods use :paramName — no string concatenation?
Transaction boundaryIs @Transactional per-batch, not wrapping the entire nightly job?
Event orderingAre file deletions in @TransactionalEventListener(AFTER_COMMIT)?
Optimistic lockingIs @Version on the entity? Is OptimisticLockException handled?
Audit completenessIs every retention action logged with policy_id, document_id, and action?
Soft-delete integrityIs the policy soft-deleted (deactivated), not hard-deleted?

Step 2.2: Java/Spring-Specific AI Pitfalls to Check

From the Java anti-patterns table (prompt-library/by-language/java.md) and Spring Boot pitfalls (prompt-library/by-framework/spring-boot.md):

  • No field injection (@Autowired on fields) — constructor injection only
  • No @Transactional on private methods (Spring proxies can't intercept them)
  • No returning null from service methods — throw domain exceptions
  • No bare catch (Exception e) — catch specific exception types
  • No @SuppressWarnings hiding real issues
  • DTOs are Java records, not mutable POJOs
  • @Transactional(readOnly = true) on all read-only service methods
  • @EntityGraph or JOIN FETCH used to prevent N+1 queries

Phase 3: Testing (PRD-STD-003)

Step 3.1: Generate Test Matrix

Use the Java Risk-Based Test Matrix prompt (prompt-library/by-language/java/test-matrix.md) combined with Spring Boot Testing Strategy (prompt-library/by-framework/spring-boot/testing-strategy.md):

Feature: Document retention policy CRUD + nightly enforcement job
Changes: JPA entity, controller, service, repository, scheduled job, event handlers

Generate a layered test strategy following the Spring Boot testing pyramid:
1. Unit tests: service logic with Mockito, DTO validation, event publishing
2. Slice tests: @WebMvcTest for controller, @DataJpaTest for repository, @JsonTest for DTOs
3. Integration tests: @SpringBootTest with Testcontainers for full lifecycle
4. Security tests: auth enforcement at every endpoint

Expected test coverage:

Test TypeCountWhat It Covers
Unit (Mockito)15-20Service logic, validation, event publishing, batch processing
Slice — @WebMvcTest10-14Controller endpoints, request validation, auth enforcement
Slice — @DataJpaTest6-8Custom queries, constraints, @EntityGraph behavior
Slice — @JsonTest4-6DTO serialization, missing fields, date formats
Integration5-8Full CRUD lifecycle, scheduled job, event flow

Step 3.2: Verify AI-Generated Tests

Common issues with AI-generated Spring Boot tests (from prompt-library/by-framework/spring-boot/testing-strategy.md):

  • @WebMvcTest includes SecurityConfig — tests auth enforcement
  • @DataJpaTest uses Testcontainers, NOT H2 (@AutoConfigureTestDatabase(replace = NONE))
  • Service unit tests use @ExtendWith(MockitoExtension.class), not @SpringBootTest
  • @Valid tests send invalid payloads and assert 400 (not just happy path)
  • Tests assert exact HTTP status codes (201, 204) not just "2xx success"
  • No Thread.sleep() — use Awaitility for async assertions
  • Tests cover both @WithMockUser and unauthenticated scenarios

Phase 4: Security Scanning (PRD-STD-004)

Step 4.1: Automated CI Checks

Your CI pipeline catches:

# These run automatically on every PR
- SpotBugs: Null dereference, SQL injection, serialization issues
- OWASP Dependency-Check: Known CVEs in Java dependencies
- Semgrep: Spring Security misconfigurations, injection patterns
- Checkstyle: Code style enforcement

Step 4.2: Compliance-Specific Security Review

Document retention is a compliance feature. Use the Spring Boot Security Review prompt (prompt-library/by-framework/spring-boot/security-review.md) to verify:

  • Retention policies cannot be modified after documents have been processed under them (immutability after activation)
  • Audit log entries are append-only — no update/delete API for audit records
  • Two-admin approval flow cannot be bypassed (same admin cannot approve their own request)
  • Scheduled job uses ShedLock to prevent duplicate runs across instances
  • Actuator endpoints for job status are not exposed publicly
  • Hard-deleted files are unrecoverable (S3 object deleted, not just hidden)
  • Soft-deleted metadata retains the audit trail reference

Phase 5: Quality Gates (PRD-STD-007)

Step 5.1: PR Checklist

GateToolPass Criteria
Compilationgradle compileJavaZero errors
LintCheckstyle + SpotBugsZero errors
Unit testsgradle test100% passing, new code covered
Slice testsgradle testAll @WebMvcTest and @DataJpaTest passing
Integration testsgradle integrationTestFull lifecycle tests passing
Security scanOWASP Dependency-CheckZero high/critical CVEs
API contractspringdoc OpenAPI diffNo unintentional breaking changes
Buildgradle bootJarSuccessful

Step 5.2: PR Metadata

## Changes
- Add RetentionPolicy JPA entity with Flyway migration V7__retention_policies
- Add CRUD endpoints: POST/GET/PATCH/DELETE /api/v1/retention-policies
- Add approval workflow for deletion policies (requires two ORG_ADMINs)
- Add nightly retention enforcement job with ShedLock
- Add audit trail for all retention actions
- Add ApplicationEvents: ArchiveEvent, DeleteEvent, ApprovalRequestEvent

## AI Disclosure
- AI-Usage: claude
- AI-Prompt-Ref: by-language/java/secure-endpoint + by-framework/spring-boot/endpoint-implementation (CRUD),
by-framework/spring-boot/component-implementation (scheduled job)
- AI-Review: Used by-language/java/pr-risk-review for self-review
- Human-Review: Approval workflow manually verified, audit trail completeness reviewed

## Testing
- 18 unit tests (service logic, validation, events, batch processing)
- 12 controller slice tests (CRUD + auth + validation)
- 7 repository slice tests (custom queries, constraints)
- 5 JSON serialization tests (DTO shape, date formats)
- 6 integration tests (full lifecycle, scheduled job, events)

Phase 6: Dependency Compliance (PRD-STD-008)

Use the Java Dependency Risk Check (prompt-library/by-language/java/dependency-check.md) if new dependencies were added:

Review these dependency additions:
- net.javacrumbs.shedlock:shedlock-spring (distributed job locking)
- net.javacrumbs.shedlock:shedlock-provider-jdbc-template (JDBC lock provider)
- org.awaitility:awaitility (async test assertions)

Check: license, CVEs, maintenance status, Spring Boot version compatibility, alternatives.

Phase 7: Documentation (PRD-STD-005)

Use the Java Change Runbook (prompt-library/by-language/java/change-runbook.md) to generate:

  1. Migration notes: Flyway migration V7 must run before deployment; ShedLock table DDL required
  2. Environment variables: RETENTION_JOB_CRON (default: 0 0 2 * * *), RETENTION_BATCH_SIZE (default: 100), RETENTION_ERROR_THRESHOLD_PERCENT (default: 5)
  3. Rollback procedure: Revert Flyway migration, redeploy previous JAR, ShedLock table can remain (no-op if job doesn't exist)
  4. Monitoring:
    • Alert on retention job failure (ShedLock timeout or error rate breach)
    • Alert on approval queue depth > 50 (pending deletions not being reviewed)
    • Dashboard: documents archived/deleted per day, approval queue depth, job duration trend
  5. Compliance notes:
    • Audit log entries are immutable — no API for modification or deletion
    • Retention reports available via /api/v1/retention-policies/{id}/audit-log
    • Document deletion is irreversible — ensure policies are tested before activation

Summary: Standards Applied

StandardHow It Was AppliedEvidence
PRD-STD-001 (Prompt Engineering)Structured prompts from Java/Spring Boot templatesPR description AI-Prompt-Ref
PRD-STD-002 (Code Review)AI + human review with compliance focusReview comments on PR
PRD-STD-003 (Testing)Full testing pyramid with Testcontainers, 48+ testsCI test results
PRD-STD-004 (Security)Automated scans + compliance-specific reviewCI scan output + review notes
PRD-STD-005 (Documentation)Generated runbook with compliance notesPR description + runbook
PRD-STD-007 (Quality Gates)All gates including API contract checkCI status checks
PRD-STD-008 (Dependencies)Dependency risk check for new packagesPR comment with assessment

What This Demonstrates

  1. @Valid is non-negotiable — the most common AI mistake in Spring Boot is omitting @Valid; the review checklist catches this every time
  2. Testing pyramid saves CI time — unit tests (fast) catch logic errors, slice tests (medium) catch Spring wiring issues, integration tests (slow) catch lifecycle issues
  3. Compliance features need extra governance — retention policies with legal implications require audit trails, two-admin approval, and immutability guarantees
  4. Events decouple side effects safely — @TransactionalEventListener(AFTER_COMMIT) ensures files are only deleted after metadata is committed
  5. Enterprise scale doesn't mean enterprise overhead — 48 tests and 7 standards applied in a single PR without blocking the team

Apply This Pattern in Your Repo

Use this scenario as a reference pattern, then choose an implementation path:

Next Steps