[JAVA] Mutation with GraphQL

In this article, we will describe the sample application used in "Implement GraphQL with Spring Boot" as an example.

Mutation schema definition

First of all, it is desirable to name Mutation with a verb associated with the application. This time, I will take three arguments, id, name, and pageCount, and define a Book type schema for the return value.

schema.graphqls


type Mutation {
	registerBook (
    	id: ID
	    name: String!
	    pageCount: Int
	): Book
}

Server side

The server-side implementation is as follows. I need to implement GraphQLMutationResolver (I do this because I implement it in Java, I think it will look different in other languages). Also, as described in the schema definition, the return value defines registerBook, which is a Book type resolver, with id, name, and pageCount as arguments (the contents are dummy implementation as mentioned in the comment).

BookResolver.java


@Component
public class BookResolver implements GraphQLQueryResolver, GraphQLMutationResolver {
	
	public Book bookById(String bookId) {
		//Actually, in most cases, data is read from some data store and returned, but here a dummy value is returned.
		Book book = new Book();
		book.setId(bookId);
		book.setName("bookName");
		book.setPageCount(900);
		Author author = new Author();
		author.setId("0001");
		author.setFirstName("fName");
		author.setLastName("lName");
		book.setAuthor(author);
		return book;
	}
	
	public Book registerBook(String id, String name, int pageCount) {
		//Actually, the data registration process is performed here
		
		//Book is returned according to GraphQL schema definition. Generally, the registered data will be returned.
		Book book = new Book();
		book.setId(id);
		book.setName(name);
		book.setPageCount(pageCount);
		
		return book;
	}
}

Run Mutation

I will actually throw a Mutation. You can set all the arguments and throw them as follows. Since the Book type is returned due to the schema definition, here the query is such that the id and name in the Book type are received as the response.

mutation {
  registerBook(id: "1", name:"bookName", pageCount:100) {
    id
    name
  }
}

The response looks like this:

{
  "data": {
    "registerBook": {
      "id": "1",
      "name": "bookName"
    }
  }
}

Since the registerBook name argument is required, a query like the one below will result in a syntax error.

mutation {
  registerBook(id:"1", pageCount:100) {
    id
    name
  }
}

On the contrary, since the arguments other than name are non-essential, the following query can be executed (specify only the required arguments).

mutation {
  registerBook(name:"bookName") {
    id
    name
  }
}

Multiple data registration with one mutation

Add another field to mutation to register multiple data. Here, add registerAuthor.

schema.graphqls


type Mutation {
	registerBook (
    	id: ID
	    name: String!
	    pageCount: Int
	): Book
	
	registerAuthor (
		id: ID
		firstName: String
		lastName: String
	): Author
}

Add registerAuthor on the server side as follows.

BookResolver.java


@Component
public class BookResolver implements GraphQLQueryResolver, GraphQLMutationResolver {
	
	public Book bookById(String bookId) {
		//Actually, in most cases, data is read from some data store and returned, but here a dummy value is returned.
		Book book = new Book();
		book.setId(bookId);
		book.setName("bookName");
		book.setPageCount(900);
		Author author = new Author();
		author.setId("0001");
		author.setFirstName("fName");
		author.setLastName("lName");
		book.setAuthor(author);
		return book;
	}
	
	public Book registerBook(String id, String name, int pageCount) {
		//Actually, the data registration process is performed here
		
		//Book is returned according to GraphQL schema definition. Generally, the registered data will be returned.
		Book book = new Book();
		book.setId(id);
		book.setName(name);
		book.setPageCount(pageCount);
		
		return book;
	}
	
	public Author registerAuthor(String id, String firstName, String lastName) {
		//Actually, the data registration process is performed here
		
		//Return Author according to GraphQL schema definition. Generally, the registered data will be returned.
		Author author = new Author();
		author.setId(id);
		author.setFirstName(firstName);
		author.setLastName(lastName);
		
		return author;
	}
}

The query is as follows.

mutation {
  registerBook(id:"1", name:"bookName", pageCount:100) {
    id
    name
    pageCount
  }
  registerAuthor(id:"1", firstName:"fName", lastName: "lName") {
    id
    firstName
    lastName
  }
}

Execute Mutation using query variables

It is also possible to dynamically change the value registered in Mutation using a "query variable". The query looks like this:

mutation createBook($id:ID $name:String! $pageCount:Int) {
  registerBook(id:$id, name:$name, pageCount: $pageCount) {
    id
    name
    pageCount
  }
  registerAuthor(id:$id, firstName:"fName", lastName: "lName") {
    id
    firstName
    lastName
  }
}

An arbitrary mutation name is required after the mutation syntactically to receive the query variable (referred to as createBook above). The query variable can be any variable name with "$" at the beginning.

GraphiQL and GraphQL Playground have a query variable window, so set the value to be set in the variable in that window in JSON format and execute it. The JSON key name will be the query variable name. キャプチャ.PNG

that's all.

Recommended Posts

Mutation with GraphQL
Implement GraphQL with Spring Boot
API creation with Rails + GraphQL
Test GraphQL resolver with rspec
I tried GraphQL with Spring Boot
How to build API with GraphQL and Rails