GraphQL
Schema files, @TypeController, @Field, the namespace pattern, queries, mutations, subscriptions, and DataLoader batching.
Schema Files
GraphQL schemas are .graphqls files under src/main/resources/graphql/:
Schema Registration
Each module declares which schema files to load with a @Schemas interface:
KSP merges all @Schemas interfaces across all modules into a single unified schema.
TypeController & Fields
@TypeController marks a class as the field resolver for a GraphQL type. The type is inferred from GraphQLController<T>. Each method is annotated with @Field:
The first parameter receives the parent object being resolved.
Automatic Parameter Injection
| Parameter Type | What It Provides |
|---|---|
AuthenticationContext | Authenticated user (required — fails if unauthenticated) |
AuthenticationContext? | Optional auth — null for unauthenticated requests |
Batch<K, V> | DataLoader batch context |
DataFetchingEnvironment | GraphQL Java environment |
ServerCall | Underlying HTTP request |
All other parameters map to GraphQL field arguments by name.
The Namespace Pattern
Top-level fields return singleton objects, which are resolved by their own @TypeController:
This creates the query path: query { content { categories { all { ... } } } }
Mutation Controllers
Mutations follow the same namespace pattern with separate mutation objects:
AuthenticationContext) → Authorize (permission check) → Execute (delegate to service) → Return. Subscriptions
Subscription fields return Flow<T> backed by PubSubService:
Batching (DataLoader)
Use Batch<K, V> in field resolvers to avoid N+1 queries:
The ServiceCache batch resolver handles loading all keys in a single query. See Caching for how batch resolvers are declared.