{"id":17010498,"url":"https://github.com/raharrison/spring-boot-crud-api","last_synced_at":"2026-05-13T07:04:58.966Z","repository":{"id":152041064,"uuid":"598302347","full_name":"raharrison/spring-boot-crud-api","owner":"raharrison","description":"The simplest CRUD API with Spring Boot","archived":false,"fork":false,"pushed_at":"2023-02-06T21:10:19.000Z","size":67,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-27T12:46:39.858Z","etag":null,"topics":["api","crud","easy","liquibase","rest-api","simple","spring","spring-boot"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/raharrison.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-02-06T20:32:25.000Z","updated_at":"2024-07-18T08:55:49.000Z","dependencies_parsed_at":"2023-09-14T04:49:45.380Z","dependency_job_id":null,"html_url":"https://github.com/raharrison/spring-boot-crud-api","commit_stats":{"total_commits":2,"total_committers":1,"mean_commits":2.0,"dds":0.0,"last_synced_commit":"490dc51e58ca2e9db5772acefe1d411b5ba4c137"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raharrison%2Fspring-boot-crud-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raharrison%2Fspring-boot-crud-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raharrison%2Fspring-boot-crud-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raharrison%2Fspring-boot-crud-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/raharrison","download_url":"https://codeload.github.com/raharrison/spring-boot-crud-api/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244959458,"owners_count":20538629,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","crud","easy","liquibase","rest-api","simple","spring","spring-boot"],"created_at":"2024-10-14T06:04:40.460Z","updated_at":"2026-05-13T07:04:58.960Z","avatar_url":"https://github.com/raharrison.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Simple Spring Boot CRUD API\n\nA full Spring Boot CRUD (create, read, update, delete) RESTful API with the least fuss possible. Is Spring Boot the best framework\nfor this? Who knows - compare this implementation with `framework x` and decide for yourself!\n\n### Stack\n\n- **Java 25**\n- **Spring Boot 4** (Spring Framework 7, Jackson 3)\n- **Spring Data JPA** with H2 (in-memory)\n- **Liquibase** for schema migrations\n- **Lombok** for entity boilerplate\n- **JSpecify** for null safety annotations\n\n### Key Premises\n\nThe word `simple` can quickly get lost, so here is what this project does and doesn't cover:\n\n- Must provide a full CRUD interface for a single entity (`Product`)\n  - using the standard RESTful verbs, although it should be easy to change as needed\n  - the entity should have a `UUID` primary key and a mix of `String` and `DateTime` properties\n- All endpoints should return standard HTTP codes (`200`, `201`, `404`) for common scenarios\n- An in-memory database is fine, but should be easy to change out to a 'real' database later\n  - this project uses `H2` with Spring Data JPA\n- The service should handle database migrations and cater for future schema changes\n  - handled by `Liquibase` not JPA here (future-proof)\n- The `getAll` endpoint should support full pagination\n  - specify the `page` and `size` as query params\n  - returns a slim `PageResponse` (content, page, size, totalElements, totalPages) rather than Spring's verbose `Page` wrapper\n- The `getAll` endpoint should support filtering any entity property through query params\n  - e.g. `?name=Ca%` should return all entities with name beginning with `Ca`\n  - multiple parameters can be specified to filter by many properties\n  - wildcards supported (`LIKE` query) for string fields; exact match for the `id` field\n- Full testing suite - not just unit tests\n  - integration tests for each endpoint (testing the HTTP layer)\n  - tests which run the full database queries on a real database with the full schema loaded (even if in-memory), rather than mocking everywhere\n\n### Endpoints\n\nBase path: `/api`\n\n- `GET /api/products` - retrieve all products (supports pagination and filtering via query params)\n- `GET /api/products/{id}` - retrieve a specific product by id\n- `POST /api/products` - save a new product\n- `PUT /api/products/{id}` - update a specific product by id\n- `DELETE /api/products/{id}` - delete a specific product by id\n\n### Running\n\n```bash\n./mvnw spring-boot:run\n```\n\n### Testing\n\n```bash\n./mvnw verify\n```\n\nCI runs automatically on push via GitHub Actions.\n\n### Outcomes/Remarks\n\nA few remarks about using Spring Boot for this use case:\n\n- Spring Boot gets you up and running with a new project extremely quickly - especially with \u003chttps://start.spring.io\u003e\n- The default autoconfiguration for creating endpoints is easy (no surprises there)\n  - it can parse the `Pageable` object from query params easily and maps the entities out-of-the-box\n- Choosing a DAO layer is a bit complicated. Do you go with jOOQ, Spring Data JPA or Spring Data JDBC (or others)?\n  - `data-jdbc` is lighter-weight than JPA (great!) but doesn't support dynamic queries unless you write the SQL yourself. If you\ncan deal with only using the repository methods then it's a good choice however (it doesn't support `Criteria` etc.)\n  - `jOOQ` provides a really nice api for querying, but the code-generation is painful to set up, and you have to deal with the pagination\n    side of things yourself. No nice built-in support for `Pageable` like Spring Data has. Producing the dynamic filtering query\n    is easy however\n  - `data-jpa` is probably the default heavyweight choice and offers the most flexibility. It has easy support for pagination, but no out-of-the-box\nfeature for simple filtering on entity attributes. I had to construct my own `Specification` manually which includes hard coding column names (yuck!)\n- Built-in support for database migrations with `Liquibase` is really easy - literally just drop the changelogs in the right folder and that's it\n- `CrudRepository.deleteById` returns `void` with no indication of whether anything was actually deleted. The workaround is an\n  `existsById` check + delete in a single `@Transactional` method in the service - more boilerplate than it should be\n- Spring's `Page\u003cT\u003e` response includes a lot of noise (`pageable`, `sort`, `first`, `last`, `empty` etc). Worth wrapping it in a\n  slimmer DTO\n- Testing is one of Spring Boot's strong points\n  - easily test the repository layer with `H2` and running the db migrations to create the right schema\n  - test the web layer endpoints with `MockMvc` - although the api for that remains awkward (not a fan of Json path assertions).\n    I prefer to just pull it back to the object model\nand write the standard assertions as opposed to using json paths or dodgy Hamcrest matchers\n- It's a shame that I still have to use `Lombok` for the entity boilerplate (getters/setters etc). And also for the filter to get a nice builder\n- It's Spring Boot, so you know that you can easily extend this like crazy in the future...\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraharrison%2Fspring-boot-crud-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fraharrison%2Fspring-boot-crud-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraharrison%2Fspring-boot-crud-api/lists"}