Spring Boot Todos¶
A REST API for managing todos, built with Java/Spring Boot and PostgreSQL. Demonstrates deploying a database-backed Java application on AppMecca with Spring Data JPA and Flyway migrations.
Overview¶
| Repository | git@gitlab.com:appmecca-sample-apps/spring-boot-todos.git |
| Tech Stack | Java 21 / Spring Boot / Spring Data JPA / Flyway |
| Services | api (port 8080) |
| Database | Yes |
| Cache | None |
| URL Pattern | https://spring-boot-todos-api.{env}.appmecca.net |
What This App Demonstrates¶
- Deploying a database-backed Java application on AppMecca
- Flyway database migrations with versioned SQL files
- Spring Data JPA with the repository pattern for data access
- REST API with full CRUD operations against PostgreSQL
- The
database.enabled: trueconfiguration pattern
appmecca.yaml¶
containers:
- name: api
dockerfile: Dockerfile
context: .
deploy:
- name: api
container: api
port: 8080
health_check:
path: /health
startup_timeout: 300
resources:
memory: "512m"
database:
enabled: true
The only addition compared to Hello Java is database.enabled: true. AppMecca provisions a PostgreSQL database on first deploy and injects DATABASE_URL, DB_HOST, DB_PORT, DB_NAME, DB_USER and DB_PASSWORD into every container of the app automatically.
Never hardcode the database name
The database and user names are opaque, generated identifiers of the form
am_<hash>_db and am_<hash>_user — derived from the app and branch,
so each branch gets its own isolated database. They are never
spring-boot-todos_db. Always read DATABASE_URL (or the DB_* pair).
Give the JVM room, and time
The two extra settings above are not optional decoration for a Spring Boot app:
resources.memory: "512m". The platform default is 128 MB, which the JVM plus Tomcat plus Flyway will blow through during startup — the container is killed (exit code 137) seconds into boot. Note the unit suffix is required:512mor1g. A bare512means 512 bytes, and512mbis not a recognised form.health_check.startup_timeout: 300. The default is 120 seconds. A cold JVM with migrations to apply frequently needs longer, and a deploy that runs out of startup budget is rolled back. The range is 30-600.
Step-by-Step Deployment¶
1. Register the app¶
2. Build the container¶
Expected output
Java builds are slower than scripted languages because the Gradle build must download dependencies and compile the source code. Subsequent builds with cached Docker layers are faster.
3. Deploy¶
Expected output
4. Verify¶
Test the API:
# Create a todo
curl -X POST https://spring-boot-todos-api.dev.appmecca.net/api/todos \
-H "Content-Type: application/json" \
-d '{"title": "Deploy more apps", "done": false}'
# List all todos
curl https://spring-boot-todos-api.dev.appmecca.net/api/todos
# Update a todo
curl -X PUT https://spring-boot-todos-api.dev.appmecca.net/api/todos/1 \
-H "Content-Type: application/json" \
-d '{"done": true}'
# Delete a todo
curl -X DELETE https://spring-boot-todos-api.dev.appmecca.net/api/todos/1
API Endpoints¶
| Method | Path | Description |
|---|---|---|
GET |
/health |
Health check |
GET |
/api/todos |
List all todos |
POST |
/api/todos |
Create a todo |
PUT |
/api/todos/:id |
Update a todo |
DELETE |
/api/todos/:id |
Delete a todo |
Key Concepts¶
Flyway database migrations (versioned SQL files)¶
Flyway manages database schema changes using versioned SQL files in src/main/resources/db/migration/. Files follow the naming convention V1__Create_todos_table.sql, V2__Add_priority_column.sql, etc. Spring Boot auto-detects Flyway on the classpath and runs pending migrations on startup -- no entrypoint script is needed for the migration step. Flyway tracks which migrations have been applied in a flyway_schema_history table.
Spring Data JPA (repository pattern)¶
Spring Data JPA eliminates boilerplate data access code. You define a repository interface extending JpaRepository<Todo, Long>, and Spring generates the implementation at runtime. Standard CRUD operations (findAll, findById, save, deleteById) are provided without writing any SQL. Custom queries can be declared as method signatures (e.g., findByDone(boolean done)) and Spring derives the SQL automatically.
Any language, same workflow
AppMecca does not care what language your application is written in. As long as your container listens on the declared port and responds to health checks, the deployment workflow is identical.
What's Next?¶
- Hello Java -- the same stack without a database
- Express Knex Todos -- the same pattern in Node.js with Knex.js
- Actix Todos -- the same pattern in Rust with SQLx
- App with Database -- full guide to database configuration