How does Spring for GraphQL expose the GraphQL API over HTTP, and how do you enable the GraphiQL UI for exploring it?
answer
- single POST /graphql, body carries the query
- spring.graphql.path relocates it
- GraphiQL off by default -> enabled=true
- /graphiql playground is dev-only
- 200 OK + errors[] envelope
basics
~10 sSpring for GraphQL serves a single endpoint at POST /graphql. GraphiQL is a built-in in-browser query playground, disabled by default; enable it with spring.graphql.graphiql.enabled=true, then open /graphiql.
solid answer
~40 sThe spring-boot-starter-graphql auto-configuration maps one HTTP endpoint, POST /graphql (path configurable via spring.graphql.path). Clients send a JSON body with query, optional operationName, and variables; the response is a JSON envelope with data and errors. GraphQL uses one URL for everything — the operation type is in the request body, not the path or verb. GraphiQL is an official in-browser IDE (autocomplete, docs explorer, run queries) bundled with the starter but off by default. Turn it on with spring.graphql.graphiql.enabled=true and browse to /graphiql (path set by spring.graphql.graphiql.path). You typically enable it only in dev/staging because it exposes your full schema and lets anyone run queries. Schema files live under src/main/resources/graphql/*.graphqls by default.
code
java · 16 lines// application.properties
// spring.graphql.path=/graphql (default)
// spring.graphql.graphiql.enabled=true (turn on the in-browser IDE)
// spring.graphql.graphiql.path=/graphiql (default)
@Controller
class BookController {
@QueryMapping
public Book book(@Argument String id) { // resolves the `book(id: ID!)` field
return repository.findById(id);
}
}
// Schema at src/main/resources/graphql/schema.graphqls:
// type Query { book(id: ID!): Book }
// type Book { id: ID!, title: String }go deeper
Know it's one POST /graphql endpoint and that GraphiQL needs spring.graphql.graphiql.enabled=true.
Explain the JSON envelope, the 200-with-errors behavior, and why GraphiQL should be dev-only.
Discuss introspection hardening, content-type negotiation, and gating the playground behind profiles/auth.
Weigh GraphQL's single-endpoint model against REST for caching, observability, and gateway routing decisions.
**What Spring for GraphQL is.** Spring for GraphQL is the Spring integration on top of the graphql-java engine. Adding `spring-boot-starter-graphql` (usually alongside `spring-boot-starter-web` or `-webflux`) auto-configures a runnable GraphQL server. **The HTTP transport.** Unlike REST, GraphQL exposes a *single* endpoint. By default it is **`POST /graphql`** (change with the property `spring.graphql.path`). The HTTP method and URL never vary per operation — *what* you want is expressed entirely in the request body: ```json { "query": "query($id: ID!){ book(id:$id){ title } }", "operationName": null, "variables": { "id": "42" } } ``` The server always responds `200 OK` (even for GraphQL-level errors) with a JSON envelope: ```json { "data": { "book": { "title": "..." } }, "errors": [ ] } ``` `errors` is populated for validation or data-fetching failures; `data` and `errors` can coexist (partial results). Spring also supports **GET /graphql** for queries when explicitly used, and negotiates content type `application/graphql-response+json`. **Where the schema comes from.** By default Spring loads schema definition files matching `classpath:graphql/**/*.graphqls`. `@Controller` beans with `@QueryMapping`, `@MutationMapping`, `@SchemaMapping`, and `@SubscriptionMapping` methods supply the data fetchers. **GraphiQL.** GraphiQL (note the *i* — it is a specific open-source project, not just "graphical") is an in-browser IDE: schema documentation explorer, field autocomplete, and a console to run queries against your endpoint. The starter bundles a copy but it is **disabled by default**. Enable it: ```properties spring.graphql.graphiql.enabled=true # optional, defaults to /graphiql spring.graphql.graphiql.path=/graphiql ``` Then open `http://localhost:8080/graphiql`. **Gotchas / when-to-use.** - GraphiQL exposes your **entire schema** and lets any visitor run operations, so gate it: enable only in dev/staging, or put it behind auth. Do not ship it wide-open in production. - Introspection (the query GraphiQL uses to learn the schema) is on by default; you can disable it with `spring.graphql.schema.introspection.enabled=false` to harden production. - Because everything is one POST, standard REST tooling (per-path caching, HTTP verbs mapping to CRUD) does not apply — caching/observability are done differently. - 200-with-errors surprises people used to REST status codes; check the `errors` array, not the HTTP status, for GraphQL failures.
- Why does a GraphQL error still return HTTP 200?The GraphQL-over-HTTP convention puts operation-level errors in the response body's `errors` array rather than in the HTTP status, since one request can produce partial data plus errors. Transport-level failures (malformed JSON, unsupported media type) can still yield 4xx.
- How would you keep GraphiQL out of production?Bind spring.graphql.graphiql.enabled to a profile (e.g. set true only in application-dev.properties), or leave it false and additionally disable introspection with spring.graphql.schema.introspection.enabled=false to prevent schema discovery.
saying these in an interview costs you the question
- Thinking each GraphQL operation has its own URL/path like REST
- Believing GraphiQL is enabled by default
- Assuming GraphQL errors come back as HTTP 4xx/5xx
- Confusing GraphiQL (the IDE) with the /graphql endpoint itself