CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-springframework-boot--spring-boot-starter-graphql

Starter for building GraphQL applications with Spring GraphQL

Pending
Overview
Eval results
Files

web-integration.mddocs/

Web Integration

Spring Boot GraphQL Starter provides seamless integration with both Spring MVC (servlet-based) and Spring WebFlux (reactive) web stacks. The integration includes HTTP endpoints, WebSocket support, Server-Sent Events, and comprehensive transport layer configuration.

Spring MVC Integration

Auto-configuration for servlet-based applications using Spring MVC.

Auto-Configuration Class

@AutoConfiguration(after = GraphQlAutoConfiguration.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass({ GraphQL.class, GraphQlHttpHandler.class })
@ConditionalOnBean(ExecutionGraphQlService.class)
@EnableConfigurationProperties(GraphQlCorsProperties.class)
public class GraphQlWebMvcAutoConfiguration {
    // MVC-specific GraphQL configuration
}

Core MVC Beans

GraphQlHttpHandler

Handles HTTP POST requests to the GraphQL endpoint.

@Bean
@ConditionalOnMissingBean
public GraphQlHttpHandler graphQlHttpHandler(WebGraphQlHandler webGraphQlHandler) {
    return new GraphQlHttpHandler(webGraphQlHandler);
}

GraphQlSseHandler

Handles Server-Sent Events for GraphQL subscriptions over HTTP.

@Bean
@ConditionalOnMissingBean
public GraphQlSseHandler graphQlSseHandler(
    WebGraphQlHandler webGraphQlHandler, 
    GraphQlProperties properties
) {
    return new GraphQlSseHandler(
        webGraphQlHandler,
        properties.getHttp().getSse().getTimeout(),
        properties.getHttp().getSse().getKeepAlive()
    );
}

WebGraphQlHandler

Web-specific GraphQL handler with interceptor support.

@Bean
@ConditionalOnMissingBean
public WebGraphQlHandler webGraphQlHandler(
    ExecutionGraphQlService service,
    ObjectProvider<WebGraphQlInterceptor> interceptors
) {
    return WebGraphQlHandler.builder(service)
        .interceptors(interceptors.orderedStream().toList())
        .build();
}

Router Function Configuration

Configures routing for GraphQL endpoints using Spring's functional routing.

@Bean
@Order(0)
public RouterFunction<ServerResponse> graphQlRouterFunction(
    GraphQlHttpHandler httpHandler,
    GraphQlSseHandler sseHandler,
    ObjectProvider<GraphQlSource> graphQlSourceProvider,
    GraphQlProperties properties
) {
    String path = properties.getHttp().getPath();
    RouterFunctions.Builder builder = RouterFunctions.route();
    
    // Main GraphQL endpoint
    builder.route(GraphQlRequestPredicates.graphQlHttp(path), httpHandler::handleRequest);
    
    // Server-Sent Events endpoint  
    builder.route(GraphQlRequestPredicates.graphQlSse(path), sseHandler::handleRequest);
    
    // Error handling
    builder.POST(path, this::unsupportedMediaType);
    builder.GET(path, this::onlyAllowPost);
    
    // Optional GraphiQL endpoint
    if (properties.getGraphiql().isEnabled()) {
        GraphiQlHandler graphiQLHandler = new GraphiQlHandler(path, properties.getWebsocket().getPath());
        builder.GET(properties.getGraphiql().getPath(), graphiQLHandler::handleRequest);
    }
    
    // Optional schema printer endpoint
    if (properties.getSchema().getPrinter().isEnabled()) {
        SchemaHandler schemaHandler = new SchemaHandler(graphQlSource);
        builder.GET(path + "/schema", schemaHandler::handleRequest);
    }
    
    return builder.build();
}

WebSocket Support (MVC)

WebSocket configuration for GraphQL subscriptions in servlet applications.

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ ServerContainer.class, WebSocketHandler.class })
@ConditionalOnProperty("spring.graphql.websocket.path")
public static class WebSocketConfiguration {
    
    @Bean
    @ConditionalOnMissingBean
    public GraphQlWebSocketHandler graphQlWebSocketHandler(
        WebGraphQlHandler webGraphQlHandler,
        GraphQlProperties properties,
        HttpMessageConverters converters
    ) {
        return new GraphQlWebSocketHandler(
            webGraphQlHandler,
            getJsonConverter(converters),
            properties.getWebsocket().getConnectionInitTimeout(),
            properties.getWebsocket().getKeepAlive()
        );
    }
    
