Skip to content
This repository was archived by the owner on Dec 19, 2023. It is now read-only.

Commit c8f0a72

Browse files
feat(#5): add example project to demonstrate GraphQL Annotations support
1 parent e560e6f commit c8f0a72

File tree

24 files changed

+657
-0
lines changed

24 files changed

+657
-0
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
apply plugin: "org.springframework.boot"
2+
3+
dependencies {
4+
implementation(project(":graphql-spring-boot-starter"))
5+
implementation(project(":graphql-kickstart-spring-boot-starter-graphql-annotations"))
6+
implementation "io.reactivex.rxjava2:rxjava"
7+
runtimeOnly(project(":graphiql-spring-boot-starter"))
8+
runtimeOnly(project(":playground-spring-boot-starter"))
9+
runtimeOnly(project(":voyager-spring-boot-starter"))
10+
11+
implementation("org.springframework.boot:spring-boot-starter-web")
12+
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
13+
runtimeOnly("com.h2database:h2")
14+
15+
testImplementation "org.springframework.boot:spring-boot-starter-test"
16+
testImplementation(project(":graphql-spring-boot-starter-test"))
17+
}
18+
19+
jar.enabled = false
20+
uploadArchives.enabled = false
21+
bintrayUpload.enabled = false
22+
publishToMavenLocal.enabled = false
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package graphql.kickstart.spring.boot.graphql.annotations.example;
2+
3+
import org.springframework.boot.SpringApplication;
4+
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
6+
@SpringBootApplication
7+
public class GraphQLAnnotationsSampleApplication {
8+
9+
public static void main(final String[] args) {
10+
SpringApplication.run(GraphQLAnnotationsSampleApplication.class, args);
11+
}
12+
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package graphql.kickstart.spring.boot.graphql.annotations.example.model.directives;
2+
3+
import graphql.annotations.annotationTypes.GraphQLDescription;
4+
import graphql.annotations.annotationTypes.GraphQLName;
5+
import graphql.annotations.annotationTypes.directives.definition.DirectiveLocations;
6+
import graphql.annotations.annotationTypes.directives.definition.GraphQLDirectiveDefinition;
7+
import graphql.introspection.Introspection;
8+
9+
import java.lang.annotation.Retention;
10+
import java.lang.annotation.RetentionPolicy;
11+
12+
@GraphQLName("upperCase")
13+
@GraphQLDescription("This directive makes a string uppercase")
14+
@GraphQLDirectiveDefinition(wiring = UpperCaseDirectiveWiring.class)
15+
@DirectiveLocations({Introspection.DirectiveLocation.FIELD_DEFINITION})
16+
@Retention(RetentionPolicy.RUNTIME)
17+
public @interface UpperCaseDirective {
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package graphql.kickstart.spring.boot.graphql.annotations.example.model.directives;
2+
3+
import graphql.annotations.directives.AnnotationsDirectiveWiring;
4+
import graphql.annotations.directives.AnnotationsWiringEnvironment;
5+
import graphql.annotations.processor.util.CodeRegistryUtil;
6+
import graphql.schema.GraphQLFieldDefinition;
7+
import lombok.NoArgsConstructor;
8+
9+
@NoArgsConstructor
10+
public class UpperCaseDirectiveWiring implements AnnotationsDirectiveWiring {
11+
12+
@Override
13+
public GraphQLFieldDefinition onField(final AnnotationsWiringEnvironment environment) {
14+
final GraphQLFieldDefinition field = (GraphQLFieldDefinition) environment.getElement();
15+
CodeRegistryUtil.wrapDataFetcher(field, environment, (((dataFetchingEnvironment, value) -> {
16+
if (value instanceof String) {
17+
return ((String) value).toUpperCase();
18+
}
19+
return value;
20+
})));
21+
return field;
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package graphql.kickstart.spring.boot.graphql.annotations.example.model.extension;
2+
3+
import graphql.annotations.annotationTypes.GraphQLField;
4+
import graphql.annotations.annotationTypes.GraphQLNonNull;
5+
import graphql.annotations.annotationTypes.GraphQLTypeExtension;
6+
import graphql.kickstart.spring.boot.graphql.annotations.example.model.type.Person;
7+
import lombok.Getter;
8+
import lombok.RequiredArgsConstructor;
9+
10+
@Getter
11+
@RequiredArgsConstructor
12+
@GraphQLTypeExtension(Person.class)
13+
public class PersonExtension {
14+
15+
private final Person person;
16+
17+
@GraphQLField
18+
@GraphQLNonNull
19+
public String fullName() {
20+
return String.format("%s, %s", person.getLastName(), person.getFirstName());
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package graphql.kickstart.spring.boot.graphql.annotations.example.model.input;
2+
3+
import graphql.annotations.annotationTypes.GraphQLField;
4+
import graphql.annotations.annotationTypes.GraphQLNonNull;
5+
import lombok.AllArgsConstructor;
6+
import lombok.Builder;
7+
import lombok.Data;
8+
import lombok.NoArgsConstructor;
9+
10+
import java.time.LocalDate;
11+
12+
@Data
13+
@Builder
14+
@NoArgsConstructor
15+
@AllArgsConstructor
16+
public class CreatePerson {
17+
18+
@GraphQLField
19+
@GraphQLNonNull
20+
private String firstName;
21+
22+
@GraphQLField
23+
@GraphQLNonNull
24+
private String lastName;
25+
26+
@GraphQLField
27+
private LocalDate dateOfBirth;
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package graphql.kickstart.spring.boot.graphql.annotations.example.model.scalar;
2+
3+
import graphql.language.StringValue;
4+
import graphql.schema.Coercing;
5+
import graphql.schema.CoercingParseLiteralException;
6+
import graphql.schema.CoercingParseValueException;
7+
import graphql.schema.CoercingSerializeException;
8+
import graphql.schema.GraphQLScalarType;
9+
import lombok.NoArgsConstructor;
10+
import org.springframework.context.annotation.Bean;
11+
import org.springframework.context.annotation.Configuration;
12+
13+
import java.time.LocalDate;
14+
import java.time.format.DateTimeParseException;
15+
16+
@Configuration
17+
@NoArgsConstructor
18+
public class LocalDateScalarConfiguration {
19+
20+
@Bean
21+
public GraphQLScalarType localDateScalar() {
22+
return GraphQLScalarType.newScalar()
23+
.name("Date")
24+
.description("LocalDate as GraphQL scalar.")
25+
.coercing(new Coercing<LocalDate, String>() {
26+
@Override
27+
public String serialize(Object dataFetcherResult) throws CoercingSerializeException {
28+
if (!(dataFetcherResult instanceof LocalDate)) {
29+
throw new CoercingSerializeException("LocalDate expected.");
30+
}
31+
return String.valueOf(dataFetcherResult);
32+
}
33+
34+
@Override
35+
public LocalDate parseValue(Object input) throws CoercingParseValueException {
36+
try {
37+
return LocalDate.parse(String.valueOf(input));
38+
} catch (DateTimeParseException e) {
39+
throw new CoercingParseValueException(e);
40+
}
41+
}
42+
43+
@Override
44+
public LocalDate parseLiteral(Object input) throws CoercingParseLiteralException {
45+
try {
46+
if (!(input instanceof StringValue)) {
47+
throw new CoercingParseLiteralException("String value expected.");
48+
}
49+
return LocalDate.parse(((StringValue) input).getValue());
50+
} catch (DateTimeParseException e) {
51+
throw new CoercingParseLiteralException("Failed to parse date literal", e);
52+
}
53+
}
54+
})
55+
.build();
56+
}
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package graphql.kickstart.spring.boot.graphql.annotations.example.model.type;
2+
3+
import graphql.annotations.annotationTypes.GraphQLField;
4+
import graphql.annotations.annotationTypes.GraphQLID;
5+
import graphql.annotations.annotationTypes.GraphQLNonNull;
6+
import graphql.kickstart.spring.boot.graphql.annotations.example.model.directives.UpperCaseDirective;
7+
import lombok.AllArgsConstructor;
8+
import lombok.Builder;
9+
import lombok.Data;
10+
import lombok.NoArgsConstructor;
11+
12+
import javax.persistence.Column;
13+
import javax.persistence.Entity;
14+
import javax.persistence.Id;
15+
import javax.persistence.Transient;
16+
import java.time.LocalDate;
17+
18+
@Data
19+
@Builder
20+
@NoArgsConstructor
21+
@AllArgsConstructor
22+
@Entity
23+
public class Person {
24+
25+
@Id
26+
@GraphQLID
27+
@GraphQLField
28+
@GraphQLNonNull
29+
@UpperCaseDirective
30+
private String id;
31+
32+
@Column(nullable = false)
33+
@GraphQLField
34+
@GraphQLNonNull
35+
private String firstName;
36+
37+
@Column(nullable = false)
38+
@GraphQLField
39+
@GraphQLNonNull
40+
private String lastName;
41+
42+
@GraphQLField
43+
private LocalDate dateOfBirth;
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package graphql.kickstart.spring.boot.graphql.annotations.example.repository;
2+
3+
import graphql.kickstart.spring.boot.graphql.annotations.example.model.type.Person;
4+
import org.springframework.data.jpa.repository.JpaRepository;
5+
6+
public interface PersonRepository extends JpaRepository<Person, String> {
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package graphql.kickstart.spring.boot.graphql.annotations.example.resolvers;
2+
3+
import graphql.annotations.annotationTypes.GraphQLDescription;
4+
import graphql.annotations.annotationTypes.GraphQLField;
5+
import graphql.annotations.annotationTypes.GraphQLNonNull;
6+
import graphql.kickstart.spring.boot.graphql.annotations.example.model.input.CreatePerson;
7+
import graphql.kickstart.spring.boot.graphql.annotations.example.model.type.Person;
8+
import graphql.kickstart.spring.boot.graphql.annotations.example.repository.PersonRepository;
9+
import graphql.kickstart.tools.GraphQLMutationResolver;
10+
import lombok.NoArgsConstructor;
11+
import org.springframework.beans.BeansException;
12+
import org.springframework.context.ApplicationContext;
13+
import org.springframework.context.ApplicationContextAware;
14+
import org.springframework.stereotype.Service;
15+
16+
import java.util.UUID;
17+
18+
/**
19+
* Same restrictions / considerations apply as for the query resolver.
20+
* @see Queries
21+
*/
22+
@Service
23+
@NoArgsConstructor
24+
public class Mutations implements GraphQLMutationResolver, ApplicationContextAware {
25+
26+
private static PersonRepository personRepository;
27+
28+
@GraphQLField
29+
@GraphQLNonNull
30+
@GraphQLDescription("Creates a new person.")
31+
public static Person createPerson(final @GraphQLNonNull CreatePerson createPerson) {
32+
final Person newPerson = Person.builder()
33+
.firstName(createPerson.getFirstName())
34+
.lastName(createPerson.getLastName())
35+
.dateOfBirth(createPerson.getDateOfBirth())
36+
.id(String.valueOf(UUID.randomUUID()))
37+
.build();
38+
return personRepository.save(newPerson);
39+
}
40+
41+
@Override
42+
public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
43+
personRepository = applicationContext.getBean(PersonRepository.class);
44+
}
45+
}

0 commit comments

Comments
 (0)