What is schema-first GraphQL development in Spring for GraphQL, and where do you put the schema files?
answer
- SDL .graphqls = source of truth
- classpath:graphql/**/ default location
- folder graphql, extension .graphqls
- @QueryMapping resolves fields
- schema-first vs code-first
basics
~10 sYou write the GraphQL schema by hand in SDL (.graphqls) files. Spring Boot loads them from classpath:graphql/ by default and builds the schema from them; your Java code just supplies the data.
solid answer
~40 sSchema-first means the GraphQL schema — the contract of types, queries, and mutations — is authored by hand in SDL (Schema Definition Language) text files, not generated from Java classes. In a Spring Boot app using the spring-boot-starter-graphql, you place .graphqls (or .gql) files under src/main/resources/graphql/. On startup the GraphQL auto-configuration discovers every file matching classpath:graphql/**/, parses and merges them into one schema, and exposes it. You then write controller methods (e.g. @QueryMapping) that resolve each field. The schema file is the single source of truth: the API shape is defined there, and Java code only fills in how each field's data is fetched. This contrasts with code-first, where the schema is derived programmatically from code.
code
java · 19 lines// src/main/resources/graphql/schema.graphqls
// type Query { book(id: ID!): Book }
// type Book { id: ID! title: String! author: String }
@Controller
class BookController {
private final BookRepository repository;
BookController(BookRepository repository) {
this.repository = repository;
}
// Field name 'book' under type Query is matched by method name.
@QueryMapping
public Book book(@Argument String id) {
return repository.findById(id).orElse(null);
}
}go deeper
Know: hand-written SDL, .graphqls files under resources/graphql/, code supplies data.
Explain the default location property and that multiple files merge into one schema.
Contrast schema-first vs code-first and articulate why Spring favors schema-first (contract-as-doc, versioned SDL).
Discuss governance: SDL as a reviewable, diffable contract; schema linting and breaking-change detection in CI.
**GraphQL** is a query language for APIs where the server publishes a strongly-typed **schema** describing every type, query, and mutation clients can use; clients ask for exactly the fields they want. **Schema-first vs code-first.** There are two ways to define that schema. *Code-first* builds the schema programmatically from Java/Kotlin (e.g. GraphQL-Java's `GraphQLObjectType` builders or a library like Netflix DGS annotations). *Schema-first* — the approach Spring for GraphQL is built around — means you write the schema by hand in **SDL (Schema Definition Language)**, a plain-text notation, and keep it as `.graphqls` files. SDL is the source of truth; code only implements resolvers. **Where the files go.** `spring-boot-starter-graphql` auto-configures schema loading. By default it looks at the property `spring.graphql.schema.locations`, whose default value is `classpath:graphql/**/`, and file extensions from `spring.graphql.schema.file-extensions` defaulting to `.graphqls,.gqls`. So conventionally you create `src/main/resources/graphql/schema.graphqls`. You can split the schema across many files in that folder (and subfolders, because of `**/`); Spring reads and **merges** them all into one schema. You can also override the location property to point elsewhere. **What SDL looks like.** A minimal schema: ```graphql type Query { book(id: ID!): Book } type Book { id: ID! title: String! author: String } ``` `type Query` is the special root type for reads; `type Mutation` for writes; `type Subscription` for streaming. `!` means non-null, `[Book]` a list. **How Spring uses it.** On startup the auto-configured `GraphQlSource` bean reads the SDL, builds a `graphql.schema.GraphQLSchema`, and wires each field to a resolver. Resolvers are typically **annotated controller** methods: `@QueryMapping Book book(@Argument String id)`. The method name matches the schema field (or you name it explicitly). Java DTO field names are matched to schema fields automatically for simple properties. **Gotchas.** (1) The schema file must exist — with no `.graphqls` under the location and no programmatic schema, startup fails ("No schema files"). (2) The folder is `graphql`, not `graphqls`; the *extension* is `.graphqls`. (3) Every non-scalar field a client can request needs a resolver or a matching DTO property; Spring Boot can log a **schema-mapping inspection report** warning about schema fields with no backing. **When to use schema-first.** It is the idiomatic Spring choice and preferred when the API contract is designed up front, shared with front-end/other teams, or reviewed independently of implementation — the SDL doubles as human-readable documentation and can be linted/diffed in version control.
- What is the default classpath location and file extension Spring scans for schema files?Location default is classpath:graphql/**/ (property spring.graphql.schema.locations); extensions default to .graphqls and .gqls (spring.graphql.schema.file-extensions). Conventionally src/main/resources/graphql/schema.graphqls.
- If you have three .graphqls files in that folder, what happens?Spring reads and merges all matching files into a single GraphQLSchema. You can split one logical schema across many files, e.g. one per domain type.