Schema-First Design
GraphQL starts with a typed schema (SDL): object types, queries, and the contract that both client and server share.
On this page
GraphQL starts with a schema - a typed contract, written in the Schema Definition Language (SDL), that
declares every type, every field, and every entry point into your graph. Both client and server share it: the
client knows exactly what it can ask for, the server knows exactly what it must resolve. Spring for GraphQL is
schema-first - you write the .graphqls file, and your Java code fulfils it.
The SDL: types and fields
A schema describes the shape of your data with object types and typed fields. Here's BookVault's catalog:
type Book {
id: ID! # ! means non-nullable
title: String!
isbn: String
availableCopies: Int!
author: Author! # a field can be another object type
}
type Author {
id: ID!
name: String!
books: [Book!]! # a list of Books
}Read the type modifiers carefully - they are the contract:
String!- a non-null String; the server promises it's never null.[Book!]!- a non-null list of non-null Books (the list exists and contains no null elements).author: Author!- the graph's edges: from aBookyou can traverse to itsAuthor, and from anAuthorback to itsbooks. This traversal is what lets one query gather related data.
Entry points: Query, Mutation, Subscription
Three special root types are the doors into the graph. Query is for reads:
type Query {
book(id: ID!): Book # fetch one book by id
books(topic: String): [Book!]! # list books, optionally filtered
}
type Mutation {
borrowBook(bookId: ID!, memberId: ID!): Loan # writes (later lesson)
}Every client query must start at a field of Query (or Mutation for writes). From that entry point, the
client traverses the graph via the object fields you declared. In Spring, you drop this file in
src/main/resources/graphql/schema.graphqls and Spring Boot's GraphQL starter picks it up automatically.
Schema-first vs. code-first
Spring for GraphQL is schema-first: the SDL file is the source of truth and your resolvers are validated against it at startup - a field with no data source is caught early. Some other stacks are code-first (annotations generate the schema). Schema-first keeps the contract human-readable and front-end-friendly, which is usually the point of adopting GraphQL in the first place.
Nullability is the contract
That ! is not decoration - it's a promise the engine enforces. If a non-null field (title: String!)
resolves to null at runtime, GraphQL doesn't silently return null; it errors that field and propagates the
null up to the nearest nullable parent. So nullability is a real design decision:
- Mark a field
!only when it genuinely always has a value. - Make fields that can be absent (an optional
isbn) nullable, or a single missing value can blank out a whole object.
The schema is the printed menu every diner and every cook shares. Object types are the dishes; fields are
the components listed under each dish; the edges (author: Author!) are the 'comes with' lines that let you
follow one dish to its side. The Query type is the 'you may order from this section' header - you can't
order something that isn't a starting point on the menu. And the ! is the kitchen's guarantee that a listed
component is always included - promise it on something that sometimes runs out, and one missing item spoils the
whole plate.
BookVault wants to add reviews. A Book should expose its list of reviews; each Review has a rating (1-5, always
present), an optional text comment, and the member who wrote it. Sketch the SDL Review type and the field you'd
add to Book. Which fields get ! and which don't?
In GraphQL SDL, what does the '!' in 'title: String!' mean?
Key takeaways
- GraphQL is schema-first in Spring: an SDL (.graphqls) file is the shared, typed contract between client and server.
- Object types have typed fields; fields that reference other types are the graph's edges that let one query traverse related data.
- Root types Query (reads), Mutation (writes), and Subscription (streams) are the only entry points; every query starts at one of their fields.
- The '!' marks non-nullable fields and is enforced - a non-null field resolving to null errors and propagates up, so nullability is a deliberate design choice.
- Spring Boot auto-loads schema.graphqls from resources/graphql and validates your resolvers against it at startup.