-
Notifications
You must be signed in to change notification settings - Fork 0
FAQ
Common questions about using Graphite.
Graphite is a type-safe GraphQL client library for Java/Spring Boot. It generates Java code from your GraphQL schema, providing compile-time type safety and IDE support for building queries.
| Feature | Graphite | Apollo Android | DGS Codegen |
|---|---|---|---|
| Type-safe queries | Yes | Yes | Yes |
| Spring Boot integration | Native | Manual | Native |
| Runtime reflection | No | Minimal | Yes |
| GraalVM support | Native | Limited | Limited |
| Retry support | Built-in | Manual | Manual |
| Rate limiting | Built-in | Manual | Manual |
| Metrics | Built-in | Manual | Partial |
Java 21 or higher. Graphite uses modern Java features like records and pattern matching.
Yes. Graphite uses no runtime reflection, making it fully compatible with GraalVM native image compilation.
You need an introspection schema in JSON format. Common ways to obtain it:
-
graphql-cli:
graphql get-schema --endpoint URL --json > schema.json - Postman/Insomnia: Run an introspection query and save the result
- GraphQL Playground: Download schema from the UI
- Server export: Many GraphQL servers can export their schema
Currently, Graphite only supports introspection JSON format. Support for SDL (.graphql) files is planned for a future release.
Regenerate whenever your GraphQL schema changes. This is typically:
- After updating the schema file
- As part of your CI/CD pipeline
- Before releases
- Update your local schema file
- Regenerate code:
./gradlew graphiteGenerate - Fix any compile errors in your code
- Update tests if needed
Breaking changes in the schema will cause compile errors, helping you catch issues early.
Currently, the generated code style is fixed. If you need customization, you can:
- Use interceptors to modify behavior
- Extend generated classes in your code
- Request features via GitHub issues
Use the selection builder:
GetUserQuery.builder()
.id("123")
.selecting(s -> s
.id()
.name()
.email()
// Only these fields will be requested
)
.build();Variables are passed as builder parameters:
GetUserQuery.builder()
.id("123") // Variable: $id
.includeEmail(true) // Variable: $includeEmail
.build();Graphite generates flat selection builders. The generated code optimizes queries automatically. For complex selection reuse, create helper methods:
private void selectUserFields(UserSelection s) {
s.id().name().email();
}
var query = GetUserQuery.builder()
.selecting(this::selectUserFields)
.build();Nullable fields return @Nullable types. Handle them appropriately:
UserDTO user = response.data();
String email = user.email(); // May be null
if (email != null) {
sendEmail(email);
}Or use Optional:
Optional.ofNullable(user.email())
.ifPresent(this::sendEmail);-
GraphQL errors: In the response body, accessible via
response.errors(). The request succeeded but had issues. -
Exceptions: Network failures, timeouts, etc. Thrown as
GraphiteExceptionsubclasses.
-
Use
getData()when you want to handle errors yourself:if (response.hasErrors()) { handleErrors(response.errors()); } return response.data();
-
Use
getDataOrThrow()when errors should be exceptional:return response.getDataOrThrow(); // Throws if errors present
GraphQL can return both data and errors. Check for both:
var response = client.execute(query);
if (response.hasErrors()) {
log.warn("Partial errors: {}", response.errors());
}
if (response.data() != null) {
processData(response.data());
}Use Spring profiles:
# application-dev.yml
graphite:
url: http://localhost:8080/graphql
# application-prod.yml
graphite:
url: https://api.production.com/graphqlStatic headers via config:
graphite:
headers:
Authorization: Bearer ${TOKEN}Dynamic headers via interceptor:
client = GraphiteClient.builder()
.requestInterceptor(req ->
req.withHeader("Authorization", "Bearer " + getToken()))
.build();graphite:
retry:
enabled: true
max-attempts: 3
initial-delay: 100ms
multiplier: 2.0
max-delay: 5sThis is not supported directly for security reasons. For development, use:
- A proper development certificate
- A local GraphQL server without SSL
- A proxy that terminates SSL
Use GraphiteMockServer:
try (GraphiteMockServer server = GraphiteMockServer.create()) {
server.stubQuery("GetUser", Map.of("id", "1", "name", "Test"));
GraphiteClient client = GraphiteClient.builder()
.endpoint(URI.create(server.getUrl()))
.build();
// Your test code
}// GraphQL errors
server.stubError("GetUser",
GraphQLError.builder()
.message("Not found")
.build());
// HTTP errors
server.stubHttpError("GetUser", 500);
// Timeouts
server.stubWithDelay("GetUser", 5000, data);Yes, GraphiteMockServer wraps WireMock:
server.getWireMockServer().stubFor(
post("/graphql")
.willReturn(aResponse().withStatus(200))
);- Connection pooling: Configure appropriate pool size
-
Async execution: Use
executeAsync()for concurrent requests - Field selection: Only request needed fields
- Caching: Implement application-level caching
- Rate limiting: Prevent server overload
Yes. GraphiteClient is thread-safe and designed for concurrent use. Create one instance and share it.
Usually no. A single GraphiteClient can handle many concurrent requests. Create multiple clients only if you need:
- Different configurations (timeouts, headers)
- Connection to different GraphQL servers
- Isolation for testing
-
graphite.client.requests- Request count by operation/status -
graphite.client.request.duration- Request timing -
graphite.client.retry.attempts- Retry counts -
graphite.http.connections.*- Connection pool metrics
Add Micrometer Tracing to your classpath:
implementation("io.micrometer:micrometer-tracing")
implementation("io.micrometer:micrometer-tracing-bridge-otel") // or braveTrace context is propagated automatically.
Use MDC keys in your log format:
<pattern>%d [%X{graphite.operation}] [%X{graphite.requestId}] %msg%n</pattern>- Add Graphite dependencies
- Generate code from your schema
- Replace client initialization
- Update query calls to use generated builders
- Update error handling to use Graphite exceptions
- Update tests to use
GraphiteMockServer
Yes. Graphite doesn't conflict with other GraphQL libraries. You can migrate incrementally.
GitHub Issues - use the feature request template.
Not currently. For enterprise needs, please open a GitHub issue to discuss.