Skip to content

2. Getting Started

Balf edited this page Aug 25, 2024 · 3 revisions

Getting started

Installation

The GraphQL SPQR package is available via Maven Central.

Maven

<dependency>
    <groupId>io.leangen.graphql</groupId>
    <artifactId>spqr</artifactId>
    <version>0.12.4</version>
</dependency>

Gradle

compile 'io.leangen.graphql:spqr:0.12.3'

Hello World

Let's start with a basic example, using annotations provided by GraphQL SPQR.

First we need an entrypoint from which GraphQL SPQR can generate the schema. This can be either a bean or a service. For this example we will use a simple service:

class UserService {

    @GraphQLQuery(name = "user")
    public User getById(@GraphQLArgument(name = "id") Integer id) {
      ...
    }
}

The GraphQLQuery annotation in the code above makes a Query available within the schema which will return a User for the given ID. The method returns a User Pojo, which is automatically registered to the GraphQLSchema as a User type.

The GraphQLArgument annotation is there to add the id parameter to the schema. If you want to skip adding @GraphQLArgument, compile with the -parameters option or the names will be lost.

public class User {

    private String name;
    private Integer id;
    private Date registrationDate;

    @GraphQLQuery(name = "name", description = "A person's name")
    public String getName() {
        return name;
    }

    @GraphQLQuery
    public Integer getId() {
        return id;
    }

    @GraphQLQuery(name = "regDate", description = "Date of registration")
    public Date getRegistrationDate() {
        return registrationDate;
    }
}

Now we need to generate the schema based on the UserService:

UserService userService = new UserService(); //instantiate the service (or inject by Spring or another framework)
GraphQLSchema schema = new GraphQLSchemaGenerator()
        .withBasePackages("io.leangen") //not mandatory but strongly recommended to set your "root" packages
        .withOperationsFromSingleton(userService) //register the service
        .generate(); //done ;)
GraphQL graphQL = new GraphQL.Builder(schema)
        .build();

//keep the reference to GraphQL instance and execute queries against it.
//this operation selects a user by ID and requests name, regDate and twitterProfile fields only
ExecutionResult result = graphQL.execute(
        "{ user (id: 123) {
            name,
            regDate
         }}");

The GraphQLQuery annotation supports the following parameters:

  • name allows you to customize the field name, if omitted the method name will be used to create the fieldname, so for example getName will lead to the name name.
  • description - allows you to add a description to the field, which will be added to the schema. This is especially useful for consumers of your GraphQL API as it gives them more information on the field
  • deprecationReason - if the method is also annotated with @Deprecated you can add a reason why here, which is also reflected in the Schema.

More on schema generation

By default GraphQL SPQR uses the AnnotatedResolverBuilder to detect which methods in the UserService should be added to the GraphQL schema, meaning that only explicitly annotated methods are taken into account when generating the schema.

Alternatively you can configure GraphQL SPQR to use the BeanResolverBuilder to register all public methods within the UserService to the GraphQL schema. You can configure the ResolverBuilder to use via the SchemaGenerator:

GraphQLSchema schema = new GraphQLSchemaGenerator()
        ...
        .withResolverBuilders(new BeanResolverBuilder())
        ...
        .generate(); //done ;)

This setting only applies to top level operations, meaning the first level of operations within the Query type. For lower level operations SPQR uses the AnnotatedResolverBuilder, BeanResolverBuilder and the RecordResolverBuilder by default, in that specific order. If a method within an Object has already been parsed by one of the preceding ResolverBuilders it is not parsed again by any other ResolverBuilder.

The reasoning behind is that the user usually has tight control over the service that exposes the top level operations, while the underlying Objects might come from a framework or another 3rd party component.

Clone this wiki locally