    @Bean
    public HandlerMapping graphQlWebSocketMapping(
        GraphQlWebSocketHandler handler,
        GraphQlProperties properties
    ) {
        String path = properties.getWebsocket().getPath();
        WebSocketHandlerMapping mapping = new WebSocketHandlerMapping();
        mapping.setWebSocketUpgradeMatch(true);
        mapping.setUrlMap(Collections.singletonMap(path, 
            handler.initWebSocketHttpRequestHandler(new DefaultHandshakeHandler())));
        mapping.setOrder(-2); // Higher priority than HTTP endpoint
        return mapping;
    }
}

Spring WebFlux Integration

Auto-configuration for reactive applications using Spring WebFlux.

Auto-Configuration Class

@AutoConfiguration(after = GraphQlAutoConfiguration.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
@ConditionalOnClass({ GraphQL.class, org.springframework.graphql.server.webflux.GraphQlHttpHandler.class })
@ConditionalOnBean(ExecutionGraphQlService.class)
@EnableConfigurationProperties(GraphQlCorsProperties.class)
public class GraphQlWebFluxAutoConfiguration {
    // WebFlux-specific GraphQL configuration
}

Core WebFlux Beans

Reactive GraphQlHttpHandler

Handles reactive HTTP requests using WebFlux.

@Bean
@ConditionalOnMissingBean
public org.springframework.graphql.server.webflux.GraphQlHttpHandler graphQlHttpHandler(
    WebGraphQlHandler webGraphQlHandler
) {
    return new org.springframework.graphql.server.webflux.GraphQlHttpHandler(webGraphQlHandler);
}

Reactive GraphQlSseHandler

Handles reactive Server-Sent Events for subscriptions.

@Bean
@ConditionalOnMissingBean
public org.springframework.graphql.server.webflux.GraphQlSseHandler graphQlSseHandler(
    WebGraphQlHandler webGraphQlHandler,
    GraphQlProperties properties
) {
    return new org.springframework.graphql.server.webflux.GraphQlSseHandler(
        webGraphQlHandler,
        properties.getHttp().getSse().getTimeout(),
        properties.getHttp().getSse().getKeepAlive()
    );
}

Reactive Router Function

@Bean
@Order(0)
public RouterFunction<ServerResponse> graphQlRouterFunction(
    org.springframework.graphql.server.webflux.GraphQlHttpHandler httpHandler,
    org.springframework.graphql.server.webflux.GraphQlSseHandler sseHandler,
    ObjectProvider<GraphQlSource> graphQlSourceProvider,
    GraphQlProperties properties
) {
    // Similar structure to MVC but using reactive handlers
    return RouterFunctions.route()
        .POST(path, accept(MediaType.APPLICATION_JSON), httpHandler::handleRequest)
        .GET(path, accept(MediaType.TEXT_EVENT_STREAM), sseHandler::handleRequest)
        // Additional routing configuration
        .build();
}

CORS Configuration

Cross-Origin Resource Sharing configuration for GraphQL endpoints.

CORS Auto-Configuration

@Configuration(proxyBeanMethods = false)
public static class GraphQlEndpointCorsConfiguration implements WebMvcConfigurer {
    
    private final GraphQlProperties graphQlProperties;
    private final GraphQlCorsProperties corsProperties;
    
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        CorsConfiguration configuration = this.corsProperties.toCorsConfiguration();
        if (configuration != null) {
            registry.addMapping(this.graphQlProperties.getHttp().getPath())
                .combine(configuration);
        }
    }
}

CORS Usage Examples

// Custom CORS configuration
@Configuration
public class GraphQlCorsConfig {
    
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOriginPatterns(List.of("https://*.example.com"));
        configuration.setAllowedMethods(List.of("GET", "POST"));
        configuration.setAllowedHeaders(List.of("*"));
        configuration.setAllowCredentials(true);
        
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/graphql", configuration);
        return source;
    }
}

Request/Response Handling

Request Predicates

GraphQL-specific request matching predicates.

public final class GraphQlRequestPredicates {
    
    // Match GraphQL HTTP requests (POST with application/json)
    public static RequestPredicate graphQlHttp(String path) {
        return RequestPredicates.POST(path)
            .and(RequestPredicates.accept(MediaType.APPLICATION_JSON))
            .and(RequestPredicates.contentType(MediaType.APPLICATION_JSON));
    }
    
