JAVA-12421 Renamed graphql to graphql-modules

This commit is contained in:
Dhawal Kapil
2022-06-03 18:00:47 +05:30
parent 6b63897e42
commit 8b0ba1686c
81 changed files with 12 additions and 11 deletions

View File

@@ -0,0 +1,9 @@
## GraphQL Java
This module contains articles about GraphQL with Java
## Relevant articles:
- [Introduction to GraphQL](https://www.baeldung.com/graphql)
- [Make a Call to a GraphQL Service from a Java Application](https://www.baeldung.com/java-call-graphql-service)
- [Return Map from GraphQL](https://www.baeldung.com/java-graphql-return-map)

View File

@@ -0,0 +1,8 @@
{
"query": "mutation($name: String! $email: String! $age: String! ){ createUser ( name: $name email: $email age: $age) { id name email age } }",
"parameters": {
"name": "John",
"email": "john@email.com",
"age": 34
}
}

View File

@@ -0,0 +1,6 @@
{
"query": "mutation($name: String! ){ deleteUser ( id: $id) { id name email age} }",
"parameters": {
"id": 2
}
}

View File

@@ -0,0 +1,4 @@
{
"query": "{ listUsers{ id name email age}}",
"parameters": {}
}

View File

@@ -0,0 +1,6 @@
{
"query": "query($id: String!){ retrieveUser ( id: $id) { id name email} }",
"parameters": {
"id": 1
}
}

View File

@@ -0,0 +1,6 @@
{
"query": "query($id: String!){ searchName ( id: $id) { id name email} }",
"parameters": {
"id": 2
}
}

View File

@@ -0,0 +1,9 @@
{
"query": "mutation($id: String! $name: String! $email: String! $age: String! ){ updateUser ( id: $id name: $name email: $email age: $age) { id name email age} }",
"parameters": {
"id": 1,
"name":"John updated",
"email": "johnupdate@email.com",
"age": 50
}
}

View File

@@ -0,0 +1,163 @@
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>graphql-java</artifactId>
<version>1.0</version>
<name>graphql-java</name>
<parent>
<groupId>com.baeldung.graphql</groupId>
<artifactId>graphql-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java-annotations</artifactId>
<version>${graphql-java-annotations.version}</version>
</dependency>
<dependency>
<groupId>io.ratpack</groupId>
<artifactId>ratpack-core</artifactId>
<version>${ratpack-core.version}</version>
</dependency>
<dependency>
<groupId>com.github.americanexpress.nodes</groupId>
<artifactId>nodes</artifactId>
<version>${nodes.version}</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java</artifactId>
<version>${graphql-java.version}</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java-tools</artifactId>
<version>${graphql-java-tools.version}</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java-servlet</artifactId>
<version>${graphql-java-servlet.version}</version>
</dependency>
<dependency>
<groupId>com.graphql-java-generator</groupId>
<artifactId>graphql-java-runtime</artifactId>
<version>${graphql.java.generator.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${javax.servlet-api.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>${httpclient.version}</version>
</dependency>
<dependency>
<groupId>org.mock-server</groupId>
<artifactId>mockserver-netty</artifactId>
<version>${mockserver-netty.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mock-server</groupId>
<artifactId>mockserver-client-java</artifactId>
<version>${mockserver-client-java.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java-extended-scalars</artifactId>
<version>${graphql-java-extended-scalars.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>${jetty-maven-plugin.version}</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>${maven-war-plugin.version}</version>
</plugin>
<plugin>
<groupId>com.graphql-java-generator</groupId>
<artifactId>graphql-maven-plugin</artifactId>
<version>${graphql.java.generator.version}</version>
<executions>
<execution>
<goals>
<goal>generateClientCode</goal>
</goals>
</execution>
</executions>
<configuration>
<packageName>com.baeldung.graphql.generated</packageName>
<copyRuntimeSources>false</copyRuntimeSources>
<generateDeprecatedRequestResponse>false</generateDeprecatedRequestResponse>
<separateUtilityClasses>true</separateUtilityClasses>
<customScalars>
<customScalar>
<graphQLTypeName>JSON</graphQLTypeName>
<javaType>java.util.Map</javaType>
<graphQLScalarTypeClass>com.baeldung.graphqlreturnmap.ExtendedGraphQLScalarType</graphQLScalarTypeClass>
</customScalar>
</customScalars>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<graphql-java.version>11.0</graphql-java.version>
<graphql-java-tools.version>5.2.4</graphql-java-tools.version>
<graphql-java-servlet.version>6.1.3</graphql-java-servlet.version>
<graphql-java-annotations.version>3.0.3</graphql-java-annotations.version>
<graphql.java.generator.version>1.18</graphql.java.generator.version>
<ratpack-core.version>1.9.0</ratpack-core.version>
<nodes.version>0.5.0</nodes.version>
<httpclient.version>4.5.13</httpclient.version>
<mockserver-netty.version>5.13.2</mockserver-netty.version>
<mockserver-client-java.version>5.13.2</mockserver-client-java.version>
<jetty-maven-plugin.version>10.0.7</jetty-maven-plugin.version>
<graphql.java.generator.version>1.18</graphql.java.generator.version>
<graphql-java-extended-scalars.version>2022-04-06T00-10-27-a70541e</graphql-java-extended-scalars.version>
</properties>
</project>

View File

@@ -0,0 +1,17 @@
package com.baeldung.graphql;
import ratpack.server.RatpackServer;
import com.baeldung.graphql.handler.UserHandler;
public class Application {
public static void main(String[] args) throws Exception {
new Application();
}
private Application() throws Exception {
final RatpackServer server = RatpackServer.of(s -> s.handlers(chain -> chain.post("users", new UserHandler())));
server.start();
}
}

View File

@@ -0,0 +1,24 @@
package com.baeldung.graphql.clients;
import com.baeldung.graphql.data.Data;
import io.aexp.nodes.graphql.GraphQLRequestEntity;
import io.aexp.nodes.graphql.GraphQLResponseEntity;
import io.aexp.nodes.graphql.GraphQLTemplate;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
public class AmericanExpressNodes {
public static GraphQLResponseEntity<Data> callGraphQLService(String url, String query) throws IOException {
GraphQLTemplate graphQLTemplate = new GraphQLTemplate();
GraphQLRequestEntity requestEntity = GraphQLRequestEntity.Builder()
.url(StringUtils.join(url, "?query=", query))
.request(Data.class)
.build();
return graphQLTemplate.query(requestEntity, Data.class);
}
}

View File

@@ -0,0 +1,25 @@
package com.baeldung.graphql.clients;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClientBuilder;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
public class ApacheHttpClient {
public static HttpResponse callGraphQLService(String url, String query) throws URISyntaxException, IOException {
HttpClient client = HttpClientBuilder.create().build();
HttpGet request = new HttpGet(url);
URI uri = new URIBuilder(request.getURI())
.addParameter("query", query)
.build();
request.setURI(uri);
return client.execute(request);
}
}

View File

@@ -0,0 +1,31 @@
package com.baeldung.graphql.data;
import org.apache.commons.lang3.StringUtils;
public class Author {
private String name;
private String surname;
public Author() {
}
public Author(String name, String surname) {
this.name = name;
this.surname = surname;
}
public String getName() {
return name;
}
public String getSurname() {
return surname;
}
public String getFullName() {
return StringUtils.join(getName(), " ", getSurname());
}
}

View File

@@ -0,0 +1,25 @@
package com.baeldung.graphql.data;
public class Book {
private String title;
private Author author;
public Book() {
}
public Book(String title, Author author) {
this.title = title;
this.author = author;
}
public String getTitle() {
return title;
}
public Author getAuthor() {
return author;
}
}

View File

@@ -0,0 +1,19 @@
package com.baeldung.graphql.data;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class BookRepository {
private static final List<Book> books = Stream.of(
new Book("Title 1", new Author("Pero", "Peric")),
new Book("Title 2", new Author("Marko", "Maric"))
).collect(Collectors.toList());
public List<Book> getAllBooks() {
return Collections.unmodifiableList(books);
}
}

View File

@@ -0,0 +1,22 @@
package com.baeldung.graphql.data;
import java.util.Collections;
import java.util.List;
public class Data {
private List<Book> allBooks;
public Data() {
}
public Data(List<Book> allBooks) {
this.allBooks = allBooks;
}
public List<Book> getAllBooks() {
return Collections.unmodifiableList(allBooks);
}
}

View File

@@ -0,0 +1,19 @@
package com.baeldung.graphql.data;
public class Response {
private Data data;
public Response() {
}
public Response(Data data) {
this.data = data;
}
public Data getData() {
return data;
}
}

View File

@@ -0,0 +1,78 @@
package com.baeldung.graphql.entity;
import java.util.List;
import com.baeldung.graphql.handler.UserHandler;
import com.baeldung.graphql.utils.SchemaUtils;
import graphql.annotations.GraphQLField;
import graphql.annotations.GraphQLName;
@GraphQLName(SchemaUtils.USER)
public class User {
@GraphQLField
private Long id;
@GraphQLField
private String name;
@GraphQLField
private String email;
@GraphQLField
private Integer age;
public User(String name, String email, Integer age) {
this.id = genId();
this.name = name;
this.email = email;
this.age = age;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setEmail(String email) {
this.email = email;
}
public String getEmail() {
return email;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public static Long genId() {
Long id = 1L;
try {
List<User> users = new UserHandler().getUsers();
for (User user : users)
id = (user.getId() > id ? user.getId() : id) + 1;
} catch (Exception e) {
e.printStackTrace();
}
return id;
}
public String toString() {
return "[id=" + id + ", name=" + name + ", email="+email+ ", age="+ age +"]";
}
}

View File

@@ -0,0 +1,59 @@
package com.baeldung.graphql.handler;
import graphql.ExecutionResult;
import graphql.GraphQL;
import graphql.schema.DataFetchingEnvironment;
import ratpack.handling.Context;
import ratpack.handling.Handler;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import com.baeldung.graphql.entity.User;
import com.baeldung.graphql.schema.UserSchema;
import com.baeldung.graphql.utils.SchemaUtils;
import static ratpack.jackson.Jackson.json;
public class UserHandler implements Handler {
private static final Logger LOGGER = Logger.getLogger(UserHandler.class.getSimpleName());
private static final List<User> USERS = new ArrayList<>();
private final GraphQL graphql;
public UserHandler() throws Exception {
graphql = GraphQL.newGraphQL(new UserSchema().getSchema()).build();
}
@Override
public void handle(Context context) {
context.parse(Map.class)
.then(payload -> {
Map<String, Object> parameters = (Map<String, Object>) payload.get("parameters");
ExecutionResult executionResult = graphql.execute(payload.get(SchemaUtils.QUERY)
.toString(), null, this, parameters);
Map<String, Object> result = new LinkedHashMap<>();
if (executionResult.getErrors().isEmpty()) {
result.put(SchemaUtils.DATA, executionResult.getData());
} else {
result.put(SchemaUtils.ERRORS, executionResult.getErrors());
LOGGER.warning("Errors: " + executionResult.getErrors());
}
context.render(json(result));
});
}
public List<User> getUsers() {
return USERS;
}
public static List<User> getUsers(DataFetchingEnvironment env) {
return ((UserHandler) env.getSource()).getUsers();
}
}

View File

@@ -0,0 +1,57 @@
package com.baeldung.graphql.mutation;
import graphql.annotations.GraphQLField;
import graphql.annotations.GraphQLName;
import graphql.schema.DataFetchingEnvironment;
import javax.validation.constraints.NotNull;
import com.baeldung.graphql.entity.User;
import com.baeldung.graphql.utils.SchemaUtils;
import java.util.List;
import java.util.Optional;
import static com.baeldung.graphql.handler.UserHandler.getUsers;
@GraphQLName(SchemaUtils.MUTATION)
public class UserMutation {
@GraphQLField
public static User createUser(final DataFetchingEnvironment env, @NotNull @GraphQLName(SchemaUtils.NAME) final String name, @NotNull @GraphQLName(SchemaUtils.EMAIL) final String email, @NotNull @GraphQLName(SchemaUtils.AGE) final String age) {
List<User> users = getUsers(env);
final User user = new User(name, email, Integer.valueOf(age));
users.add(user);
return user;
}
@GraphQLField
public static User updateUser(final DataFetchingEnvironment env, @NotNull @GraphQLName(SchemaUtils.ID) final String id, @NotNull @GraphQLName(SchemaUtils.NAME) final String name, @NotNull @GraphQLName(SchemaUtils.EMAIL) final String email,
@NotNull @GraphQLName(SchemaUtils.AGE) final String age) {
final Optional<User> user = getUsers(env).stream()
.filter(c -> c.getId() == Long.parseLong(id))
.findFirst();
if (!user.isPresent()) {
return null;
}
user.get()
.setName(name);
user.get()
.setEmail(email);
user.get()
.setAge(Integer.valueOf(age));
return user.get();
}
@GraphQLField
public static User deleteUser(final DataFetchingEnvironment env, @NotNull @GraphQLName(SchemaUtils.ID) final String id) {
final List<User> users = getUsers(env);
final Optional<User> user = users.stream()
.filter(c -> c.getId() == Long.parseLong(id))
.findFirst();
if (!user.isPresent()) {
return null;
}
users.removeIf(c -> c.getId() == Long.parseLong(id));
return user.get();
}
}

View File

@@ -0,0 +1,42 @@
package com.baeldung.graphql.query;
import graphql.annotations.GraphQLField;
import graphql.annotations.GraphQLName;
import graphql.schema.DataFetchingEnvironment;
import javax.validation.constraints.NotNull;
import com.baeldung.graphql.entity.User;
import com.baeldung.graphql.utils.SchemaUtils;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import static com.baeldung.graphql.handler.UserHandler.getUsers;
@GraphQLName(SchemaUtils.QUERY)
public class UserQuery {
@GraphQLField
public static User retrieveUser(final DataFetchingEnvironment env, @NotNull @GraphQLName(SchemaUtils.ID) final String id) {
final Optional<User> any = getUsers(env).stream()
.filter(c -> c.getId() == Long.parseLong(id))
.findFirst();
return any.orElse(null);
}
@GraphQLField
public static List<User> searchName(final DataFetchingEnvironment env, @NotNull @GraphQLName(SchemaUtils.NAME) final String name) {
return getUsers(env).stream()
.filter(c -> c.getName()
.contains(name))
.collect(Collectors.toList());
}
@GraphQLField
public static List<User> listUsers(final DataFetchingEnvironment env) {
return getUsers(env);
}
}

View File

@@ -0,0 +1,24 @@
package com.baeldung.graphql.schema;
import graphql.annotations.GraphQLAnnotations;
import graphql.schema.GraphQLSchema;
import static graphql.schema.GraphQLSchema.newSchema;
import com.baeldung.graphql.mutation.UserMutation;
import com.baeldung.graphql.query.UserQuery;
public class UserSchema {
private final GraphQLSchema schema;
public UserSchema() throws IllegalAccessException, NoSuchMethodException, InstantiationException {
schema = newSchema().query(GraphQLAnnotations.object(UserQuery.class))
.mutation(GraphQLAnnotations.object(UserMutation.class))
.build();
}
public GraphQLSchema getSchema() {
return schema;
}
}

View File

@@ -0,0 +1,36 @@
package com.baeldung.graphql.server;
import com.baeldung.graphql.data.BookRepository;
import com.coxautodev.graphql.tools.SchemaParser;
import graphql.schema.GraphQLSchema;
import graphql.servlet.SimpleGraphQLHttpServlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(urlPatterns = "/graphql")
public class GraphQLEndpoint extends HttpServlet {
private SimpleGraphQLHttpServlet graphQLServlet;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
graphQLServlet.service(req, resp);
}
@Override
public void init() {
GraphQLSchema schema = SchemaParser.newParser()
.resolvers(new GraphQLQuery(new BookRepository()))
.file("schema.graphqls")
.build()
.makeExecutableSchema();
graphQLServlet = SimpleGraphQLHttpServlet
.newBuilder(schema)
.build();
}
}

View File

@@ -0,0 +1,30 @@
package com.baeldung.graphql.server;
import com.baeldung.graphql.data.Book;
import com.baeldung.graphql.data.BookRepository;
import com.baeldung.graphqlreturnmap.entity.Product;
import com.coxautodev.graphql.tools.GraphQLQueryResolver;
import java.util.List;
public class GraphQLQuery implements GraphQLQueryResolver {
private final BookRepository repository;
public GraphQLQuery(BookRepository repository) {
this.repository = repository;
}
public List<Book> allBooks() {
return repository.getAllBooks();
}
public List<Product> getProducts(int pageSize, int pageNumber) {
return null;
}
public Product getProduct(int id) {
return null;
}
}

View File

@@ -0,0 +1,14 @@
package com.baeldung.graphql.utils;
public class SchemaUtils {
public static final String USER = "user";
public static final String ID = "id";
public static final String NAME = "name";
public static final String EMAIL = "email";
public static final String AGE = "age";
public static final String MUTATION = "mutation";
public static final String QUERY = "query";
public static final String ERRORS = "errors";
public static final String DATA = "data";
}

View File

@@ -0,0 +1,52 @@
package com.baeldung.graphqlreturnmap;
import com.baeldung.graphql.utils.SchemaUtils;
import com.baeldung.graphqlreturnmap.resolver.ProductResolver;
import com.baeldung.graphqlreturnmap.resolver.Query;
import com.coxautodev.graphql.tools.SchemaParser;
import graphql.ExecutionResult;
import graphql.GraphQL;
import graphql.scalars.ExtendedScalars;
import graphql.schema.GraphQLSchema;
import ratpack.handling.Context;
import ratpack.handling.Handler;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.logging.Logger;
import static ratpack.jackson.Jackson.json;
public class AppHandler implements Handler {
private static final Logger LOGGER = Logger.getLogger(AppHandler.class.getSimpleName());
private GraphQL graphql;
public AppHandler() throws Exception {
GraphQLSchema schema = SchemaParser.newParser()
.resolvers(new Query(), new ProductResolver())
.scalars(ExtendedScalars.Json)
.file("schema.graphqls")
.build()
.makeExecutableSchema();
graphql = GraphQL.newGraphQL(schema).build();
}
@Override
public void handle(Context context) throws Exception {
context.parse(Map.class)
.then(payload -> {
ExecutionResult executionResult = graphql.execute(payload.get(SchemaUtils.QUERY)
.toString(), null, this, Collections.emptyMap());
Map<String, Object> result = new LinkedHashMap<>();
if (executionResult.getErrors()
.isEmpty()) {
result.put(SchemaUtils.DATA, executionResult.getData());
} else {
result.put(SchemaUtils.ERRORS, executionResult.getErrors());
LOGGER.warning("Errors: " + executionResult.getErrors());
}
context.render(json(result));
});
}
}

View File

@@ -0,0 +1,24 @@
package com.baeldung.graphqlreturnmap;
import graphql.language.ScalarTypeDefinition;
import graphql.schema.Coercing;
import graphql.schema.GraphQLDirective;
import graphql.schema.GraphQLScalarType;
import java.util.List;
public class ExtendedGraphQLScalarType extends GraphQLScalarType {
public ExtendedGraphQLScalarType(){
super("","",null);
}
public ExtendedGraphQLScalarType(String name, String description, Coercing coercing) {
super(name, description, coercing);
}
public ExtendedGraphQLScalarType(String name, String description, Coercing coercing, List<GraphQLDirective> directives, ScalarTypeDefinition definition) {
super(name, description, coercing, directives, definition);
}
}

View File

@@ -0,0 +1,12 @@
package com.baeldung.graphqlreturnmap;
import ratpack.server.RatpackServer;
public class GraphqlReturnMap {
public static void main(String[] args) throws Exception {
final RatpackServer server = RatpackServer.of(s -> s.handlers(chain -> chain.post("product", new AppHandler())));
server.start();
}
}

View File

@@ -0,0 +1,46 @@
package com.baeldung.graphqlreturnmap.entity;
public class Attribute {
private String name;
private String description;
private String unit;
public Attribute(String name, String description, String unit){
this.name = name;
this.description = description;
this.unit = unit;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
}
@Override
public String toString() {
return "Attribute{" +
"name='" + name + '\'' +
", description='" + description + '\'' +
", unit='" + unit + '\'' +
'}';
}
}

View File

@@ -0,0 +1,48 @@
package com.baeldung.graphqlreturnmap.entity;
import java.util.Map;
public class Product {
private Integer id;
private String name;
private String description;
private Map<String, Attribute> attributes;
public Product(){
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Map<String, Attribute> getAttributes() {
return attributes;
}
public void setAttributes(Map<String, Attribute> attributes) {
this.attributes = attributes;
}
}

View File

@@ -0,0 +1,30 @@
package com.baeldung.graphqlreturnmap.model;
import com.baeldung.graphqlreturnmap.entity.Attribute;
public class AttributeKeyValueModel {
private String key;
private Attribute value;
public AttributeKeyValueModel(String key, Attribute value) {
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public Attribute getValue() {
return value;
}
public void setValue(Attribute value) {
this.value = value;
}
}

View File

@@ -0,0 +1,12 @@
package com.baeldung.graphqlreturnmap.repository;
import com.baeldung.graphqlreturnmap.entity.Product;
import java.util.List;
public interface ProductRepository {
List<Product> getProducts(Integer pageSize, Integer pageNumber);
Product getProduct(Integer id);
}

View File

@@ -0,0 +1,43 @@
package com.baeldung.graphqlreturnmap.repository.impl;
import com.baeldung.graphqlreturnmap.entity.Attribute;
import com.baeldung.graphqlreturnmap.entity.Product;
import com.baeldung.graphqlreturnmap.repository.ProductRepository;
import org.springframework.stereotype.Repository;
import java.util.*;
import java.util.stream.Collectors;
@Repository
public class ProductRepositoryImpl implements ProductRepository {
private static List<Product> productList = new ArrayList<>();
public ProductRepositoryImpl() {
for (int i = 1; i <= 10; i++){
Product product = new Product();
product.setId(i);
product.setName(String.format("Product %d", i));
product.setDescription(String.format("Product %d description", i));
product.setAttributes(createAttributes(i));
productList.add(product);
}
}
private Map<String, Attribute> createAttributes(int i) {
Map<String, Attribute> attributeMap = new HashMap<>();
attributeMap.put(String.format("attribute_%d",i), new Attribute(String.format("Attribute%d name",i),"This is custom attribute description","This is custom attribute unit"));
attributeMap.put("size", new Attribute((i & 1) == 0 ? "Small" : "Large","This is custom attribute description","This is custom attribute unit"));
return attributeMap;
}
@Override
public List<Product> getProducts(Integer pageSize, Integer pageNumber) {
return productList.stream().skip(pageSize*pageNumber).limit(pageSize).collect(Collectors.toList());
}
@Override
public Product getProduct(Integer id) {
return productList.stream().filter(product -> product.getId().equals(id)).findFirst().orElse(null);
}
}

View File

@@ -0,0 +1,30 @@
package com.baeldung.graphqlreturnmap.resolver;
import com.baeldung.graphqlreturnmap.entity.Product;
import com.baeldung.graphqlreturnmap.model.AttributeKeyValueModel;
import com.coxautodev.graphql.tools.GraphQLResolver;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.LinkedList;
import java.util.List;
public class ProductResolver implements GraphQLResolver<Product> {
public ProductResolver(){
}
public List<AttributeKeyValueModel> getAttribute_list(Product product){
List<AttributeKeyValueModel> attributeModelList = new LinkedList<>();
product.getAttributes().forEach((key, val) -> attributeModelList.add(new AttributeKeyValueModel(key, val)));
return attributeModelList;
}
public String getAttribute_string(Product product){
try {
return new ObjectMapper().writeValueAsString(product.getAttributes());
} catch (JsonProcessingException e) {
e.printStackTrace();
return "";
}
}
}

View File

@@ -0,0 +1,33 @@
package com.baeldung.graphqlreturnmap.resolver;
import com.baeldung.graphql.data.Book;
import com.baeldung.graphqlreturnmap.entity.Product;
import com.baeldung.graphqlreturnmap.repository.ProductRepository;
import com.baeldung.graphqlreturnmap.repository.impl.ProductRepositoryImpl;
import com.coxautodev.graphql.tools.GraphQLQueryResolver;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
public class Query implements GraphQLQueryResolver {
@Autowired
private ProductRepository productRepository;
public Query(){
productRepository = new ProductRepositoryImpl();
}
public List<Product> getProducts(int pageSize, int pageNumber) {
return productRepository.getProducts(pageSize, pageNumber);
}
public Product getProduct(int id) {
return productRepository.getProduct(id);
}
public List<Book> allBooks() {
return null;
}
}

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@@ -0,0 +1,43 @@
type Book {
title: String!
author: Author
}
type Author {
name: String!
surname: String!
}
type Query {
allBooks: [Book]
products(size: Int, page: Int): [Product]!
product(id: Int): Product!
}
type Product {
id: ID
name: String!
description: String
attribute_string:String
attribute_list:[AttributeKeyValuePair]
attributes: JSON
}
type AttributeKeyValuePair {
key:String
value:Attribute
}
type Attribute {
name:String
description:String
unit:String
}
scalar JSON
schema {
query: Query
}

View File

@@ -0,0 +1,88 @@
package com.baeldung.graphql;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.mockserver.client.MockServerClient;
import org.mockserver.configuration.Configuration;
import org.mockserver.integration.ClientAndServer;
import org.mockserver.model.HttpStatusCode;
import org.slf4j.event.Level;
import java.io.IOException;
import java.net.ServerSocket;
import static org.mockserver.integration.ClientAndServer.startClientAndServer;
import static org.mockserver.matchers.Times.exactly;
import static org.mockserver.model.HttpRequest.request;
import static org.mockserver.model.HttpResponse.response;
public class GraphQLMockServer {
private static final String SERVER_ADDRESS = "127.0.0.1";
private static final String PATH = "/graphql";
public static String serviceUrl;
private static ClientAndServer mockServer;
private static int serverPort;
@BeforeAll
static void startServer() throws IOException {
serverPort = getFreePort();
serviceUrl = "http://" + SERVER_ADDRESS + ":" + serverPort + PATH;
Configuration config = Configuration.configuration().logLevel(Level.WARN);
mockServer = startClientAndServer(config, serverPort);
mockAllBooksTitleRequest();
mockAllBooksTitleAuthorRequest();
}
@AfterAll
static void stopServer() {
mockServer.stop();
}
private static void mockAllBooksTitleAuthorRequest() {
String requestQuery = "{allBooks{title,author{name,surname}}}";
String responseJson = "{\"data\":{\"allBooks\":[{\"title\":\"Title 1\",\"author\":{\"name\":\"Pero\",\"surname\":\"Peric\"}},{\"title\":\"Title 2\",\"author\":{\"name\":\"Marko\",\"surname\":\"Maric\"}}]}}";
new MockServerClient(SERVER_ADDRESS, serverPort)
.when(
request()
.withPath(PATH)
.withQueryStringParameter("query", requestQuery),
exactly(1)
)
.respond(
response()
.withStatusCode(HttpStatusCode.OK_200.code())
.withBody(responseJson)
);
}
private static void mockAllBooksTitleRequest() {
String requestQuery = "{allBooks{title}}";
String responseJson = "{\"data\":{\"allBooks\":[{\"title\":\"Title 1\"},{\"title\":\"Title 2\"}]}}";
new MockServerClient(SERVER_ADDRESS, serverPort)
.when(
request()
.withPath(PATH)
.withQueryStringParameter("query", requestQuery),
exactly(1)
)
.respond(
response()
.withStatusCode(HttpStatusCode.OK_200.code())
.withBody(responseJson)
);
}
private static int getFreePort () throws IOException {
try (ServerSocket serverSocket = new ServerSocket(0)) {
return serverSocket.getLocalPort();
}
}
}

View File

@@ -0,0 +1,39 @@
package com.baeldung.graphql.clients;
import com.baeldung.graphql.GraphQLMockServer;
import com.baeldung.graphql.data.Data;
import io.aexp.nodes.graphql.GraphQLResponseEntity;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertAll;
class AmericanExpressNodesUnitTest extends GraphQLMockServer {
@Test
void givenGraphQLEndpoint_whenRequestingAllBooksWithTitle_thenExpectedJsonIsReturned() throws IOException {
GraphQLResponseEntity<Data> responseEntity = AmericanExpressNodes.callGraphQLService(serviceUrl, "{allBooks{title}}");
assertAll(
() -> assertThat(responseEntity.getResponse().getAllBooks()).hasSize(2),
() -> assertThat(responseEntity.getResponse().getAllBooks().get(0).getTitle()).isEqualTo("Title 1"),
() -> assertThat(responseEntity.getResponse().getAllBooks().get(1).getTitle()).isEqualTo("Title 2")
);
}
@Test
void givenGraphQLEndpoint_whenRequestingAllBooksWithTitleAndAuthor_thenExpectedJsonIsReturned() throws IOException {
GraphQLResponseEntity<Data> responseEntity = AmericanExpressNodes.callGraphQLService(serviceUrl, "{allBooks{title,author{name,surname}}}");
assertAll(
() -> assertThat(responseEntity.getResponse().getAllBooks()).hasSize(2),
() -> assertThat(responseEntity.getResponse().getAllBooks().get(0).getTitle()).isEqualTo("Title 1"),
() -> assertThat(responseEntity.getResponse().getAllBooks().get(0).getAuthor().getFullName()).isEqualTo("Pero Peric"),
() -> assertThat(responseEntity.getResponse().getAllBooks().get(1).getTitle()).isEqualTo("Title 2"),
() -> assertThat(responseEntity.getResponse().getAllBooks().get(1).getAuthor().getFullName()).isEqualTo("Marko Maric")
);
}
}

View File

@@ -0,0 +1,49 @@
package com.baeldung.graphql.clients;
import com.baeldung.graphql.GraphQLMockServer;
import com.baeldung.graphql.data.Response;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertAll;
class ApacheHttpClientUnitTest extends GraphQLMockServer {
private static final ObjectMapper objectMapper = new ObjectMapper();
@Test
void givenGraphQLEndpoint_whenRequestingAllBooksWithTitle_thenExpectedJsonIsReturned() throws IOException, URISyntaxException {
HttpResponse httpResponse = ApacheHttpClient.callGraphQLService(serviceUrl, "{allBooks{title}}");
String actualResponse = IOUtils.toString(httpResponse.getEntity().getContent(), StandardCharsets.UTF_8.name());
Response parsedResponse = objectMapper.readValue(actualResponse, Response.class);
assertAll(
() -> assertThat(parsedResponse.getData().getAllBooks()).hasSize(2),
() -> assertThat(parsedResponse.getData().getAllBooks().get(0).getTitle()).isEqualTo("Title 1"),
() -> assertThat(parsedResponse.getData().getAllBooks().get(1).getTitle()).isEqualTo("Title 2")
);
}
@Test
void givenGraphQLEndpoint_whenRequestingAllBooksWithTitleAndAuthor_thenExpectedJsonIsReturned() throws IOException, URISyntaxException {
HttpResponse httpResponse = ApacheHttpClient.callGraphQLService(serviceUrl, "{allBooks{title,author{name,surname}}}");
String actualResponse = IOUtils.toString(httpResponse.getEntity().getContent(), StandardCharsets.UTF_8.name());
Response parsedResponse = objectMapper.readValue(actualResponse, Response.class);
assertAll(
() -> assertThat(parsedResponse.getData().getAllBooks()).hasSize(2),
() -> assertThat(parsedResponse.getData().getAllBooks().get(0).getTitle()).isEqualTo("Title 1"),
() -> assertThat(parsedResponse.getData().getAllBooks().get(0).getAuthor().getFullName()).isEqualTo("Pero Peric"),
() -> assertThat(parsedResponse.getData().getAllBooks().get(1).getTitle()).isEqualTo("Title 2"),
() -> assertThat(parsedResponse.getData().getAllBooks().get(1).getAuthor().getFullName()).isEqualTo("Marko Maric")
);
}
}