Federation

Spring for GraphQL provides an integration for the federation-jvm library, which uses GraphQL Java to initialize the schema of a sub-graph within a graph of federated services. See Apollo Federation and the Subgraph specification for details.

Config

To enable the integration, declare a FederationSchemaFactory bean in your config, and plug it into GraphQlSource.Builder. For example, with Spring Boot:

@Configuration
public class FederationConfig {

	@Bean
	public GraphQlSourceBuilderCustomizer customizer(FederationSchemaFactory factory) {
		return builder -> builder.schemaFactory(factory::createGraphQLSchema);
	}

	@Bean
	public FederationSchemaFactory schemaFactory() {
		return new FederationSchemaFactory();
	}
}

Now the schema for the sub-graph service can extend federated types:

type Book @key(fields: "id") @extends {
    id: ID! @external
    author: Author
}

type Author {
    id: ID
    firstName: String
    lastName: String
}

@EntityMapping

An @EntityMapping method can load federated type instances in response to an _entities query from the federation gateway. For example:

For example:

@Controller
private static class BookController {

	@EntityMapping
	public Book book(@Argument int id) { (1)
		// ...
	}

	@SchemaMapping
	public Author author(Book book) { (2)
		// ...
	}

}
1 The @Argument method parameter is resolved from the "representation" input map for the entity. The full "representation" input Map can also be resolved. See Method Signature for supported method argument and return value types.
2 @SchemaMapping methods can be used for the rest of the graph.

An @EntityMapping method can batch load federated entities of a given type. To do that, declare the @Argument method parameter as a list, and return the corresponding entity instances as a list in the same order.

For example:

@Controller
private static class BookController {

	@EntityMapping
	public List<Book> book(@Argument List<Integer> idList) { (1)
		// ... return books in the same order
	}

	@BatchMapping
	public Map<Book, Author> author(List<Book> books) { (2)
		// ...
	}
}
1 The idList naming convention helps to de-pluralize the parameter name in order to look up the correct value in the "representation" input map. You can also set the argument name through the annotation.
2 @BatchMapping methods can be used for the rest of the graph.

Method Signature

Entity mapping methods support the following arguments:

Method Argument Description

@Argument

For access to a named value from the "representation" input map, also converted to typed Object.

Map<String, Object>

The full "representation" input map for the entity.

List<Map<String, Object>>

The list of "representation" input maps when using a single controller method to load all entities of a given type.

@ContextValue

For access to an attribute from the main GraphQLContext in DataFetchingEnvironment.

@LocalContextValue

For access to an attribute from the local GraphQLContext in DataFetchingEnvironment.

GraphQLContext

For access to the context from the DataFetchingEnvironment.

java.security.Principal

Obtained from the Spring Security context, if available.

@AuthenticationPrincipal

For access to Authentication#getPrincipal() from the Spring Security context.

DataFetchingFieldSelectionSet

For access to the selection set for the query through the DataFetchingEnvironment.

Locale, Optional<Locale>

For access to the Locale from the DataFetchingEnvironment.

DataFetchingEnvironment

For direct access to the underlying DataFetchingEnvironment.

@EntityMapping methods can return Mono, CompletableFuture, Callable, or the actual entity.

Exception Handling

You can use @GraphQlExceptionHandler methods to map exceptions from @EntityMapping methods to GraphQLError's. The errors will be included in the response of the "_entities" query. Exception handler methods can be in the same controller or in an @ControllerAdvice class.