Category Archives: GraphQL

Apollo GraphQL client

Based upon our previous implementation(s) of a server it’s now time to write some client code.

  • yarn add apollo-client
  • yarn add apollo-cache-inmemory
  • yarn add apollo-link-http
  • yarn add graphql-tag
  • yarn add isomorphic-fetch
  • yarn add -D @types/isomorphic-fetch

Now let’s create a simple script entry (this extends the previous post’s scripts section)

"scripts": {
  "build": "tsc",
  "client": "node client.js"
}

Now let’s create the file client.ts which should look like this

import ApolloClient from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { HttpLink } from 'apollo-link-http';
import gql from 'graphql-tag';
import fetch from 'isomorphic-fetch';

const cache = new InMemoryCache();
const link = new HttpLink({
  uri: 'http://localhost:4000/',
  fetch: fetch
})

const client = new ApolloClient({
  cache,
  link,
});

client.query({
  query: gql`
    {
    users {
      firstName
      lastName
    }
  }`
  })
  .then((response: any) => console.log(response.data.users));

The response.data.users should now output the array of User objects.

Here’s an example of a mutation

client.mutate({
  mutation: gql`
    mutation {
      create(user: {
        firstName: "Miner",
        lastName: "FortyNiner"
      }) {
        firstName
        lastName
      }
    }
  `
}).then((response: any) => console.log(response.data.create));

Note: I had lots of issues around the fetch code, with errors such as Invariant Violation:
fetch is not found globally and no fetcher passed, to fix pass a fetch for your environment like
https://www.npmjs.com/package/node-fetch.
. The addition of the isomorphic-fetch solved this problem.

Adding GraphQL to our Express server

In the previous two posts, we firstly create a basic server, then extended this with REST functionality, now lets add GraphQL capabilities.

First off, run the following

  • yarn add express-graphql graphql
  • Add a folder named schema

With the schema folder add a new file userSchema.ts with the following code

import { buildSchema } from "graphql";

export const schema = buildSchema(`
  type User {
    firstName: String
    lastName: String
  }

  type Query {
    users: [User]
  }
`);

In the above code, we create a GraphQL schema based upon our User type, along with the type Query for us to use the User type.

Next we’ll create a folder named resolvers along with the file userResolver.ts. GraphQL uses resolvers to interact with the data via GraphQL (like the code in the indexController in the previous post).

import { stubData } from "../models/user";

export const userResolver = {
  users: () => {
    return stubData;
  }
}

Now let’s update the server.ts file by adding the GraphQL code, I’ll include the whole file here (at least the specifics for GraphQL)

import graphqlHTTP from "express-graphql";
import { schema } from "./schema/userSchema";
import { userResolver } from "./resolvers/userResolver";

const server = express();

server.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: userResolver,
  graphiql: true,
}));

const port = 4000;
server.listen(port,
  () => console.log(`Server on port ${port}`)
);

In the above we’ve specified graphiql: true which allows us to via the GraphIQL page using http://localhost:4000/graphql

Now if you type the following into the left hand (query) pane

{
  users {
    firstName
    lastName
  }
}

Running this from GraphIQL should output all our stubData.

We’ve essentially got the users method from our original code but now let’s add the equivalent of the create method, which in GraphQL terms is a mutation type.

In the userSchema.ts file, change the schema to look like this

export const schema = buildSchema(`
  type User {
    firstName: String
    lastName: String
  }

  input UserInput {
    firstName: String
    lastName: String
  }

  type Mutation {
    create(user: UserInput): User
  }

  type Query {
    users: [User]
  }
`);

We’ve added an input type UserInput along with the type Mutation. Next, within the userResolve.ts file change the userResolve to add the create function, as below

export const userResolver = {
  users: () => {
    return stubData;
  },
  create: (data: any) => {
    stubData.push(new User(data.user.firstName, data.user.lastName)); 
    return data.user;
  }
}

Let’s test this code by executing the following query via GraphIQL