    // Match GraphQL SSE requests (GET with text/event-stream)
    public static RequestPredicate graphQlSse(String path) {
        return RequestPredicates.GET(path)
            .and(RequestPredicates.accept(MediaType.TEXT_EVENT_STREAM));
    }
}

Error Handling

Built-in error responses for unsupported requests.

// Unsupported media type response
private ServerResponse unsupportedMediaType(ServerRequest request) {
    return ServerResponse.status(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
        .headers(headers -> headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)))
        .build();
}

// Method not allowed response  
private ServerResponse onlyAllowPost(ServerRequest request) {
    return ServerResponse.status(HttpStatus.METHOD_NOT_ALLOWED)
        .headers(headers -> headers.setAllow(Collections.singleton(HttpMethod.POST)))
        .build();
}

Web GraphQL Interceptors

Implement cross-cutting concerns for web GraphQL requests.

WebGraphQlInterceptor Interface

public interface WebGraphQlInterceptor {
    Mono<WebGraphQlResponse> intercept(WebGraphQlRequest request, WebGraphQlInterceptorChain chain);
}

Implementation Example

@Component
public class AuthenticationInterceptor implements WebGraphQlInterceptor {
    
    @Override
    public Mono<WebGraphQlResponse> intercept(WebGraphQlRequest request, WebGraphQlInterceptorChain chain) {
        // Extract authentication from request headers
        String token = extractAuthToken(request);
        
        if (token == null) {
            return Mono.error(new GraphQlAuthenticationException("Authentication required"));
        }
        
        // Validate token and set context
        return validateToken(token)
            .flatMap(user -> {
                request.configureExecutionInput((executionInput, builder) -> 
                    builder.graphQLContext(context -> context.put("currentUser", user))
                );
                return chain.next(request);
            });
    }
}

Transport Protocols

HTTP Transport

Standard HTTP POST requests with JSON payload:

// Example HTTP request
POST /graphql
Content-Type: application/json

{
  "query": "query GetBooks { books { id title author } }",
  "variables": {},
  "operationName": "GetBooks"
}

Server-Sent Events

For GraphQL subscriptions over HTTP:

// JavaScript SSE client example
const eventSource = new EventSource('/graphql?query=subscription{bookAdded{id title}}');
eventSource.onmessage = function(event) {
    const data = JSON.parse(event.data);
    console.log('Subscription update:', data);
};

WebSocket Transport

GraphQL over WebSocket using graphql-ws protocol:

// WebSocket client example
const client = new GraphQLWsClient({
    url: 'ws://localhost:8080/graphql-ws',
    connectionParams: {
        authToken: 'Bearer ...'
    }
});

client.subscribe({
    query: 'subscription { bookAdded { id title } }'
}, {
    next: (data) => console.log('Subscription data:', data),
    error: (err) => console.error('Subscription error:', err),
    complete: () => console.log('Subscription complete')
});

Development Tools Integration

GraphiQL Interface

Built-in GraphQL IDE for development:

# Enable GraphiQL
spring.graphql.graphiql.enabled=true
spring.graphql.graphiql.path=/graphiql

GraphiQL provides:

  • Interactive query editor with syntax highlighting
  • Schema explorer and documentation
  • Query variables and headers support
  • Subscription testing capabilities

Schema Printer

Development endpoint to view the complete GraphQL schema:

# Enable schema printer endpoint
spring.graphql.schema.printer.enabled=true

Access schema at: GET /graphql/schema

Performance Considerations

Connection Pooling

WebSocket connections are pooled and managed automatically:

# WebSocket connection timeout
spring.graphql.websocket.connection-init-timeout=30s

# Keep-alive for idle connections
spring.graphql.websocket.keep-alive=15s

Request Batching

HTTP endpoint supports GraphQL request batching:

// Batch multiple operations in single HTTP request
POST /graphql
Content-Type: application/json

[
  {"query": "query GetBooks { books { id title } }"},
  {"query": "query GetAuthors { authors { id name } }"}
]

Caching Headers

Automatic HTTP caching headers for non-subscription queries:

Cache-Control: public, max-age=300
ETag: "schema-hash-query-hash"

Install with Tessl CLI

npx tessl i tessl/maven-org-springframework-boot--spring-boot-starter-graphql

docs

configuration-properties.md

core-infrastructure.md

data-integration.md

index.md

observability-integration.md

security-integration.md

testing-support.md

transport-support.md

web-integration.md

tile.json