Skip to content

Commit 841c07b

Browse files
authored
Return Map from GraphQL (eugenp#11966)
* Return Map from GraphQL Three techniques have been used 1. Return as Json String 2. Return Json using GraphQL scalar type 3. Return as list of key-value pair * Adding custom scalar in plugin configuration * Build failure fix 1. Integrating the .graphqls files 2. Updating the respective query resolvers * Build failure Fix 1. Removed the extra .graphql file 2. Added ExtendedGraphQLScalarType class because the parent class didn't have default constructor and the client code generation plugin was requiring it. * Code refactoring * Code refactoring
1 parent 8636934 commit 841c07b

13 files changed

Lines changed: 398 additions & 1 deletion

File tree

graphql/graphql-java/pom.xml

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,21 @@
3636
<artifactId>graphql-java-annotations</artifactId>
3737
<version>${graphql-java-annotations.version}</version>
3838
</dependency>
39+
<dependency>
40+
<groupId>io.ratpack</groupId>
41+
<artifactId>ratpack-core</artifactId>
42+
<version>${ratpack-core.version}</version>
43+
</dependency>
44+
<dependency>
45+
<groupId>com.github.americanexpress.nodes</groupId>
46+
<artifactId>nodes</artifactId>
47+
<version>0.5.0</version>
48+
</dependency>
49+
<dependency>
50+
<groupId>com.graphql-java</groupId>
51+
<artifactId>graphql-java</artifactId>
52+
<version>11.0</version>
53+
</dependency>
3954
<dependency>
4055
<groupId>com.graphql-java</groupId>
4156
<artifactId>graphql-java-tools</artifactId>
@@ -95,6 +110,14 @@
95110
<version>${mockserver-client-java.version}</version>
96111
<scope>test</scope>
97112
</dependency>
113+
114+
<dependency>
115+
<groupId>com.graphql-java</groupId>
116+
<artifactId>graphql-java-extended-scalars</artifactId>
117+
<version>${graphql-java-extended-scalars.version}</version>
118+
</dependency>
119+
120+
98121
</dependencies>
99122

100123
<build>
@@ -133,6 +156,13 @@
133156
<copyRuntimeSources>false</copyRuntimeSources>
134157
<generateDeprecatedRequestResponse>false</generateDeprecatedRequestResponse>
135158
<separateUtilityClasses>true</separateUtilityClasses>
159+
<customScalars>
160+
<customScalar>
161+
<graphQLTypeName>JSON</graphQLTypeName>
162+
<javaType>java.util.Map</javaType>
163+
<graphQLScalarTypeClass>com.baeldung.graphqlreturnmap.ExtendedGraphQLScalarType</graphQLScalarTypeClass>
164+
</customScalar>
165+
</customScalars>
136166
</configuration>
137167
</plugin>
138168
</plugins>
@@ -154,6 +184,8 @@
154184

155185
<maven.compiler.source>1.8</maven.compiler.source>
156186
<maven.compiler.target>1.8</maven.compiler.target>
187+
<graphql.java.generator.version>1.18</graphql.java.generator.version>
188+
<graphql-java-extended-scalars.version>2022-04-06T00-10-27-a70541e</graphql-java-extended-scalars.version>
157189
</properties>
158190

159-
</project>
191+
</project>

graphql/graphql-java/src/main/java/com/baeldung/graphql/server/GraphQLQuery.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.baeldung.graphql.data.Book;
44
import com.baeldung.graphql.data.BookRepository;
5+
import com.baeldung.graphqlreturnmap.entity.Product;
56
import com.coxautodev.graphql.tools.GraphQLQueryResolver;
67

78
import java.util.List;
@@ -18,4 +19,12 @@ public List<Book> allBooks() {
1819
return repository.getAllBooks();
1920
}
2021

22+
public List<Product> getProducts(int pageSize, int pageNumber) {
23+
return null;
24+
}
25+
26+
public Product getProduct(int id) {
27+
return null;
28+
}
29+
2130
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.baeldung.graphqlreturnmap;
2+
3+
import com.baeldung.graphql.utils.SchemaUtils;
4+
import com.baeldung.graphqlreturnmap.resolver.ProductResolver;
5+
import com.baeldung.graphqlreturnmap.resolver.Query;
6+
import com.coxautodev.graphql.tools.SchemaParser;
7+
import graphql.ExecutionResult;
8+
import graphql.GraphQL;
9+
import graphql.scalars.ExtendedScalars;
10+
import graphql.schema.GraphQLSchema;
11+
import ratpack.handling.Context;
12+
import ratpack.handling.Handler;
13+
14+
import java.util.Collections;
15+
import java.util.LinkedHashMap;
16+
import java.util.Map;
17+
import java.util.logging.Logger;
18+
19+
import static ratpack.jackson.Jackson.json;
20+
21+
public class AppHandler implements Handler {
22+
private static final Logger LOGGER = Logger.getLogger(AppHandler.class.getSimpleName());
23+
private GraphQL graphql;
24+
25+
public AppHandler() throws Exception {
26+
GraphQLSchema schema = SchemaParser.newParser()
27+
.resolvers(new Query(), new ProductResolver())
28+
.scalars(ExtendedScalars.Json)
29+
.file("schema.graphqls")
30+
.build()
31+
.makeExecutableSchema();
32+
graphql = GraphQL.newGraphQL(schema).build();
33+
}
34+
35+
@Override
36+
public void handle(Context context) throws Exception {
37+
context.parse(Map.class)
38+
.then(payload -> {
39+
ExecutionResult executionResult = graphql.execute(payload.get(SchemaUtils.QUERY)
40+
.toString(), null, this, Collections.emptyMap());
41+
Map<String, Object> result = new LinkedHashMap<>();
42+
if (executionResult.getErrors()
43+
.isEmpty()) {
44+
result.put(SchemaUtils.DATA, executionResult.getData());
45+
} else {
46+
result.put(SchemaUtils.ERRORS, executionResult.getErrors());
47+
LOGGER.warning("Errors: " + executionResult.getErrors());
48+
}
49+
context.render(json(result));
50+
});
51+
}
52+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.baeldung.graphqlreturnmap;
2+
3+
import graphql.language.ScalarTypeDefinition;
4+
import graphql.schema.Coercing;
5+
import graphql.schema.GraphQLDirective;
6+
import graphql.schema.GraphQLScalarType;
7+
8+
import java.util.List;
9+
10+
public class ExtendedGraphQLScalarType extends GraphQLScalarType {
11+
12+
public ExtendedGraphQLScalarType(){
13+
super("","",null);
14+
15+
}
16+
17+
public ExtendedGraphQLScalarType(String name, String description, Coercing coercing) {
18+
super(name, description, coercing);
19+
}
20+
21+
public ExtendedGraphQLScalarType(String name, String description, Coercing coercing, List<GraphQLDirective> directives, ScalarTypeDefinition definition) {
22+
super(name, description, coercing, directives, definition);
23+
}
24+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.baeldung.graphqlreturnmap;
2+
3+
import ratpack.server.RatpackServer;
4+
5+
public class GraphqlReturnMap {
6+
7+
public static void main(String[] args) throws Exception {
8+
final RatpackServer server = RatpackServer.of(s -> s.handlers(chain -> chain.post("product", new AppHandler())));
9+
server.start();
10+
}
11+
12+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.baeldung.graphqlreturnmap.entity;
2+
3+
public class Attribute {
4+
private String name;
5+
private String description;
6+
private String unit;
7+
8+
public Attribute(String name, String description, String unit){
9+
this.name = name;
10+
this.description = description;
11+
this.unit = unit;
12+
}
13+
14+
public String getName() {
15+
return name;
16+
}
17+
18+
public void setName(String name) {
19+
this.name = name;
20+
}
21+
22+
public String getDescription() {
23+
return description;
24+
}
25+
26+
public void setDescription(String description) {
27+
this.description = description;
28+
}
29+
30+
public String getUnit() {
31+
return unit;
32+
}
33+
34+
public void setUnit(String unit) {
35+
this.unit = unit;
36+
}
37+
38+
@Override
39+
public String toString() {
40+
return "Attribute{" +
41+
"name='" + name + '\'' +
42+
", description='" + description + '\'' +
43+
", unit='" + unit + '\'' +
44+
'}';
45+
}
46+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.baeldung.graphqlreturnmap.entity;
2+
3+
4+
import java.util.Map;
5+
6+
public class Product {
7+
private Integer id;
8+
private String name;
9+
private String description;
10+
private Map<String, Attribute> attributes;
11+
12+
13+
public Product(){
14+
15+
}
16+
17+
public Integer getId() {
18+
return id;
19+
}
20+
21+
public void setId(Integer id) {
22+
this.id = id;
23+
}
24+
25+
public String getName() {
26+
return name;
27+
}
28+
29+
public void setName(String name) {
30+
this.name = name;
31+
}
32+
33+
public String getDescription() {
34+
return description;
35+
}
36+
37+
public void setDescription(String description) {
38+
this.description = description;
39+
}
40+
41+
public Map<String, Attribute> getAttributes() {
42+
return attributes;
43+
}
44+
45+
public void setAttributes(Map<String, Attribute> attributes) {
46+
this.attributes = attributes;
47+
}
48+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.baeldung.graphqlreturnmap.model;
2+
3+
4+
import com.baeldung.graphqlreturnmap.entity.Attribute;
5+
6+
public class AttributeKeyValueModel {
7+
private String key;
8+
private Attribute value;
9+
10+
public AttributeKeyValueModel(String key, Attribute value) {
11+
this.key = key;
12+
this.value = value;
13+
}
14+
15+
public String getKey() {
16+
return key;
17+
}
18+
19+
public void setKey(String key) {
20+
this.key = key;
21+
}
22+
23+
public Attribute getValue() {
24+
return value;
25+
}
26+
27+
public void setValue(Attribute value) {
28+
this.value = value;
29+
}
30+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.baeldung.graphqlreturnmap.repository;
2+
3+
4+
import com.baeldung.graphqlreturnmap.entity.Product;
5+
6+
import java.util.List;
7+
8+
public interface ProductRepository {
9+
List<Product> getProducts(Integer pageSize, Integer pageNumber);
10+
Product getProduct(Integer id);
11+
12+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com.baeldung.graphqlreturnmap.repository.impl;
2+
3+
import com.baeldung.graphqlreturnmap.entity.Attribute;
4+
import com.baeldung.graphqlreturnmap.entity.Product;
5+
import com.baeldung.graphqlreturnmap.repository.ProductRepository;
6+
import org.springframework.stereotype.Repository;
7+
8+
import java.util.*;
9+
import java.util.stream.Collectors;
10+
11+
@Repository
12+
public class ProductRepositoryImpl implements ProductRepository {
13+
14+
private static List<Product> productList = new ArrayList<>();
15+
16+
public ProductRepositoryImpl() {
17+
for (int i = 1; i <= 10; i++){
18+
Product product = new Product();
19+
product.setId(i);
20+
product.setName(String.format("Product %d", i));
21+
product.setDescription(String.format("Product %d description", i));
22+
product.setAttributes(createAttributes(i));
23+
productList.add(product);
24+
}
25+
}
26+
27+
private Map<String, Attribute> createAttributes(int i) {
28+
Map<String, Attribute> attributeMap = new HashMap<>();
29+
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"));
30+
attributeMap.put("size", new Attribute((i & 1) == 0 ? "Small" : "Large","This is custom attribute description","This is custom attribute unit"));
31+
return attributeMap;
32+
}
33+
34+
@Override
35+
public List<Product> getProducts(Integer pageSize, Integer pageNumber) {
36+
return productList.stream().skip(pageSize*pageNumber).limit(pageSize).collect(Collectors.toList());
37+
}
38+
39+
@Override
40+
public Product getProduct(Integer id) {
41+
return productList.stream().filter(product -> product.getId().equals(id)).findFirst().orElse(null);
42+
}
43+
}

0 commit comments

Comments
 (0)