Prerequisites
What is GraphQL?
GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.
Note: This tutorial assumes that you are familiar with the Java programming language, the Spring Boot framework, and REST APIs in general. No prior GraphQL experience is required.
GraphQL is a new specification (originally developed by Facebook for internal use, later open-sourced in 2015) that describes how to implement APIs. Unlike REST, which uses different endpoints to retrieve different types of data (e. g. users, comments, blog posts…), GraphQL exposes a single endpoint that receives a query from the front-end as part of the request, returning exactly the requested pieces of data in a single response. The server defines a schema describing what queries are available.
Note: Unlike REST, GraphQL as a specification is not tied to the HTTP protocol, however, HTTP is most commonly used. In this case, GraphQL queries are simple HTTP GET or POST requests with special query parameters or request bodies, respectively. You can use Postman which recently received GraphQL support.
Step to build GraphQL server using Spring Boot
Starting with spring initializr
For all Spring applications, you should start with the Spring Initializr. The Initializr offers a fast way to pull in all the dependencies you need for an application and does a lot of the set up for you. And we will started with maven project.
The following listing shows the pom.xml
file created when you choose Maven. And here my pom.xml
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
| <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.maverick</groupId>
<artifactId>graphiql</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>graphiql</name>
<description>Demo project for Spring Boot with GraphQL</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.graphql-java-kickstart/graphql-spring-boot-starter -->
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>6.0.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.flywaydb/flyway-core -->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
|
Edit application.properties
1
2
3
4
5
6
7
8
9
10
11
12
13
| #Basic Spring Boot Config for Oracle
spring.jmx.enabled=false
info.app.name=GraphQL Example
info.app.description=GraphQL Example
info.app.version=1.0.0
management.security.enabled=false
spring.http.multipart.max-file-size=10485760
spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
graphql.servlet.enabled=true
graphql.servlet.exception-handlers-enabled=true
graphql.servlet.contextSetting= PER_REQUEST_WITH_INSTRUMENTATION
spring.jpa.hibernate.use-new-id-generator-mappings=false
|
And here my project/application.yml
for external configuration of database connection, flyway migration, etc.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| app:
name: "Maverick GraphQL Example"
website: "blog.piinalpin.com"
origin: "http://localhost:3000"
upload_dir: "./tmp/"
production: false
spring:
datasource:
url: "jdbc:mysql://localhost:3306/DB_NAME?allowPublicKeyRetrieval=true&useSSL=false"
username: DB_USERNAME
password: DB_PASSWORD
driverClassName: com.mysql.cj.jdbc.Driver
flyway:
enabled: true
baselineOnMigrate: true
url: jdbc:mysql://localhost:3306/DB_NAME?allowPublicKeyRetrieval=true&useSSL=false
user: DB_USERNAME
password: DB_PASSWORD
validateOnMigrate: false
server:
port: 8080
|
Create resource/db/migration/V1_1__Initial_Commit.sql
for initial migration script
Edit project main application and add annotation @EnableJpaRepositories
. The file should be like below.
1
2
3
4
5
6
7
8
9
| @SpringBootApplication
@EnableJpaRepositories
public class GraphqlApplication {
public static void main(String[] args) {
SpringApplication.run(GraphqlApplication.class, args);
}
}
|
Data Scalar
Create bean configuration com.maverick.graphql.configuration.DataScalarConfiguration
to define scalar for GraphQL schema.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
| @Configuration
public class DataScalarConfiguration {
@Bean
public GraphQLScalarType dateScalar() {
return GraphQLScalarType.newScalar()
.name("Date")
.description("Java 8 LocalDate as Scalar")
.coercing(new Coercing<LocalDate, String>() {
@Override
public String serialize(Object dataFetcherResult) throws CoercingSerializeException {
if (dataFetcherResult instanceof Timestamp) return dataFetcherResult.toString();
else throw new CoercingSerializeException("Expected a Timestamp object.");
}
@Override
public LocalDate parseValue(Object input) throws CoercingParseValueException {
try {
if (input instanceof String) return LocalDate.parse((String) input, DateTimeFormatter.ofPattern("dd-MM-yyyy"));
else throw new CoercingParseValueException("Expected a String");
} catch (DateTimeParseException e) {
throw new CoercingParseValueException(String.format("Not a valid date: %s", input), e);
}
}
@Override
public LocalDate parseLiteral(Object input) throws CoercingParseLiteralException {
if (input instanceof StringValue) {
try {
return LocalDate.parse(((StringValue) input).getValue());
} catch (DateTimeParseException e) {
throw new CoercingParseLiteralException();
}
} else throw new CoercingParseLiteralException("Expected a StringValue");
}
}).build();
}
}
|
Create Person
Create GraphQL schema on resource/schema.graphqls
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| scalar Date
type Mutation {
createPerson(input: PersonInput!): Person!
}
input PersonInput {
firstName: String!,
lastName: String!,
dateOfBirth: Date,
identityType: String!,
identityNumber: String!,
address: String
}
type Person {
id: Int!
firstName: String!,
lastName: String!,
dateOfBirth: Date,
identityType: String!,
identityNumber: String!,
address: String,
createdAt: Date,
createdBy: Int,
updatedAt: Date
}
|
Create table on database migration resource/db/migration/V2_1__Person.sql
see Flyway Documentation for versioning migration.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| SET AUTOCOMMIT = false;
START TRANSACTION;
CREATE TABLE m_person (
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
created_at DATETIME NOT NULL,
created_by BIGINT NOT NULL,
updated_at DATETIME,
deleted_at DATETIME,
first_name VARCHAR(255) NOT NULL,
last_name VARCHAR(255) NOT NULL,
date_of_birth DATETIME NOT NULL,
identity_type VARCHAR(255) NOT NULL,
identity_number VARCHAR(255) NOT NULL,
address VARCHAR(1000)
);
COMMIT;
|
Create abstract class com.maverick.graphql.model.BaseModel
first which aim can be inheritence for another model.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
| @NoArgsConstructor
@MappedSuperclass
abstract class BaseModel {
@JsonProperty("created_at")
@Column(name = "CREATED_AT", nullable = false)
@Getter
@Setter
private Timestamp createdAt;
@JsonProperty("created_by")
@Column(name = "CREATED_BY", nullable = false)
@Getter
@Setter
private Long createdBy;
@JsonProperty("updated_at")
@Column(name = "UPDATED_AT")
@Getter
@Setter
private Timestamp updatedAt;
@JsonIgnore
@Column(name = "DELETED_AT")
@Getter
@Setter
private Timestamp deleted_at;
@PrePersist
void onCreate() {
createdAt = Timestamp.valueOf(LocalDateTime.now());
if (createdBy == null) createdBy = 0L;
}
@PreUpdate
void onUpdate() {
updatedAt = Timestamp.valueOf(LocalDateTime.now());
}
}
|
Create person model com.maverick.graphql.model.Person
which is inheritence from BaseModel
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
| @Entity
@Table(name = "M_PERSON")
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Where(clause = "deleted_at is null")
public class PersonModel extends BaseModel {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Getter
@Setter
private Long id;
@Column(name = "FIRST_NAME", nullable = false)
@Getter
@Setter
private String firstName;
@Column(name = "LAST_NAME", nullable = false)
@Getter
@Setter
private String lastName;
@Column(name = "DATE_OF_BIRTH", nullable = false)
@Getter
@Setter
private Timestamp dateOfBirth;
@Column(name = "IDENTITY_TYPE", nullable = false)
@Getter
@Setter
private String identityType;
@Column(name = "IDENTITY_NUMBER", nullable = false)
@Getter
@Setter
private String identityNumber;
@Column(name = "ADDRESS")
@Getter
@Setter
private String address;
}
|
Create repository com.maverick.graphql.repository.PersonRepository
for transactional query which extends from JpaRepository
1
2
3
4
| @Repository
public interface PersonRepository extends JpaRepository<PersonModel, Long> {
}
|
Create form com.maverick.graphql.form.PersonForm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| @Data
public class PersonForm {
private String firstName;
private String lastName;
private LocalDate dateOfBirth;
private String identityType;
private String identityNumber;
private String address;
}
|
Create service com.maverick.graphql.service.PersonService
to store person model into database using repository.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| @Service
public class PersonService {
private final PersonRepository personRepository;
@Autowired
public PersonService(PersonRepository personRepository) {
this.personRepository = personRepository;
}
public PersonModel save(PersonModel person) {
return personRepository.save(person);
}
}
|
Create mutation service com.maverick.graphql.mutation.PersonMutation
use for anychange data from GraphQL schema.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| @Service
public class PersonMutation implements GraphQLMutationResolver {
private final PersonService personService;
@Autowired
public PersonMutation(PersonService personService) {
this.personService = personService;
}
public PersonModel createPerson(PersonForm form) {
PersonModel person = PersonModel.builder()
.address(form.getAddress())
.dateOfBirth(Timestamp.valueOf(form.getDateOfBirth().atStartOfDay()))
.firstName(form.getFirstName())
.lastName(form.getLastName())
.identityType(form.getIdentityType())
.identityNumber(form.getIdentityNumber())
.build();
return personService.save(person);
}
}
|
Try to run by typing mvn spring-boot:run
then open Postman like below.
URL: http://localhost:8080/graphql (POST)
Query
1
2
3
4
5
6
7
8
| mutation CreatePerson($input: PersonInput!){
createPerson(input: $input) {
id
firstName
identityNumber
address
}
}
|
GraphQL Variables
1
2
3
4
5
6
7
8
9
10
| {
"input": {
"firstName": "Alvinditya",
"lastName": "Saputra",
"dateOfBirth": "10-11-1996",
"identityType": "KTP",
"identityNumber": "346343723744",
"address": "Yogyakarta"
}
}
|
Response should be like below.
1
2
3
4
5
6
7
8
9
10
| {
"data": {
"createPerson": {
"id": 1,
"firstName": "Alvinditya",
"identityNumber": "346343723744",
"address": "Yogyakarta"
}
}
}
|
Get Person Data
Edit resource/schema.graphqls
, code should be like below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
| scalar Date
type Query {
getAllPerson: [Person!]
getPersonById(id: Int!): Person
getPersonByIdentityNumber(identityNumber: String!): Person
}
type Mutation {
createPerson(input: PersonInput!): Person!
}
input PersonInput {
firstName: String!,
lastName: String!,
dateOfBirth: Date,
identityType: String!,
identityNumber: String!,
address: String
}
type Person {
id: Int!
firstName: String!,
lastName: String!,
dateOfBirth: Date,
identityType: String!,
identityNumber: String!,
address: String,
createdAt: Date,
createdBy: Int,
updatedAt: Date
}
|
Edit com.maverick.graphql.repository.PersonRepository
add line to get person data by identity number.
1
2
3
4
5
6
7
8
| @Repository
@Transactional
public interface PersonRepository extends JpaRepository<PersonModel, Long> {
@Query(value = "SELECT * FROM m_person WHERE identity_number = ?1", nativeQuery = true)
PersonModel findByIdentityNumber(String identityNumber);
}
|
Edit com.maverick.graphql.service.PersonService
to process logic get data from repository. Code should be like below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| @Service
public class PersonService {
private final PersonRepository personRepository;
@Autowired
public PersonService(PersonRepository personRepository) {
this.personRepository = personRepository;
}
public PersonModel save(PersonModel person) {
return personRepository.save(person);
}
public List<PersonModel> getAll() {
return personRepository.findAll();
}
public PersonModel getByIdentityNumber(String identityNumber) {
return personRepository.findByIdentityNumber(identityNumber);
}
public Optional<PersonModel> getById(Long id) {
return personRepository.findById(id);
}
}
|
Create exception com.maverick.graphql.exception.DataNotFoundException
to handle when record not found.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| @ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "data: not found")
@NoArgsConstructor
public class DataNotFoundException extends RuntimeException {
@Getter
@Setter
private String message = "data: not found";
public DataNotFoundException(String message) {
super();
this.message = message;
}
}
|
Create query resolver com.maverick.graphql.resolver.PersonResolver
to handle query request.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| @Service
public class PersonResolver implements GraphQLQueryResolver {
private final PersonService personService;
@Autowired
public PersonResolver(PersonService personService) {
this.personService = personService;
}
public List<PersonModel> getAllPerson() {
return personService.getAll();
}
public PersonModel getPersonById(final Long id) {
PersonModel person = personService.getById(id).orElse(null);
if (person == null) throw new DataNotFoundException("person record: not found");
return person;
}
public PersonModel getPersonByIdentityNumber(final String identityNumber) {
PersonModel person = personService.getByIdentityNumber(identityNumber);
if (person == null) throw new DataNotFoundException("person record: not found");
return person;
}
}
|
Try to run by typing mvn spring-boot:run
then open Postman like below. You can edit any field you want.
URL: http://localhost:8080/graphql (POST)
Query
1
2
3
4
5
6
7
| query {
getAllPerson {
id
firstName
identityNumber
}
}
|
Response should be like below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| {
"data": {
"getAllPerson": [
{
"id": 1,
"firstName": "Calvin",
"identityNumber": "2263246348434"
},
{
"id": 2,
"firstName": "Calvin 2",
"identityNumber": "237384374233"
}
]
}
}
|
Query
1
2
3
4
5
6
7
| query {
getPersonById(id: 4) {
id
firstName
identityNumber
}
}
|
Response should be like below.
1
2
3
4
5
6
7
8
9
| {
"data": {
"getPersonById": {
"id": 4,
"firstName": "Alvinditya",
"identityNumber": "346343723744"
}
}
}
|
Query
1
2
3
4
5
6
7
8
| query {
getPersonByIdentityNumber(identityNumber: "346343723744") {
id
firstName
lastName
identityNumber
}
}
|
Response should be like below.
1
2
3
4
5
6
7
8
9
10
| {
"data": {
"getPersonByIdentityNumber": {
"id": 4,
"firstName": "Alvinditya",
"lastName": "Saputra",
"identityNumber": "346343723744"
}
}
}
|
Update Person
Edit resource/schema.graphqls
, code should be like below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| scalar Date
type Query {
getAllPerson: [Person!]
getPersonById(id: Int!): Person
getPersonByIdentityNumber(identityNumber: String!): Person
}
type Mutation {
createPerson(input: PersonInput!): Person!
updatePerson(input: PersonInput!, id: Int!): Person!
}
input PersonInput {
firstName: String!,
lastName: String!,
dateOfBirth: Date,
identityType: String!,
identityNumber: String!,
address: String
}
type Person {
id: Int!
firstName: String!,
lastName: String!,
dateOfBirth: Date,
identityType: String!,
identityNumber: String!,
address: String,
createdAt: Date,
createdBy: Int,
updatedAt: Date
}
|
Edit mutation com.maverick.graphql.mutation.PersonMutation
to process logic save updated data. Code should be like below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| @Service
public class PersonMutation implements GraphQLMutationResolver {
private final PersonService personService;
@Autowired
public PersonMutation(PersonService personService) {
this.personService = personService;
}
public PersonModel createPerson(PersonForm form) {
PersonModel person = PersonModel.builder()
.address(form.getAddress())
.dateOfBirth(Timestamp.valueOf(form.getDateOfBirth().atStartOfDay()))
.firstName(form.getFirstName())
.lastName(form.getLastName())
.identityType(form.getIdentityType())
.identityNumber(form.getIdentityNumber())
.build();
return personService.save(person);
}
public PersonModel updatePerson(PersonForm form, Long id) {
PersonModel person = personService.getById(id).orElse(null);
if (person == null) throw new DataNotFoundException("person record: not found");
person.setAddress(form.getAddress());
person.setDateOfBirth(Timestamp.valueOf(form.getDateOfBirth().atStartOfDay()));
person.setFirstName(form.getFirstName());
person.setLastName(form.getLastName());
person.setIdentityNumber(form.getIdentityNumber());
person.setIdentityType(form.getIdentityType());
return personService.save(person);
}
}
|
Try to run by typing mvn spring-boot:run
then open Postman like below. You can edit any field you want.
URL: http://localhost:8080/graphql (POST)
Query
1
2
3
4
5
6
7
8
9
10
| mutation UpdatePerson($input: PersonInput!){
updatePerson(input: $input, id: 2) {
id
firstName
lastName
createdAt
identityNumber
address
}
}
|
GraphQL Variables
1
2
3
4
5
6
7
8
9
10
| {
"input": {
"firstName": "Maverick",
"lastName": "Johnson",
"dateOfBirth": "10-11-1996",
"identityType": "KTP",
"identityNumber": "346322723744",
"address": "Yogyakarta"
}
}
|
Response should be like below.
1
2
3
4
5
6
7
8
9
10
11
12
| {
"data": {
"updatePerson": {
"id": 2,
"firstName": "Maverick",
"lastName": "Johnson",
"createdAt": "2021-01-05 11:32:23.0",
"identityNumber": "346322723744",
"address": "Yogyakarta"
}
}
}
|
Delete Person
Edit resource/schema.graphqls
, code should be like below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
| scalar Date
scalar Timestamp
type Query {
getAllPerson: [Person!]
getPersonById(id: Int!): Person
getPersonByIdentityNumber(identityNumber: String!): Person
}
type Mutation {
createPerson(input: PersonInput!): Person!
updatePerson(input: PersonInput!, id: Int!): Person!
deletePerson(id: Int!): OkMessage!
}
input PersonInput {
firstName: String!,
lastName: String!,
dateOfBirth: Date,
identityType: String!,
identityNumber: String!,
address: String
}
type Person {
id: Int!
firstName: String!,
lastName: String!,
dateOfBirth: Date,
identityType: String!,
identityNumber: String!,
address: String,
createdAt: Date,
createdBy: Int,
updatedAt: Date
}
type OkMessage {
message: String!
}
|
Edit com.maverick.graphql.repository.PersonRepository
add line to update deleted_at for soft delete.
1
2
3
4
5
6
7
8
9
10
11
12
| @Repository
@Transactional
public interface PersonRepository extends JpaRepository<PersonModel, Long> {
@Query(value = "SELECT * FROM m_person WHERE identity_number = ?1", nativeQuery = true)
PersonModel findByIdentityNumber(String identityNumber);
@Query(value = "UPDATE m_person SET deleted_at = CURRENT_DATE WHERE id = ?1", nativeQuery = true)
@Modifying
void softDelete(Long id);
}
|
Edit com.maverick.graphql.service.PersonService
to process logic delete data from repository. Code should be like below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| @Service
public class PersonService {
private final PersonRepository personRepository;
@Autowired
public PersonService(PersonRepository personRepository) {
this.personRepository = personRepository;
}
public PersonModel save(PersonModel person) {
return personRepository.save(person);
}
public List<PersonModel> getAll() {
return personRepository.findAll();
}
public PersonModel getByIdentityNumber(String identityNumber) {
return personRepository.findByIdentityNumber(identityNumber);
}
public Optional<PersonModel> getById(Long id) {
return personRepository.findById(id);
}
public void deletePerson(Long id) {
personRepository.softDelete(id);
}
}
|
Edit mutation com.maverick.graphql.mutation.PersonMutation
to process logic save updated data. Code should be like below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
| @Service
public class PersonMutation implements GraphQLMutationResolver {
private final PersonService personService;
@Autowired
public PersonMutation(PersonService personService) {
this.personService = personService;
}
public PersonModel createPerson(PersonForm form) {
PersonModel person = PersonModel.builder()
.address(form.getAddress())
.dateOfBirth(Timestamp.valueOf(form.getDateOfBirth().atStartOfDay()))
.firstName(form.getFirstName())
.lastName(form.getLastName())
.identityType(form.getIdentityType())
.identityNumber(form.getIdentityNumber())
.build();
return personService.save(person);
}
public PersonModel updatePerson(PersonForm form, Long id) {
PersonModel person = personService.getById(id).orElse(null);
if (person == null) throw new DataNotFoundException("person record: not found");
person.setAddress(form.getAddress());
person.setDateOfBirth(Timestamp.valueOf(form.getDateOfBirth().atStartOfDay()));
person.setFirstName(form.getFirstName());
person.setLastName(form.getLastName());
person.setIdentityNumber(form.getIdentityNumber());
person.setIdentityType(form.getIdentityType());
return personService.save(person);
}
public Map<String, String> deletePerson(Long id) {
PersonModel person = personService.getById(id).orElse(null);
if (person == null) throw new DataNotFoundException("person record: not found");
personService.deletePerson(person.getId());
Map<String,String> ret = new HashMap<>();
ret.put("message", "ok");
return ret;
}
}
|
Try to run by typing mvn spring-boot:run
then open Postman like below. You can edit any field you want.
URL: http://localhost:8080/graphql (POST)
Query
1
2
3
4
5
| mutation {
deletePerson(id: 2) {
message
}
}
|
Response should be like below.
1
2
3
4
5
6
7
| {
"data": {
"deletePerson": {
"message": "ok"
}
}
}
|
If data not found, should be like below.
Query
1
2
3
4
5
| mutation {
deletePerson(id: 3) {
message
}
}
|
Response should be like below.
1
2
3
4
5
6
7
8
| {
"errors": [
{
"message": "person record: not found"
}
],
"data": null
}
|
Clone or Download
You can clone or download this project
1
| https://github.com/piinalpin/graphql-spring-boot.git
|
Thankyou
Medium - GraphQL server using Spring Boot, Part I
Baeldung - Getting Started with GraphQL and Spring Boot
Github - Team Supercharge