Với RESTful API, các bạn có thể sử dụng OpenAPI Generator Maven plugin để generate source code và chỉ cần thêm implementation cho các API. Với GraphQL, các bạn cũng có thể làm điều này sử dụng GraphQL Maven plugin. Cụ thể như thế nào? Chúng ta hãy cùng nhau tìm hiểu trong bài viết này các bạn nhé!
Đầu tiên, mình sẽ tạo mới một Spring Boot project với Spring Web và Spring for GraphQL dependencies để làm ví dụ:
Kết quả như sau:
Cho ví dụ của bài viết này, mình sẽ định nghĩa một tập tin schema schema.graphqls nằm trong thư mục src/main/resources/graphql với nội dung như sau:
1 2 3 4 5 6 7 8 9 10 11 12 |
type Query { students(clazz: String): [Student] } type Student { id: ID code: String name: String age: Int address: String clazz: String } |
Bây giờ thì các bạn có thể định nghĩa GraphQL Maven plugin như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<plugin> <groupId>com.graphql-java-generator</groupId> <artifactId>graphql-maven-plugin</artifactId> <version>2.1</version> <executions> <execution> <goals> <goal>generateServerCode</goal> </goals> </execution> </executions> <configuration> <schemaFileFolder>${project.basedir}/src/main/resources/graphql</schemaFileFolder> <packageName>com.huongdanjava.graphql</packageName> <targetSourceFolder>${project.basedir}/src/main/java</targetSourceFolder> </configuration> </plugin> |
GraphQL Maven plugin định nghĩa một số goal, để generate GraphQL contract cho server, các bạn hãy khai báo sử dụng goal “generateServerCode” trong phần execution của GraphQL Maven plugin các bạn nhé.
Trong phần configuration, mặc định thì GraphQL Maven plugin sẽ scan hết tất cả các file .graphqls trong thư mục src/main/resources để generate server code nhưng vì mình đã muốn centralize tất cả các file .graphqls trong thư mục src/main/resources/graphql nên các bạn có thể sử dụng tag <schemaFileFolder> để modify giá trị mặc định này.
<packageName> sẽ là tên package để GraphQL Maven plugin generate source code.
Mặc định thì code sẽ được generate trong thư mục /target/generated-sources/graphql-maven-plugin, nếu các bạn muốn thay đổi giá trị mặc định này thì có thể cấu hình như mình sử dụng tag <targetSourceFolder> nhé!
Các bạn có thể xem thêm tất cả configuration của GraphQL Maven plugin với goal “generateServerCode” tại đây.
Lúc này, các bạn sẽ thấy GraphQL Maven plugin generate code với kết quả như sau:
Để code có thể compile được, các bạn cần thêm 1 số dependencies như sau:
1 2 3 4 5 |
<dependency> <groupId>com.graphql-java-generator</groupId> <artifactId>graphql-java-server-runtime</artifactId> <version>2.1</version> </dependency> |
Trong package com.huongdanjava.graphql, các bạn có thể thấy Graphql Maven plugin generate 2 class Query và Student tương ứng với 2 GraphQL object type mà chúng ta định nghĩa trong tập tin .graphqls.
Class QueryController sẽ handle type Query cho GraphQL mà chúng ta đã định nghĩa. Class này sử dụng implementation của interface DataFetchersDelegateQuery để lấy dữ liệu trả về cho query nên các bạn cần implement interface DataFetchersDelegateQuery này. Ví dụ của mình như sau:
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 |
package com.huongdanjava.graphql; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.UUID; import org.springframework.stereotype.Service; import com.huongdanjava.graphql.util.DataFetchersDelegateQuery; import graphql.schema.DataFetchingEnvironment; @Service public class DataFetchersDelegateQueryImpl implements DataFetchersDelegateQuery { @Override public List<Student> students(DataFetchingEnvironment dataFetchingEnvironment, String clazz) { if (clazz == null) { return StudentRepository.findAll(); } return StudentRepository.findByClazz(clazz); } static class StudentRepository { // @formatter:off static List<Student> students = Arrays.asList( Student.builder() .withId(UUID.randomUUID()) .withCode("001") .withName("Khanh") .withAge(35) .withAddress("Binh Dinh") .withClazz("A") .build(), Student.builder() .withId(UUID.randomUUID()) .withCode("002") .withName("Quan") .withAge(25) .withAddress("Ho Chi Minh") .withClazz("B") .build()); // @formatter:on public static List<Student> findAll() { return students; } public static List<Student> findByClazz(String clazz) { List<Student> studentsByClazz = new ArrayList<>(); for (Student student : students) { if (student.getClazz().equals(clazz)) { studentsByClazz.add(student); } } return studentsByClazz; } } } |
Ở đây, mình chỉ implement để làm ví dụ thôi, các bạn có thể implement để lấy thông tin từ database nếu muốn nhé!
Một interface khác được sử dụng trong class StudentController liên quan đến batch loader mà các bạn cũng cần implement là DataFetchersDelegateStudent. Tuỳ nhu cầu thì các bạn có thể implement cho hợp lý nhé. Để đơn giản thì mình chỉ add class implement interface này như sau:
1 2 3 4 5 6 7 8 9 |
package com.huongdanjava.graphql; import org.springframework.stereotype.Service; import com.huongdanjava.graphql.util.DataFetchersDelegateStudent; @Service public class DataFetchersDelegateStudentImpl implements DataFetchersDelegateStudent { } |
Bây giờ thì các bạn hãy khai báo property spring.graphql.graphiql.enabled=true để enable sử dụng công cụ GraphiQL, trong tập tin application.properties:
1 |
spring.graphql.graphiql.enabled=true |
Đến đây thì chúng ta đã hoàn thành việc sử dụng GraphQL Maven plugin để generate GraphQL contract rồi đó các bạn.
Để lấy thông tin tất cả sinh viên, mình sẽ sử dụng query như sau:
1 2 3 4 5 6 7 8 9 10 |
{ students { id code name age address clazz } } |
Kết quả:
Còn lấy thông tin của lớp “A”, mình sẽ query:
1 2 3 4 5 6 7 8 9 10 |
{ students(clazz: "A") { id code name age address clazz } } |
Kết quả: