Skip to content

Commit 9eae21d

Browse files
author
etienne-sf
committed
Code reported from the Maven tutorial (README is to be adapted)
0 parents  commit 9eae21d

29 files changed

+2924
-0
lines changed

.gitignore

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Compiled class file
2+
*.class
3+
4+
# Log file
5+
*.log
6+
7+
# BlueJ files
8+
*.ctxt
9+
10+
# Mobile Tools for Java (J2ME)
11+
.mtj.tmp/
12+
13+
# Package Files #
14+
*.jar
15+
*.war
16+
*.nar
17+
*.ear
18+
*.zip
19+
*.tar.gz
20+
*.rar
21+
22+
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
23+
hs_err_pid*
24+
/.gradle/
25+
26+
# Eclipse files
27+
.classpath
28+
.project
29+
**/.settings
30+
**/bin
31+
32+
# Gradle files
33+
**/.gradle
34+
build/

README.md

Lines changed: 1089 additions & 0 deletions
Large diffs are not rendered by default.

build.gradle

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
plugins {
2+
id "com.graphql_java_generator.graphql-gradle-plugin" version "1.8.1"
3+
id 'java'
4+
}
5+
6+
repositories {
7+
jcenter()
8+
mavenCentral()
9+
}
10+
11+
dependencies {
12+
// The graphql-java-runtime module agregates all dependencies for the generated code, including the plugin runtime
13+
// CAUTION: this version should be exactly the same as the graphql-gradle-plugin's version
14+
implementation "com.graphql-java-generator:graphql-java-runtime:1.8.1"
15+
//implementation "org.apache.logging.log4j:log4j-slf4j-impl:2.12.1"
16+
implementation 'com.github.dozermapper:dozer-core:6.5.0'
17+
implementation 'io.reactivex.rxjava2:rxjava:2.2.19'
18+
19+
// The Spring Boot version should be the same as the Spring Boot version of the graphql-gradle-plugin
20+
implementation('org.springframework.boot:spring-boot-starter-data-jpa:2.2.6.RELEASE') {
21+
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
22+
}
23+
24+
runtime 'com.graphql-java-kickstart:graphiql-spring-boot-starter:6.0.1'
25+
runtime 'com.h2database:h2:1.4.199'
26+
}
27+
28+
// The line below makes the GraphQL plugin be executed before Java compiles, so that all sources are generated on time
29+
compileJava.dependsOn graphqlGenerateCode
30+
31+
// The line below adds the generated sources as a java source folder
32+
sourceSets.main.java.srcDirs += '/build/generated/graphqlGenerateCode'
33+
34+
// Let's configure the GraphQL Gradle Plugin:
35+
// All available parameters are described here:
36+
// https://graphql-maven-plugin-project.graphql-java-generator.com/graphql-maven-plugin/graphql-mojo.html
37+
graphql {
38+
mode = "server" //This line is here only for the demo, as client is the default mode
39+
packageName = 'org.forum.server'
40+
packageName = 'org.forum.server.graphql'
41+
scanBasePackages = 'org.forum.server.impl, org.forum.server.jpa'
42+
customScalars = [ [
43+
graphQLTypeName: "Date",
44+
javaType: "java.util.Date",
45+
graphQLScalarTypeStaticField: "com.graphql_java_generator.customscalars.GraphQLScalarTypeDate.Date"
46+
] ]
47+
48+
// The parameters below change the 1.x default behavior to respect the future 2.x behavior
49+
copyRuntimeSources = false
50+
generateDeprecatedRequestResponse = false
51+
separateUtilityClasses = true
52+
}
53+
54+

settings.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rootProject.name = 'GraphQL-Forum-Gradle-Tutorial-server'
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package org.forum.server.impl;
2+
3+
import java.util.Date;
4+
import java.util.List;
5+
import java.util.UUID;
6+
7+
import javax.annotation.Resource;
8+
9+
import org.forum.server.graphql.Board;
10+
import org.forum.server.graphql.Topic;
11+
import org.forum.server.graphql.util.DataFetchersDelegateBoard;
12+
import org.forum.server.jpa.BoardEntity;
13+
import org.forum.server.jpa.TopicEntity;
14+
import org.forum.server.jpa.repositories.BoardRepository;
15+
import org.forum.server.jpa.repositories.TopicRepository;
16+
import org.springframework.stereotype.Component;
17+
18+
import graphql.schema.DataFetchingEnvironment;
19+
20+
@Component
21+
public class DataFetchersDelegateBoardImpl implements DataFetchersDelegateBoard {
22+
23+
/** An internal utility to map lists of a type into list of another type */
24+
@Resource
25+
private Util util;
26+
27+
@Resource
28+
BoardRepository boardRepository;
29+
@Resource
30+
TopicRepository topicRepository;
31+
32+
@Override
33+
public List<Topic> topics(DataFetchingEnvironment dataFetchingEnvironment, Board origin, Date since) {
34+
List<TopicEntity> topics;
35+
36+
// The query to execute depends on the since param: is it given?
37+
if (since == null) {
38+
topics = topicRepository.findByBoardId(origin.getId());
39+
} else {
40+
topics = topicRepository.findByBoardIdAndSince(origin.getId(), since);
41+
}
42+
43+
return util.mapList(topics, TopicEntity.class, Topic.class);
44+
}
45+
46+
@Override
47+
public List<Board> batchLoader(List<UUID> keys) {
48+
Iterable<BoardEntity> boards = boardRepository.findAllById(keys);
49+
return util.mapList(boards, BoardEntity.class, Board.class);
50+
}
51+
52+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package org.forum.server.impl;
2+
3+
import java.util.List;
4+
import java.util.UUID;
5+
6+
import javax.annotation.Resource;
7+
8+
import org.forum.server.graphql.Member;
9+
import org.forum.server.graphql.util.DataFetchersDelegateMember;
10+
import org.forum.server.jpa.MemberEntity;
11+
import org.forum.server.jpa.repositories.MemberRepository;
12+
import org.springframework.stereotype.Component;
13+
14+
@Component
15+
public class DataFetchersDelegateMemberImpl implements DataFetchersDelegateMember {
16+
17+
/** An internal utility to map lists of a type into list of another type */
18+
@Resource
19+
private Util util;
20+
21+
@Resource
22+
private MemberRepository memberRepository;
23+
24+
@Override
25+
public List<Member> batchLoader(List<UUID> keys) {
26+
Iterable<MemberEntity> members = memberRepository.findAllById(keys);
27+
return util.mapList(members, MemberEntity.class, Member.class);
28+
}
29+
30+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package org.forum.server.impl;
2+
3+
import java.util.List;
4+
5+
import javax.annotation.Resource;
6+
7+
import org.forum.server.graphql.Board;
8+
import org.forum.server.graphql.Post;
9+
import org.forum.server.graphql.PostInput;
10+
import org.forum.server.graphql.Topic;
11+
import org.forum.server.graphql.TopicInput;
12+
import org.forum.server.graphql.util.DataFetchersDelegateMutationType;
13+
import org.forum.server.jpa.BoardEntity;
14+
import org.forum.server.jpa.PostEntity;
15+
import org.forum.server.jpa.TopicEntity;
16+
import org.forum.server.jpa.repositories.BoardRepository;
17+
import org.forum.server.jpa.repositories.PostRepository;
18+
import org.forum.server.jpa.repositories.TopicRepository;
19+
import org.springframework.stereotype.Component;
20+
21+
import com.github.dozermapper.core.Mapper;
22+
23+
import graphql.schema.DataFetchingEnvironment;
24+
import io.reactivex.subjects.Subject;
25+
26+
@Component
27+
public class DataFetchersDelegateMutationTypeImpl implements DataFetchersDelegateMutationType {
28+
29+
@Resource
30+
private Mapper mapper;
31+
32+
@Resource
33+
BoardRepository boardRepository;
34+
@Resource
35+
TopicRepository topicRepository;
36+
@Resource
37+
PostRepository postRepository;
38+
39+
/**
40+
* This {@link Subject} will be notified for each Post creation. This is the basis for the <I>subscribeToNewPost</I>
41+
* subscription
42+
*/
43+
@Resource
44+
PostPublisher postPublisher;
45+
46+
@Override
47+
public Board createBoard(DataFetchingEnvironment dataFetchingEnvironment, String name, Boolean publiclyAvailable) {
48+
BoardEntity board = new BoardEntity();
49+
board.setName(name);
50+
if (publiclyAvailable != null) {
51+
board.setPubliclyAvailable(publiclyAvailable);
52+
}
53+
boardRepository.save(board);
54+
return mapper.map(board, Board.class);
55+
}
56+
57+
@Override
58+
public Topic createTopic(DataFetchingEnvironment dataFetchingEnvironment, TopicInput topicInput) {
59+
TopicEntity newTopic = new TopicEntity();
60+
newTopic.setBoardId(topicInput.getBoardId());
61+
newTopic.setAuthorId(topicInput.getInput().getAuthorId());
62+
newTopic.setPubliclyAvailable(topicInput.getInput().getPubliclyAvailable());
63+
newTopic.setDate(topicInput.getInput().getDate());
64+
newTopic.setTitle(topicInput.getInput().getTitle());
65+
newTopic.setContent(topicInput.getInput().getContent());
66+
newTopic.setNbPosts(0);
67+
topicRepository.save(newTopic);
68+
return mapper.map(newTopic, Topic.class);
69+
}
70+
71+
@Override
72+
public Post createPost(DataFetchingEnvironment dataFetchingEnvironment, PostInput postParam) {
73+
PostEntity newPostEntity = new PostEntity();
74+
newPostEntity.setTopicId(postParam.getTopicId());
75+
newPostEntity.setAuthorId(postParam.getInput().getAuthorId());
76+
newPostEntity.setPubliclyAvailable(postParam.getInput().getPubliclyAvailable());
77+
newPostEntity.setDate(postParam.getInput().getDate());
78+
newPostEntity.setTitle(postParam.getInput().getTitle());
79+
newPostEntity.setContent(postParam.getInput().getContent());
80+
postRepository.save(newPostEntity);
81+
82+
Post newPost = mapper.map(newPostEntity, Post.class);
83+
84+
// Let's publish that new post, in case someone subscribed to the subscribeToNewPost GraphQL subscription
85+
postPublisher.onNext(newPost);
86+
87+
return newPost;
88+
}
89+
90+
@Override
91+
public List<Post> createPosts(DataFetchingEnvironment dataFetchingEnvironment, List<PostInput> spam) {
92+
// Actually, this mutation is for sample only. We don't want to implement it !
93+
// :)
94+
throw new RuntimeException("Spamming is forbidden");
95+
}
96+
97+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package org.forum.server.impl;
2+
3+
import java.util.List;
4+
import java.util.UUID;
5+
import java.util.concurrent.CompletableFuture;
6+
7+
import javax.annotation.Resource;
8+
9+
import org.dataloader.DataLoader;
10+
import org.forum.server.graphql.Member;
11+
import org.forum.server.graphql.Post;
12+
import org.forum.server.graphql.util.DataFetchersDelegatePost;
13+
import org.forum.server.jpa.MemberEntity;
14+
import org.forum.server.jpa.PostEntity;
15+
import org.forum.server.jpa.repositories.MemberRepository;
16+
import org.forum.server.jpa.repositories.PostRepository;
17+
import org.springframework.stereotype.Component;
18+
19+
import com.github.dozermapper.core.Mapper;
20+
21+
import graphql.schema.DataFetchingEnvironment;
22+
23+
@Component
24+
public class DataFetchersDelegatePostImpl implements DataFetchersDelegatePost {
25+
26+
@Resource
27+
private Mapper mapper;
28+
/** An internal utility to map lists of a type into list of another type */
29+
@Resource
30+
private Util util;
31+
32+
@Resource
33+
private MemberRepository memberRepository;
34+
@Resource
35+
private PostRepository postRepository;
36+
37+
@Override
38+
public Member author(DataFetchingEnvironment dataFetchingEnvironment, Post origin) {
39+
MemberEntity author = memberRepository.findAuthorOfTopic(origin.getId());
40+
return mapper.map(author, Member.class);
41+
}
42+
43+
@Override
44+
public CompletableFuture<Member> author(DataFetchingEnvironment dataFetchingEnvironment,
45+
DataLoader<UUID, Member> dataLoader, Post origin) {
46+
// TODO Store in cache the Post (as it has already been read) to avoid the query below
47+
PostEntity post = postRepository.findById(origin.getId()).get();
48+
49+
return dataLoader.load(post.getAuthorId());
50+
}
51+
52+
@Override
53+
public List<Post> batchLoader(List<UUID> keys) {
54+
Iterable<PostEntity> topics = postRepository.findAllById(keys);
55+
return util.mapList(topics, PostEntity.class, Post.class);
56+
}
57+
58+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package org.forum.server.impl;
2+
3+
import java.util.List;
4+
5+
import javax.annotation.Resource;
6+
7+
import org.forum.server.graphql.Board;
8+
import org.forum.server.graphql.Topic;
9+
import org.forum.server.graphql.util.DataFetchersDelegateQueryType;
10+
import org.forum.server.jpa.BoardEntity;
11+
import org.forum.server.jpa.TopicEntity;
12+
import org.forum.server.jpa.repositories.BoardRepository;
13+
import org.forum.server.jpa.repositories.TopicRepository;
14+
import org.springframework.stereotype.Component;
15+
16+
import com.github.dozermapper.core.Mapper;
17+
18+
import graphql.schema.DataFetchingEnvironment;
19+
20+
@Component
21+
public class DataFetchersDelegateQueryTypeImpl implements DataFetchersDelegateQueryType {
22+
23+
@Resource
24+
private BoardRepository boardRepository;
25+
@Resource
26+
private TopicRepository topicRepository;
27+
28+
/**
29+
* The <A HREF="https://github.com/DozerMapper/dozer/">Dozer mapper</A> will allow the mapping between the JPA
30+
* Entities (that are mapped to the database) and the GraphQL objects (that are mapped to the GraphQL schema)
31+
*/
32+
@Resource
33+
private Mapper mapper;
34+
35+
@Resource
36+
private Util util;
37+
38+
@Override
39+
public List<Board> boards(DataFetchingEnvironment dataFetchingEnvironment) {
40+
Iterable<BoardEntity> boards = boardRepository.findAll();
41+
return util.mapList(boards, BoardEntity.class, Board.class);
42+
}
43+
44+
@Override
45+
public Integer nbBoards(DataFetchingEnvironment dataFetchingEnvironment) {
46+
return (int) boardRepository.count();
47+
}
48+
49+
@Override
50+
public List<Topic> topics(DataFetchingEnvironment dataFetchingEnvironment, String boardName) {
51+
Iterable<TopicEntity> topics = topicRepository.findByBoardName(boardName);
52+
return util.mapList(topics, TopicEntity.class, Topic.class);
53+
}
54+
55+
@Override
56+
public List<Topic> findTopics(DataFetchingEnvironment dataFetchingEnvironment, String boardName,
57+
List<String> keyword) {
58+
Iterable<TopicEntity> topics = topicRepository.findByBoardNameAndKeywords(boardName, keyword);
59+
return util.mapList(topics, TopicEntity.class, Topic.class);
60+
}
61+
62+
}

0 commit comments

Comments
 (0)