mutation {
  create(user: {
    firstName: "Miner",
    lastName: "FortyNiner",
  }) {
    firstName
    lastName
  }
}

Spring boot and GraphQL

A previous post Writing a GraphQL service using graphql-dotnet and ASP.NET core covered implementing an ASP.NET application with a GraphQL service.

As GraphQL is language/platform agnostic I wanted to see how to implement a similar little service using Java frameworks.

I’m using JetBrains’ IntelliJ (I think you need the ultimate edition for this) to create a project, so I’ll list a few steps regarding this process. In IntelliJ

  • Create a new Project
  • Select Spring Initializr
  • Leave the defaults as https://start.spring.io and just press the Next button
  • Supply a name for your project then press the Next button
  • At the next page you can select dependencies, just press the Next button
  • Finally give your project a name then press the Finish button

Now let’s update the pom.xml with the following

<!-- Add the following for GraphQL -->
<dependency>
   <groupId>com.graphql-java</groupId>
   <artifactId>graphql-spring-boot-starter</artifactId>
   <version>5.0.2</version>
</dependency>
<dependency>
   <groupId>com.graphql-java</groupId>
   <artifactId>graphql-java-tools</artifactId>
   <version>5.2.4</version>
</dependency>

<!-- Add this for the GraphQL interactive tool -->
<dependency>
   <groupId>com.graphql-java</groupId>
   <artifactId>graphiql-spring-boot-starter</artifactId>
   <version>4.0.0</version>
</dependency>

As shown with the comments, the last dependency will allow us to include the GraphQL interactive web application graphiql, obviously remove this if you do not need it.

Now let’s write some code…

Schema and Queries

Unlike the previous C# example, we’re going to use the GraphQL schema definition language to declare our schema (in C# we used code to implement this).

In your package folder add Person.java with the following code

