Maven Central NuGet v1.0.0 MIT

eu.metaengine:metaengine-graphql-java-spring-maven-plugin

GraphQL SDL → Java Spring services and models, delivered as a Maven plugin. Typed queries, mutations & subscriptions over RestClient (subscriptions via spring-graphql WebSocketGraphQlClient → Flux), with bearer/basic auth, retries, timeouts, and error handling — generated straight into your build at generate-sources.

GraphQL SDLMetaEngine IRJava · Spring
Install

Pick your registry

The same generator, published to every ecosystem we support. Install however your project expects.

Maven CentralPrimaryeu.metaengine:metaengine-graphql-java-spring-maven-plugin
$eu.metaengine:metaengine-graphql-java-spring-maven-plugin
v1.0.0
NuGetMetaEngine.Java.GraphQL.Spring
$dotnet add package MetaEngine.Java.GraphQL.Spring
v1.0.0
Usage

Drive it from Maven or programmatically

Maven Central ships a build-time plugin that runs inside your build. NuGet ships the same generator as a C# fluent API — same options, same output.

Maven Central · build-time plugin

Add the plugin to your pom.xml. Its generate goal binds to the generate-sources phase, so the Spring client and models are produced — and added to your compile roots — on every mvn compile or package. Point <inputSpec> at a GraphQL SDL file or URL and set the target <packageName>.

Plugin setup
pom.xml
<build>
  <plugins>
    <plugin>
      <groupId>eu.metaengine</groupId>
      <artifactId>metaengine-graphql-java-spring-maven-plugin</artifactId>
      <version>1.0.0</version>
      <executions>
        <execution>
          <id>generate-graphql-client</id>
          <goals>
            <goal>generate</goal>
          </goals>
          <configuration>
            <inputSpec>${project.basedir}/src/main/resources/schema.graphql</inputSpec>
            <packageName>com.example.api</packageName>
          </configuration>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

The generate goal binds to the generate-sources phase, so a normal mvn compile (or package) produces the client and registers it as a compile source root — no extra wiring. <inputSpec> accepts a local path or an http(s) URL; GraphQL SDL is also accepted as inline content. Queries, mutations and subscriptions are generated (subscriptions resolve to a Flux<T> over spring-graphql WebSocketGraphQlClient).

Configuration examples
Auth, retries and a request timeout
<configuration>
  <inputSpec>${project.basedir}/schema.graphql</inputSpec>
  <packageName>com.example.api</packageName>
  <bearerAuth>API_TOKEN</bearerAuth>
  <timeout>30</timeout>
  <retry>3</retry>
  <errorHandling>true</errorHandling>
</configuration>
Named fragments, JavaDoc and a custom base-url property
<configuration>
  <inputSpec>https://api.example.com/schema.graphql</inputSpec>
  <packageName>com.example.api</packageName>
  <fragments>true</fragments>
  <baseUrlProperty>api.base-url</baseUrlProperty>
  <documentation>true</documentation>
</configuration>
Basic auth and a tenant header from env vars
<configuration>
  <inputSpec>${project.basedir}/schema.graphql</inputSpec>
  <packageName>com.example.api</packageName>
  <basicAuth>API_USER,API_PASS</basicAuth>
  <customHeaders>
    <customHeader>X-Tenant-ID:TENANT_ID</customHeader>
  </customHeaders>
</configuration>
Configuration
Element
Description
<inputSpec>
GraphQL SDL — local file path, http(s) URL, or inline SDL content. Required.
<packageName>
Java package for the generated code, e.g. com.example.api. Required.
<outputDirectory>
Output directory [default: ${project.build.directory}/generated-sources/metaengine]. Added to the compile source roots.
<baseUrlProperty>
Spring property name for base-URL injection [default: api.base-url]
<documentation>
Generate JavaDoc comments from SDL descriptions [default: false]
<fragments>
Emit reusable named fragments for object-type selections [default: false]
<oneOfInputs>
Generate idiomatic @oneOf tagged-union input types [default: false]
<bearerAuth>
Env var holding the bearer token — adds an Authorization header to every request
<bearerAuthHeader>
Custom header name for the bearer token [default: Authorization]. Requires bearerAuth.
<basicAuth>
HTTP Basic auth from env vars, format USER_VAR,PASS_VAR
<customHeaders>
Static headers from env vars (Header-Name:ENV_VAR) as <customHeader> children. Repeatable.
<timeout>
Request timeout in seconds (connect + read)
<timeoutConnect>
Connect timeout in seconds
<timeoutRead>
Read timeout in seconds
<retry>
Enable retries with exponential backoff [default attempts: 3]
<errorHandling>
Smart error handling on RestClient — status-aware null / error / throw [default: false]
<optionsThreshold>
Parameter count threshold for the options-object pattern [default: 4]
<clean>
Clean the output directory before generation (remove files not in generation) [default: false]
<verbose>
Enable verbose logging [default: false]
Options reference

Every knob, documented

Every option is available on the C# fluent API as a method; the Maven plugin exposes most as <configuration> elements. Cross-cutting auth, headers, retries and timeouts apply across frameworks.

Spring Options

3
  • WithBaseUrlProperty(string)Spring property placeholder for base-URL injection (default: "api.base-url"). Generated services bind it with @Value("${...}").
  • WithBeanValidation()Emit Jakarta Bean Validation annotations (@NotNull, @Min / @Max, @Size, @Pattern, @Email) on model records from schema constraints
  • WithNonNullSerialization()Add @JsonInclude(NON_NULL) to records so unset nullable fields drop out of the serialized JSON

Auth · Headers · Resilience

13
  • WithErrorHandling()Smart error handling on RestClient based on HTTP status (404 / 403 → null · 400 / 422 / 409 → error body · 401 / 5xx → throw). GraphQL operations travel over HTTP POST.
  • WithErrorHandling(errors => errors...)Per-status routing: ReturnNullFor(404, 403) · ReturnErrorFor(400, 422) · ThrowFor(401, 500)
  • WithBearerAuth()Bearer token from env var (default API_TOKEN) — adds Authorization header
  • WithBearerAuth(string)Bearer token from a specific env var name
  • WithBearerAuth(string, string)Bearer token with custom header name (e.g. X-Api-Key)
  • WithBasicAuth()HTTP Basic auth from default env vars (API_USERNAME / API_PASSWORD)
  • WithBasicAuth(string, string)HTTP Basic auth from username + password env vars
  • WithCustomHeader(string, string)Static header from env var. Repeatable (e.g. X-Tenant-ID ← TENANT_ID)
  • WithTimeout(double)Request timeout in seconds for all operations
  • WithTimeout(double?, double?, double?, double?)Granular timeout: connect · read · write · pool
  • WithRetries()Retries with exponential backoff (default status 429, 503)
  • WithRetries(int)Retries with custom max attempts
  • WithRetries(int, double, double, int[])Retries with full custom settings including status codes

Java Options

3
  • WithDocumentation()Generate JavaDoc comments on methods and parameters from the schema
  • WithMethodNames(Func)Custom method naming rule
  • WithOptionsObjectThreshold(int)Parameter count for options object (default: 4)

GraphQL Options

7
  • WithDocumentation()Generate JavaDoc comments from SDL type & field descriptions
  • WithFragments()Emit reusable named fragments for object-type selections (...TypeFields spreads)
  • WithOneOfInputs()Generate idiomatic @oneOf input types (tagged-union inputs where exactly one field is set)
  • WithCustomScalar(string, Type)Map a GraphQL custom scalar to a Java type (e.g. DateTime → OffsetDateTime). Unmapped scalars default to String
  • WithTypeFilter(Func)Filter extracted GraphQL types before registration — only types returning true are generated
  • WithMethodNames(Func)Custom method naming rule
  • WithOptionsObjectThreshold(int)Parameter count for options object (default: 4)

Naming Transformations

3
  • Types(Func)Transform type names
  • Paths(Func)Transform output paths
  • FileNames(Func)Transform file names

File Management

5
  • CleanDestination()Clean output directory before generation
  • AlwaysOverwrite()Always overwrite existing files
  • OnlyWhenModelChanged()Update only when model changes
  • OnlyWhenNew()Write only new files, preserve existing
  • CleanDirectories(...)Clean specific subdirectories

Diagnostics

1
  • EnableVerboseLogging()Enable detailed logging
Features

Why this package is different

Deterministic output
Same spec + same options produce byte-identical files. Safe to commit, safe to diff in review, safe to cache in CI.
Tree-shakeable
One file per tag (or per operation) means bundlers drop unused code at build time. No runtime dispatch table.
Zero runtime
Validation and clients opt in. The default emit is pure types with no dependency surface beyond your HTTP lib.
Flexible naming
Case conventions configurable per role — types, properties, operations, enums. Idiomatic in the target by default.
Type resolution
Discriminated unions for oneOf, proper nullability, bigint when the spec mandates it, refs flattened only when safe.
Semver-honest
Spec diff drives the version bump. Additive changes = minor, removed ops = major. Never a surprise in your lockfile.