A production-style GraphQL API built with Spring Boot and Spring for GraphQL: schema-first types, queries & mutations, batch loading (N+1 solved), integration tests, and one-command run with Docker.
Features • Architecture • Quick Start • API • Testing
| Feature | Description |
|---|---|
| Schema-first GraphQL | Types, queries, and mutations defined in .graphqls; Java resolvers map 1:1 to the schema. |
| Batch loading | @BatchMapping for Book.author — one batched call per request instead of N+1 queries. |
| Queries & mutations | books, bookById, authors, authorById; addBook mutation with input type. |
| In-memory store | Demo data (authors & books); easy to swap for JPA/PostgreSQL later. |
| Integration tests | GraphQlTester + WebTestClient against the real /graphql endpoint. |
| Unit tests | Service layer tests for AuthorService and BookService. |
| Docker | Multi-stage Dockerfile + docker compose up for a single-command run. |
| Actuator | Health and info endpoints for monitoring and orchestration. |
flowchart TB
subgraph Client
C[HTTP Client / curl]
end
subgraph "Spring Boot :8080"
GQL["POST /graphql"]
subgraph "Resolvers"
QC[QueryController]
BC[BookResolver]
MC[MutationController]
end
subgraph "Services"
AS[AuthorService]
BS[BookService]
end
subgraph "Storage"
M[(In-memory Map)]
end
end
C --> GQL
GQL --> QC
GQL --> BC
GQL --> MC
QC --> AS
QC --> BS
BC --> AS
MC --> BS
AS --> M
BS --> M
Flow: Client sends a GraphQL document to POST /graphql. Spring for GraphQL routes fields to the right resolvers. Query and mutation resolvers call services; BookResolver uses @BatchMapping to load authors in one batch. Services read/write in-memory maps (replace with repositories for persistence).
| Layer | Technology |
|---|---|
| Language | Java 21 |
| Framework | Spring Boot 3.2 (Web, GraphQL, Actuator) |
| GraphQL | Spring for GraphQL (schema-based, batch loading) |
| Build | Gradle 8.5 (Kotlin DSL) |
| Tests | JUnit 5, AssertJ, Spring GraphQL Test, WebTestClient |
| Container | Docker, Docker Compose (Gradle image for build, Eclipse Temurin JRE for run) |
- JDK 21 (for local run and tests)
- Docker & Docker Compose (optional; for containerized run)
git clone https://github.com/NullPoint3rDev/graphql-spring-api.git
cd graphql-spring-api
./gradlew bootRun- GraphQL endpoint:
POST http://localhost:8080/graphql - Health: http://localhost:8080/actuator/health
docker compose up --buildThen call POST http://localhost:8080/graphql as above. To run in the background: docker compose up -d --build. Stop with docker compose down.
- URL:
POST http://localhost:8080/graphql - Content-Type:
application/json - Body:
{ "query": "..." }or{ "query": "...", "variables": { ... } }
curl -s -X POST http://localhost:8080/graphql \
-H "Content-Type: application/json" \
-d '{"query": "query { books { id title author { id name } } }"}' | jqcurl -s -X POST http://localhost:8080/graphql \
-H "Content-Type: application/json" \
-d '{"query": "query { bookById(id: \"1\") { id title author { name } } }"}' | jqcurl -s -X POST http://localhost:8080/graphql \
-H "Content-Type: application/json" \
-d '{"query": "mutation { addBook(input: { title: \"New Book\", authorId: \"1\" }) { id title author { name } } }"}' | jq| Operation | Field / Mutation | Description |
|---|---|---|
| Query | books |
List all books (with optional author selection). |
| Query | bookById(id: ID!) |
Get one book by ID (null if not found). |
| Query | authors |
List all authors. |
| Query | authorById(id: ID!) |
Get one author by ID (null if not found). |
| Mutation | addBook(input: AddBookInput!) |
Create a book; returns the created book with author. |
./gradlew test- Integration tests:
GraphQlIntegrationTest— full HTTP calls to/graphql(books, bookById, authors, authorById, addBook, null handling). - Unit tests:
AuthorServiceTest,BookServiceTest— service logic with in-memory data.
src/main/java/.../graphql/
├── GraphqlApplication.java
├── controller/
│ ├── QueryController.java # Query: books, bookById, authors, authorById
│ ├── BookResolver.java # @BatchMapping for Book.author
│ └── MutationController.java # addBook
├── model/
│ ├── Book.java
│ ├── Author.java
│ └── AddBookInput.java
└── service/
├── BookService.java
└── AuthorService.java
src/main/resources/
├── application.yml
└── graphql/
└── schema.graphqls # GraphQL schema (types, Query, Mutation, input)
This project is licensed under the MIT License — see the LICENSE file for details.