public class Person {
    private String name;

    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

It’s basic but this is our starting point (and matches what we did in the C# example).

We now need to create a QueryResolver, so add a file named Query.java to the package with the following code

import com.coxautodev.graphql.tools.GraphQLQueryResolver;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component
public class Query implements GraphQLQueryResolver {
    List<Person> people = new ArrayList<>();

    public Query() {
        people.add(new Person("Scooby"));
        people.add(new Person("Shaggy"));
        people.add(new Person("Daphne"));
        people.add(new Person("Thelma"));
        people.add(new Person("Fred"));
    }

    public List<Person> people() {
        return people;
    }
}

That’s it for the Java code for now – Spring Boot’s dark magic will wire everything up for us, but before then we need to add a .graphqls file. Within the resources folder lets add a schema file named schema.graphqls (IntelliJ comes with a plugin for recognising this file type).

Note: the name of the file need not be schema, any name will suffice for this example.

Within the schema.graphqls file we have the following

type Query {
    people : [Person]
}

type Person {
    name: String!
}

That’s it!

Running the application will result in a Tomcat embedded server running on http://localhost:8080/graphiql (assuming you include graphiql in the Maven file). If we now execute the following query within graphiql

{
  people {
    name
  } 
}

we should see the result

{
  "data": {
    "people": [
      {
        "name": "Scooby"
      },
      {
        "name": "Shaggy"
      },
      {
        "name": "Daphne"
      },
      {
        "name": "Thelma"
      },
      {
        "name": "Fred"
      }
    ]
  }
}

Let’s now add an operation find to allow us to locate a Person by their name. In the Query class, add the following

public Person find(String input) {
   return people.stream()
      .filter(p -> p.getName().equalsIgnoreCase(input))
      .findFirst()
      .orElse(null);
}

This code acts a little like a Linq query in C#, returning an Optional, we’ll basically return a null if no item was found hence unwrapping our return from the Optional.

We need to add this operation to the schema.graphql Query type, so it now looks like this

type Query {
    people: [Person]
    find(input: String!) : Person
}

Running the application we can now write the following in graphiql

{
   find(input : "Scooby") {
      name
  }
}

Mutations

Next up, let’s write a mutation to add a person. We’re not going to add a Person to the list of people as this would require some refactoring of the query data, but it simply demonstrates the changes required to our project to implement mutations.

Let’s jump into the schema file and add mutation to the schema definition, so it looks like this

schema {
    query: Query
    mutation: Mutation
}

and now add the mutation type into the file, which should look like this

type Mutation {
    addPerson(input: String) : Person
}

Now we’ll create the code. Add a file (mine’s called Mutation.java) for our mutation code, here’s a the very simple example

import com.coxautodev.graphql.tools.GraphQLMutationResolver;
import org.springframework.stereotype.Component;

@Component
public class Mutation implements GraphQLMutationResolver {
    public Person addPerson(String input) {
        return new Person(input);
    }
}

That’s all there is to it, run the application and using grapiql, write the following in your query window

mutation addPerson($input : String) {
   addPerson(input : $input)
   {
      name
   }
}

and in the Query variables window add the following

{
  "input" : "Scooby Doo"
}

Subscriptions

Finally let’s write some subscription code. Change the schema.graphqls schema to look like this

schema {
    query: Query
    mutation: Mutation
    subscription : Subscription
}

and add the following type

type Subscription {
    personAdded : Person
}

The Subscription.java file will look like this

import com.coxautodev.graphql.tools.GraphQLSubscriptionResolver;
import org.reactivestreams.Publisher;
import org.springframework.stereotype.Component;

@Component
public class Subscription implements GraphQLSubscriptionResolver {

    private PersonPublisher publisher;

    public Subscription(PersonPublisher publisher) {
        this.publisher = publisher;
    }

    public Publisher<Person> personAdded() {
        return publisher.getPublisher();
    }
}

This implements our Subscription resolver, but we’ll separate out the publisher code to look like this. Here’s my PersonPublisher.java file

import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import io.reactivex.Observable;
import io.reactivex.observables.ConnectableObservable;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;

@Component
public class PersonPublisher {

    private final Flowable<Person> publisher;

    public PersonPublisher() {
        Observable<Person> o = Observable.interval(1, 1, TimeUnit.SECONDS)
                .map(l -> new Person(l.toString()));
        ConnectableObservable<Person> co = o.share().publish();

        publisher = co.toFlowable(BackpressureStrategy.BUFFER);
    }

    public Flowable<Person> getPublisher() {
        return publisher;
    }
}

Note: I’ve based the code for the Subcription and PersonPublisher on the Subscription.java and the StockTickerPublisher.java sample code.

Code

Code is available on GitHub.

Disclaimer

graphiql does not display subscription events at this time. So I’ve not tested this subscription code. Hence beware, it may or may not work. I’ll try to update when I get chance to test it fully.

Writing a GraphQL service using graphql-dotnet and ASP.NET core

Introduction

GraphQL is classified as a query language for querying your data.

I’m not going to go into a full description of it’s capabilities/uses, for that go to the GraphQL website, but one thing which has always interested me, is an API where the client application can tell the server API what data to return. Thus allow the client to reduce bandwidth as well as reduce the amount of data being deserialised to exactly what the client application requires – obviously particularly useful for mobile applications.

Using graphiql-dotnet and ASP.NET core

We’re going to be using graphql-dotnet and ASP.NET core to implement a basic

  • Create an ASP.NET Core Web Application, mine’s named GraphQLService
  • Select an Empty project
  • I’m going to uncheck “Configure for HTTPS”
  • Now add the following packages via NuGet
    • GraphQL.Server.Transports.AspNetCore
    • GraphQL.Server.Transports.WebSockets
    • GraphQL.Server.Ui.GraphiQL
    • GraphQL.Server.Ui.Playground
    • GraphQL.Server.Ui.Voyager
    • GraphQL-Parser

Note: We’ve added the GraphQL.Server.Ui.Playground package to allow us to write queries within an interactive environment (http://localhost:5000/ui/playground) which also allows us to view the schema definitions etc. We’ve added GraphQL.Server.Ui.Voyager which adds a cool schema/type viewer (http://localhost:5000/ui/voyager). Finally we’ve added GraphQL.Server.Ui.GraphiQL to allow us to use the well known GraphiQL interactive environment (http://localhost:5000/ui/graphiql), feel free to remove all or some of these as required.

Remove the code from the Configure method of the Startup.cs file except for the following

if (env.IsDevelopment())
{
   app.UseDeveloperExceptionPage();
}

Now we’re going to add some tools, the playground (an interactive query web app) the voyager for digging into the schema and the GraphQL endpoint. So add the following to the Startup.cs below the code shown above

app.UseWebSockets();
app.UseGraphQLWebSockets<PersonSchema>("/graphql");
app.UseGraphQL<PersonSchema>("/graphql");
app.UseGraphQLPlayground(new GraphQLPlaygroundOptions()
{
   Path = "/ui/playground",
});
app.UseGraphiQLServer(new GraphiQLOptions
{
   GraphiQLPath = "/ui/graphiql",
   GraphQLEndPoint = "/graphql"
});
app.UseGraphQLVoyager(new GraphQLVoyagerOptions()
{
   GraphQLEndPoint = "/graphql",
   Path = "/ui/voyager"
});

Finally within Startup.cs, within the ConfigureServices method add the following code, which will register some types (which we’ll be supplying soon, the schema and query classes) and configures the GraphQL middleware.

services.AddSingleton<PersonSchema>();

services.AddGraphQL(options =>
{
   options.EnableMetrics = true;
   options.ExposeExceptions = true;
})
.AddWebSockets()
.AddDataLoader();

Schema

At this point we can see a need for the classes PersonSchema and PersonQuery. As you’ve realised, we are needing to create a schema object which will define our queries and types that we can query against. We’ll just create the bare bones schema class in PersonSchema.cs

public class PersonSchema : Schema
{
   public PersonSchema()
   {
      Query = new PersonQuery();
   }
}

Queries

Now we’ll create a bare PersonQuery.cs file which will be the starting point for some query functionality

public class PersonQuery : ObjectGraphType
{
}

At this point we could compiler and run the ASP.NET core application and navigate to http://localhost:5000/ui/playground to view the playground web application. However there’s not much we can do at this point.

Let’s add a domain object which represents a Person object, so add the following class. This represents the class that might come from a database or from another service

public class Person
{
   public string Name { get; set; }
}

For graphql-dotnet to allow us to use this class we need to wrap our Person object within a graphql-dotnet type, so create the following PersonType

public class PersonType : ObjectGraphType<Person>
{
   public PersonType()
   {
      Field(o => o.Name);
   }
}

In this case graphql-dotnet will now map fields to the Person object via the Field methods. This type then needs to be added to the PersonQuery class, to allow for querying again PersonType (and then ultimately Person) data. So add the PersonQuery constructor with the following code

public PersonQuery()
{
   Field<ListGraphType<PersonType>>("people", resolve: context => new[]
   {
      new Person {Name = "Scooby Doo"},
      new Person {Name ="Daphne Blake" },
      new Person {Name ="Shaggy Rogers" },
      new Person {Name ="Velma Dinkley" },
      new Person {Name ="Fred Jones" }
   });
}

Now if we run the application and navigate to http://localhost:5000/ui/playground we’ll find a Schema tab which displays information about how to query our data and if we write the following query

{
  people {
     name
  }
}

and run it from the playground we’ll see a list of the names from our Person data.

The previous example omitted the query keyword, i.e. it would look like this in a more formal definition of a query

query {
  people {
     name
  }
}

We can also implement our own query methods that might be called using the following (the C# for this is shown further down the post)

find(input : "Scooby Doo") {
   name
}

Or we can create a query which takes parameters/arguments from query variables. This example shows the use of an operation name, i.e. getPerson.

Note: operation names can be used for queries, mutations and subcriptions.

query getPerson($input : String) {
  find(input : $input) {
    name
  }
}

along with the input

{
  "input" : "Scooby Doo"
}

We’ll now create an input type in C# which will work with the above queries, such as

public class PersonInputType : InputObjectGraphType
{
   public PersonInputType()
   {
      Field<StringGraphType>("input");
   }
}

Now add another field to the PersonQuery constructor like this

Field<PersonType>(
   "find", 
   arguments: new QueryArguments(
      new QueryArgument<StringGraphType> 
      {
         Name = "input"
     }),
   resolve: context =>
   {
      var i = context.GetArgument<string>("input");
      return new Person {Name = i.ToString()};
   });

In the above, we essentially have created a new field in the PersonQuery which acts like a method, it is of type PersonType (the return type in this instance) and named find it takes a single argument of type string and expects the argument name of input. Finally it resolves to a method which we can then write something more substantial code for querying our data. In this simple example we’re just returning the argument passed in.

Note: We can also create multiple queries, so for example say we want to locate Person A and Person B and return data as a single result, we could write

{
   A : find(input : "Scooby") {
      name
   }
   B : find(input : "Shaggy") {
      name
   }
}

In the above query we use a GraphQL feature using aliases, the A and B acting like variable names. This allows us to create multiple queries against the same query/method.

When our queries start to become more complicated, we might prefer to place the field selection into, what’s know as a fragment, for example

{
   find(input : "Scooby") {
    ...fields
   }
}

fragment fields on PersonType {
  name
}

Obviously in our example it took more work to create and use the fragment that just using the field name, but you get the idea. However fragments can also be reused if we had multiple queries, so hence with more fields this become a much more useful technique.

Mutations

We’ve created our queries, which is great for scenarios where we’re simply reading data, but we can also create mutations, i.e. code that changes our data.

We can write a GraphQL mutation like this

mutation addPerson($input : String) {
   addPerson(input : $input)
   {
      name
   }
}

along with input such as

{
  "input" : "Scooby Doo"
}

What we now need to do is create our mutation class, like this

public class PersonMutation : ObjectGraphType<Person>
{
   public PersonMutation()
   {
      Field<PersonType>("addPerson",
         arguments: new QueryArguments(
            new QueryArgument<StringGraphType> {Name = "input"}),
         resolve: context =>
         {
            var n = context.GetArgument<string>("input");
            return new Person { Name = n };
         });
    }
}

We also need to alter the PersonSchema constructor to look like this

public PersonSchema()
{
   Query = new PersonQuery();
   Mutation = new PersonMutation();
}

Subscriptions

As you might expect, subscriptions are a way to handle something similar to events, hence we can connect to our service and received updates. Here’s a simple example of a query

subscription {
  personAdded {
    name
  }
}

Here’s a simple example of a subscription, to keep things simple this will simply send a message every second to any subcribers

public class PersonSubscription : ObjectGraphType
{
   public PersonSubscription()
   {
      AddField(new EventStreamFieldType
      {
         Name = "personAdded",
         Type = typeof(PersonType),
         Resolver = new FuncFieldResolver<Person>(ResolvePerson),
         Subscriber = new EventStreamResolver<Person>(SubscribePerson)
      });
   }

   private Person ResolvePerson(ResolveFieldContext context)
   {
      return context.Source as Person;
   }

   private IObservable<Person> SubscribePerson(ResolveEventStreamContext context)
   {
      return Observable.Interval(
         TimeSpan.FromSeconds(1))
           .Select(s => new Person 
           {
              Name = s.ToString()
           });
   }
}

Now we need to update the schema constructor like this

public PersonSubscription()
{
   AddField(new EventStreamFieldType
   {
      Name = "personAdded",
      Type = typeof(PersonType),
      Resolver = new FuncFieldResolver<Person>(ResolvePerson),
      Subscriber = new EventStreamResolver<Person>(SubscribePerson)
   });
}

Further reading

Refer to the GraphQL site for in depth examples and more complete explanations of the everything I’ve discussed above.

Also check out the GraphQL.net web site for graphql-dotnet documentation.

If you’re interested in code for the project, it’s available on GitHub.