Running a GraphQL service
Table of contents
First, You need the armeria-graphql dependency:
dependencies {
implementation platform('com.linecorp.armeria:armeria-bom:1.33.4')
...
implementation 'com.linecorp.armeria:armeria-graphql'
}Let's assume we have the following GraphQL Schema:
type Query {
user(id: ID): User
}
type User {
id: ID
name: String
}The schema describes that if a client requests a User data using the ID field, the GraphQL server will
return the User data. The GraphQL engine uses a DataFetcher
to resolve the ID and fetch the corresponding object. For the sake of simplicity, let's implement
UserDataFetcher that stores Users in a Map:
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
class UserDataFetcher implements DataFetcher<User> {
private final Map<String, User> data = Map.of("1", new User("1", "hero"),
"2", new User("2", "human"),
"3", new User("3", "droid"));
@Override
public User get(DataFetchingEnvironment environment) throws Exception {
final String id = environment.getArgument("id");
return data.get(id);
}
}GraphqlService
Once you've finished the implementation of the DataFetcher, you need to build a GraphqlService using
a GraphqlServiceBuilder and add it to the ServerBuilder:
import com.linecorp.armeria.server.Server;
import com.linecorp.armeria.server.ServerBuilder;
import com.linecorp.armeria.server.graphql.GraphqlService;
ServerBuilder sb = Server.builder();
...
sb.service("/graphql",
GraphqlService.builder()
.runtimeWiring(c -> {
c.type("Query",
typeWiring -> typeWiring.dataFetcher("user", new UserDataFetcher()));
})
.build());
...
Server server = sb.build();
server.start();We used RuntimeWiring to wire the type with DataFetcher. Please see Creating a schema using the SDL to find more wiring examples.
Blocking service implementation
Armeria does not run service logic in a separate thread pool by default. If your service implementation
requires blocking, either run the individual blocking logic in a thread pool, or set
GraphqlServiceBuilder.useBlockingTaskExecutor() to true so the service runs in
all service methods and lifecycle callbacks.
ServerBuilder sb = Server.builder();
sb.service("/graphql",
GraphqlService.builder()
.runtimeWiring(c -> {
c.type("Query",
typeWiring -> typeWiring.dataFetcher("user", new UserDataFetcher()));
})
// All service methods will be run within
// the blocking executor.
.useBlockingTaskExecutor(true)
.build());