diff --git a/graphql-java-support/pom.xml b/graphql-java-support/pom.xml
index bdca94a2..dd12602a 100644
--- a/graphql-java-support/pom.xml
+++ b/graphql-java-support/pom.xml
@@ -26,11 +26,7 @@
org.junit.jupiter
- junit-jupiter-api
-
-
- org.junit.jupiter
- junit-jupiter-engine
+ junit-jupiter
org.slf4j
diff --git a/pom.xml b/pom.xml
index fefbc82c..f28d516e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -61,10 +61,10 @@
${java.version}
2.7
16.1
- 5.10.0
+ 11.0.0
1.8
17.0.0
- 5.4.2
+ 5.7.1
1.6
3.1.2
3.1.1
@@ -72,7 +72,7 @@
2.22.1
1.6.8
1.7.30
- 2.1.6.RELEASE
+ 2.3.6.RELEASE
@@ -80,19 +80,25 @@
com.graphql-java-kickstart
graphql-spring-boot-starter
- ${graphql-spring-boot.version}
+ ${graphql-java-kickstart.version}
com.graphql-java-kickstart
graphiql-spring-boot-starter
- ${graphql-spring-boot.version}
+ ${graphql-java-kickstart.version}
+ runtime
com.graphql-java-kickstart
graphql-spring-boot-starter-test
- ${graphql-spring-boot.version}
+ ${graphql-java-kickstart.version}
test
+
+ com.graphql-java-kickstart
+ graphql-java-tools
+ ${graphql-java-kickstart.version}
+
com.graphql-java
graphql-java
@@ -106,13 +112,7 @@
org.junit.jupiter
- junit-jupiter-api
- ${junit.version}
- test
-
-
- org.junit.jupiter
- junit-jupiter-engine
+ junit-jupiter
${junit.version}
test
diff --git a/spring-example/README.md b/spring-example/README.md
index 7d71e38f..33df17af 100644
--- a/spring-example/README.md
+++ b/spring-example/README.md
@@ -1,11 +1,16 @@
+This Spring Boot application contains examples for both a microservice using standard `graphql-java` and a microservice using `graphql-java-tools`; their code is separated under different subpackages and Spring profiles.
-To run the example, cd to the root of this project, then...
+To run the standard `graphql-java` example, `cd` to the root of this project, then...
```
## compile and install project including example and dependencies
mvn install -Dgpg.skip
## start local webserver on 9000
mvn -pl spring-example spring-boot:run
```
+To run the `graphql-java-tools` example, for the last step instead run:
+```
+mvn -pl spring-example spring-boot:run -Dspring-boot.run.profiles=graphql-java-tools
+```
Now you can query your local graph:
```
## e.g.
diff --git a/spring-example/pom.xml b/spring-example/pom.xml
index ea438a69..51ca159d 100644
--- a/spring-example/pom.xml
+++ b/spring-example/pom.xml
@@ -23,7 +23,7 @@
org.junit.jupiter
- junit-jupiter-api
+ junit-jupiter
org.springframework.boot
@@ -49,6 +49,10 @@
com.graphql-java-kickstart
graphql-spring-boot-starter-test
+
+ com.graphql-java-kickstart
+ graphql-java-tools
+
diff --git a/spring-example/src/main/java/com/apollographql/federation/springexample/App.java b/spring-example/src/main/java/com/apollographql/federation/springexample/App.java
index 0dcc4b29..0896b2c7 100644
--- a/spring-example/src/main/java/com/apollographql/federation/springexample/App.java
+++ b/spring-example/src/main/java/com/apollographql/federation/springexample/App.java
@@ -1,19 +1,11 @@
package com.apollographql.federation.springexample;
-import com.apollographql.federation.graphqljava.tracing.FederatedTracingInstrumentation;
-import graphql.execution.instrumentation.Instrumentation;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
-
- @Bean
- public Instrumentation addFederatedTracing() {
- return new FederatedTracingInstrumentation(new FederatedTracingInstrumentation.Options(true));
- }
}
diff --git a/spring-example/src/main/java/com/apollographql/federation/springexample/InventorySchemaProvider.java b/spring-example/src/main/java/com/apollographql/federation/springexample/InventorySchemaProvider.java
deleted file mode 100644
index d2c4665b..00000000
--- a/spring-example/src/main/java/com/apollographql/federation/springexample/InventorySchemaProvider.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.apollographql.federation.springexample;
-
-import com.apollographql.federation.graphqljava.Federation;
-import com.apollographql.federation.graphqljava._Entity;
-import graphql.servlet.config.DefaultGraphQLSchemaProvider;
-import graphql.servlet.config.GraphQLSchemaProvider;
-import org.jetbrains.annotations.NotNull;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.core.io.Resource;
-import org.springframework.stereotype.Component;
-
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-@Component
-public class InventorySchemaProvider extends DefaultGraphQLSchemaProvider implements GraphQLSchemaProvider {
- public InventorySchemaProvider(@Value("classpath:schemas/inventory.graphql") Resource sdl) throws IOException {
- super(Federation.transform(sdl.getFile())
- .fetchEntities(env -> env.>>getArgument(_Entity.argumentName)
- .stream()
- .map(values -> {
- if ("Product".equals(values.get("__typename"))) {
- final Object upc = values.get("upc");
- if (upc instanceof String) {
- return lookupProduct((String) upc);
- }
- }
- return null;
- })
- .collect(Collectors.toList()))
- .resolveEntityType(env -> {
- final Object src = env.getObject();
- if (src instanceof Product) {
- return env.getSchema().getObjectType("Product");
- }
- return null;
- })
- .build());
- }
-
- @NotNull
- private static Product lookupProduct(@NotNull String upc) {
- try {
- // Why not?
- int quantity = Math.floorMod(
- new BigInteger(1,
- MessageDigest.getInstance("SHA1").digest(upc.getBytes())
- ).intValue(),
- 10_000);
-
- return new Product(upc, quantity);
- } catch (NoSuchAlgorithmException e) {
- throw new RuntimeException(e);
- }
- }
-}
diff --git a/spring-example/src/main/java/com/apollographql/federation/springexample/graphqljava/AppConfiguration.java b/spring-example/src/main/java/com/apollographql/federation/springexample/graphqljava/AppConfiguration.java
new file mode 100644
index 00000000..786855b6
--- /dev/null
+++ b/spring-example/src/main/java/com/apollographql/federation/springexample/graphqljava/AppConfiguration.java
@@ -0,0 +1,47 @@
+package com.apollographql.federation.springexample.graphqljava;
+
+import com.apollographql.federation.graphqljava.Federation;
+import com.apollographql.federation.graphqljava._Entity;
+import com.apollographql.federation.graphqljava.tracing.FederatedTracingInstrumentation;
+import graphql.schema.GraphQLSchema;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.core.io.Resource;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Configuration
+@Profile("graphql-java")
+public class AppConfiguration {
+ @Bean
+ public GraphQLSchema graphQLSchema(@Value("classpath:schemas/graphql-java/inventory.graphql") Resource sdl) throws IOException {
+ return Federation.transform(sdl.getFile())
+ .fetchEntities(env -> env.>>getArgument(_Entity.argumentName)
+ .stream()
+ .map(reference -> {
+ if ("Product".equals(reference.get("__typename"))) {
+ return Product.resolveReference(reference);
+ }
+ return null;
+ })
+ .collect(Collectors.toList()))
+ .resolveEntityType(env -> {
+ final Object src = env.getObject();
+ if (src instanceof Product) {
+ return env.getSchema().getObjectType("Product");
+ }
+ return null;
+ })
+ .build();
+ }
+
+ @Bean
+ public FederatedTracingInstrumentation federatedTracingInstrumentation() {
+ return new FederatedTracingInstrumentation(new FederatedTracingInstrumentation.Options(true));
+ }
+}
diff --git a/spring-example/src/main/java/com/apollographql/federation/springexample/graphqljava/Product.java b/spring-example/src/main/java/com/apollographql/federation/springexample/graphqljava/Product.java
new file mode 100644
index 00000000..24dca16a
--- /dev/null
+++ b/spring-example/src/main/java/com/apollographql/federation/springexample/graphqljava/Product.java
@@ -0,0 +1,49 @@
+package com.apollographql.federation.springexample.graphqljava;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Map;
+
+public class Product {
+ private final String upc;
+ private final int quantity;
+
+ public Product(String upc, int quantity) {
+ this.upc = upc;
+ this.quantity = quantity;
+ }
+
+ public String getUpc() {
+ return upc;
+ }
+
+ public int getQuantity() {
+ return quantity;
+ }
+
+ public boolean isInStock() {
+ return this.quantity > 0;
+ }
+
+ public static Product resolveReference(@NotNull Map reference) {
+ if (!(reference.get("upc") instanceof String)) {
+ return null;
+ }
+ final String upc = (String) reference.get("upc");
+ try {
+ // Why not?
+ int quantity = Math.floorMod(
+ new BigInteger(1,
+ MessageDigest.getInstance("SHA1").digest(upc.getBytes())
+ ).intValue(),
+ 10_000);
+
+ return new Product(upc, quantity);
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/spring-example/src/main/java/com/apollographql/federation/springexample/graphqljavatools/AppConfiguration.java b/spring-example/src/main/java/com/apollographql/federation/springexample/graphqljavatools/AppConfiguration.java
new file mode 100644
index 00000000..2fca7c14
--- /dev/null
+++ b/spring-example/src/main/java/com/apollographql/federation/springexample/graphqljavatools/AppConfiguration.java
@@ -0,0 +1,44 @@
+package com.apollographql.federation.springexample.graphqljavatools;
+
+import com.apollographql.federation.graphqljava.SchemaTransformer;
+import com.apollographql.federation.graphqljava._Entity;
+import com.apollographql.federation.graphqljava.tracing.FederatedTracingInstrumentation;
+import graphql.schema.GraphQLSchema;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Configuration
+@Profile("graphql-java-tools")
+public class AppConfiguration {
+ @Bean
+ public GraphQLSchema graphQLSchema(SchemaTransformer schemaTransformer) {
+ return schemaTransformer
+ .fetchEntities(env -> env.>>getArgument(_Entity.argumentName)
+ .stream()
+ .map(reference -> {
+ if ("Product".equals(reference.get("__typename"))) {
+ return ProductReferenceResolver.resolveReference(reference);
+ }
+ return null;
+ })
+ .collect(Collectors.toList()))
+ .resolveEntityType(env -> {
+ final Object src = env.getObject();
+ if (src instanceof Product) {
+ return env.getSchema().getObjectType("Product");
+ }
+ return null;
+ })
+ .build();
+ }
+
+ @Bean
+ public FederatedTracingInstrumentation federatedTracingInstrumentation() {
+ return new FederatedTracingInstrumentation(new FederatedTracingInstrumentation.Options(true));
+ }
+}
diff --git a/spring-example/src/main/java/com/apollographql/federation/springexample/graphqljavatools/GraphQLJavaToolsConfiguration.java b/spring-example/src/main/java/com/apollographql/federation/springexample/graphqljavatools/GraphQLJavaToolsConfiguration.java
new file mode 100644
index 00000000..3893d8af
--- /dev/null
+++ b/spring-example/src/main/java/com/apollographql/federation/springexample/graphqljavatools/GraphQLJavaToolsConfiguration.java
@@ -0,0 +1,79 @@
+package com.apollographql.federation.springexample.graphqljavatools;
+
+import com.apollographql.federation.graphqljava.Federation;
+import com.apollographql.federation.graphqljava.SchemaTransformer;
+import graphql.Scalars;
+import graphql.kickstart.tools.SchemaObjects;
+import graphql.kickstart.tools.SchemaParser;
+import graphql.kickstart.tools.SchemaParserDictionary;
+import graphql.kickstart.tools.SchemaParserOptions;
+import graphql.schema.GraphQLFieldDefinition;
+import graphql.schema.GraphQLObjectType;
+import graphql.schema.GraphQLSchema;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * Some tips for running with graphql-java-tools:
+ * 1. You may find that graphql-java-tools removes types that are only used by the federation
+ * _entities field. This is because graphql-java-tools performs these optimizations before
+ * federation-graphql-java-support can alter the schema to include the _entities field. The
+ * simplest workaround here is to both (1) add the type to the {@link SchemaParserDictionary}
+ * bean and to (2) set the {@link SchemaParserOptions.Builder} bean to have includeUnusedTypes
+ * as true. However, the latter can't be done via properties.xml/yml since the getters/setters
+ * aren't named according to the JavaBeans API specification (i.e. getFoo()/setFoo()). You can
+ * work around this by providing the whole bean via code, or using a {@link BeanPostProcessor}
+ * as shown below to customize the auto-configuration bean.
+ * 2. If you have an empty query type, you don't need to add a dummy field to your
+ * {@link graphql.kickstart.tools.GraphQLQueryResolver} or to your schema string. However, you
+ * do need to (1) declare an empty {@link graphql.kickstart.tools.GraphQLQueryResolver}, (2)
+ * declare an empty "type Query" in your schema string, and (3) setup {@link SchemaTransformer}
+ * as shown below. We could potentially modify the federation-graphql-java-support API to accept
+ * {@link GraphQLSchema.Builder}s, but unfortunately those builders have no public getters, so
+ * we wouldn't be able to copy their data.
+ */
+@Configuration
+public class GraphQLJavaToolsConfiguration {
+ @Bean
+ public SchemaParserDictionary schemaParserDictionary() {
+ return new SchemaParserDictionary().add("Product", Product.class);
+ }
+
+ @Bean
+ public BeanPostProcessor schemaParserOptionsBuilderPostProcessor() {
+ return new BeanPostProcessor() {
+ @Override
+ public Object postProcessAfterInitialization(@NotNull Object bean, @NotNull String beanName) throws BeansException {
+ return bean instanceof SchemaParserOptions.Builder
+ ? ((SchemaParserOptions.Builder) bean).includeUnusedTypes(true)
+ : bean;
+ }
+ };
+ }
+
+ @Bean
+ public SchemaTransformer schemaTransformer(SchemaParser schemaParser) {
+ final SchemaObjects schemaObjects = schemaParser.parseSchemaObjects();
+ final boolean queryTypeIsEmpty = schemaObjects.getQuery().getFieldDefinitions().isEmpty();
+ final GraphQLObjectType newQuery = queryTypeIsEmpty
+ ? schemaObjects.getQuery().transform(graphQLObjectTypeBuilder ->
+ graphQLObjectTypeBuilder.field(GraphQLFieldDefinition.newFieldDefinition()
+ .name("_dummy")
+ .type(Scalars.GraphQLString)
+ .build()
+ )
+ )
+ : schemaObjects.getQuery();
+ final GraphQLSchema graphQLSchema = GraphQLSchema.newSchema()
+ .query(newQuery)
+ .mutation(schemaObjects.getMutation())
+ .subscription(schemaObjects.getSubscription())
+ .additionalTypes(schemaObjects.getDictionary())
+ .codeRegistry(schemaObjects.getCodeRegistryBuilder().build())
+ .build();
+ return Federation.transform(graphQLSchema, queryTypeIsEmpty);
+ }
+}
diff --git a/spring-example/src/main/java/com/apollographql/federation/springexample/Product.java b/spring-example/src/main/java/com/apollographql/federation/springexample/graphqljavatools/Product.java
similarity index 71%
rename from spring-example/src/main/java/com/apollographql/federation/springexample/Product.java
rename to spring-example/src/main/java/com/apollographql/federation/springexample/graphqljavatools/Product.java
index 7cb6b65f..8b9f2c32 100644
--- a/spring-example/src/main/java/com/apollographql/federation/springexample/Product.java
+++ b/spring-example/src/main/java/com/apollographql/federation/springexample/graphqljavatools/Product.java
@@ -1,4 +1,4 @@
-package com.apollographql.federation.springexample;
+package com.apollographql.federation.springexample.graphqljavatools;
public class Product {
private final String upc;
@@ -16,8 +16,4 @@ public String getUpc() {
public int getQuantity() {
return quantity;
}
-
- public boolean isInStock() {
- return this.quantity > 0;
- }
}
diff --git a/spring-example/src/main/java/com/apollographql/federation/springexample/graphqljavatools/ProductReferenceResolver.java b/spring-example/src/main/java/com/apollographql/federation/springexample/graphqljavatools/ProductReferenceResolver.java
new file mode 100644
index 00000000..0c44e6a0
--- /dev/null
+++ b/spring-example/src/main/java/com/apollographql/federation/springexample/graphqljavatools/ProductReferenceResolver.java
@@ -0,0 +1,29 @@
+package com.apollographql.federation.springexample.graphqljavatools;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Map;
+
+public class ProductReferenceResolver {
+ public static Product resolveReference(@NotNull Map reference) {
+ if (!(reference.get("upc") instanceof String)) {
+ return null;
+ }
+ final String upc = (String) reference.get("upc");
+ try {
+ // Why not?
+ int quantity = Math.floorMod(
+ new BigInteger(1,
+ MessageDigest.getInstance("SHA1").digest(upc.getBytes())
+ ).intValue(),
+ 10_000);
+
+ return new Product(upc, quantity);
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/spring-example/src/main/java/com/apollographql/federation/springexample/graphqljavatools/ProductResolver.java b/spring-example/src/main/java/com/apollographql/federation/springexample/graphqljavatools/ProductResolver.java
new file mode 100644
index 00000000..50200517
--- /dev/null
+++ b/spring-example/src/main/java/com/apollographql/federation/springexample/graphqljavatools/ProductResolver.java
@@ -0,0 +1,11 @@
+package com.apollographql.federation.springexample.graphqljavatools;
+
+import graphql.kickstart.tools.GraphQLResolver;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ProductResolver implements GraphQLResolver {
+ public boolean isInStock(Product product) {
+ return product.getQuantity() > 0;
+ }
+}
diff --git a/spring-example/src/main/java/com/apollographql/federation/springexample/graphqljavatools/QueryResolver.java b/spring-example/src/main/java/com/apollographql/federation/springexample/graphqljavatools/QueryResolver.java
new file mode 100644
index 00000000..a991e9bf
--- /dev/null
+++ b/spring-example/src/main/java/com/apollographql/federation/springexample/graphqljavatools/QueryResolver.java
@@ -0,0 +1,8 @@
+package com.apollographql.federation.springexample.graphqljavatools;
+
+import graphql.kickstart.tools.GraphQLQueryResolver;
+import org.springframework.stereotype.Component;
+
+@Component
+public class QueryResolver implements GraphQLQueryResolver {
+}
diff --git a/spring-example/src/main/resources/application.yml b/spring-example/src/main/resources/application.yml
index fe41530c..4a54964e 100644
--- a/spring-example/src/main/resources/application.yml
+++ b/spring-example/src/main/resources/application.yml
@@ -1,5 +1,7 @@
spring:
application:
name: federation-jvm-spring-example
+ profiles:
+ default: graphql-java
server:
port: 9000
diff --git a/spring-example/src/main/resources/schemas/graphql-java-tools/inventory.graphqls b/spring-example/src/main/resources/schemas/graphql-java-tools/inventory.graphqls
new file mode 100644
index 00000000..6e6e616c
--- /dev/null
+++ b/spring-example/src/main/resources/schemas/graphql-java-tools/inventory.graphqls
@@ -0,0 +1,7 @@
+type Query
+
+type Product @key(fields: "upc") @extends {
+ upc: String! @external
+ inStock: Boolean
+ quantity: Int
+}
diff --git a/spring-example/src/main/resources/schemas/inventory.graphql b/spring-example/src/main/resources/schemas/graphql-java/inventory.graphql
similarity index 100%
rename from spring-example/src/main/resources/schemas/inventory.graphql
rename to spring-example/src/main/resources/schemas/graphql-java/inventory.graphql
diff --git a/spring-example/src/test/java/com/apollographql/federation/springexample/AppTest.java b/spring-example/src/test/java/com/apollographql/federation/springexample/BaseAppTest.java
similarity index 59%
rename from spring-example/src/test/java/com/apollographql/federation/springexample/AppTest.java
rename to spring-example/src/test/java/com/apollographql/federation/springexample/BaseAppTest.java
index 3453a226..94432e69 100644
--- a/spring-example/src/test/java/com/apollographql/federation/springexample/AppTest.java
+++ b/spring-example/src/test/java/com/apollographql/federation/springexample/BaseAppTest.java
@@ -1,12 +1,7 @@
package com.apollographql.federation.springexample;
import com.graphql.spring.boot.test.GraphQLResponse;
-import com.graphql.spring.boot.test.GraphQLTest;
import com.graphql.spring.boot.test.GraphQLTestTemplate;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.test.context.junit4.SpringRunner;
import java.io.IOException;
@@ -14,18 +9,15 @@
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
-@RunWith(SpringRunner.class)
-@GraphQLTest
-public class AppTest {
- @Autowired
- private GraphQLTestTemplate graphqlTestTemplate;
-
- @Test
- public void lookupPlanckProduct() throws IOException {
+public class BaseAppTest {
+ public void lookupPlanckProduct(GraphQLTestTemplate graphqlTestTemplate) throws IOException {
final GraphQLResponse response = graphqlTestTemplate.postForResource("queries/LookupPlanckProduct.graphql");
assertNotNull(response, "response should not have been null");
- assertTrue(response.isOk(), "response should have been OK");
+ assertTrue(response.isOk(), "response should have been HTTP 200 OK");
+ response.assertThatNoErrorsArePresent();
final int quantity = response.get("$.data._entities[0].quantity", Integer.class);
assertEquals(8658, quantity, "Inventory contains 8658 Plancks");
+ final String federatedTrace = response.get("$.extensions.ftv1", String.class);
+ assertNotNull(federatedTrace, "response should not have had null federated trace");
}
}
diff --git a/spring-example/src/test/java/com/apollographql/federation/springexample/GraphQLJavaAppTest.java b/spring-example/src/test/java/com/apollographql/federation/springexample/GraphQLJavaAppTest.java
new file mode 100644
index 00000000..2fb7ea69
--- /dev/null
+++ b/spring-example/src/test/java/com/apollographql/federation/springexample/GraphQLJavaAppTest.java
@@ -0,0 +1,24 @@
+package com.apollographql.federation.springexample;
+
+import com.graphql.spring.boot.test.GraphQLTest;
+import com.graphql.spring.boot.test.GraphQLTestTemplate;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Import;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.io.IOException;
+
+@RunWith(SpringRunner.class)
+@GraphQLTest(profiles = "graphql-java")
+@Import(App.class)
+public class GraphQLJavaAppTest extends BaseAppTest {
+ @Autowired
+ private GraphQLTestTemplate graphqlTestTemplate;
+
+ @Test
+ public void lookupPlanckProduct() throws IOException {
+ lookupPlanckProduct(graphqlTestTemplate);
+ }
+}
diff --git a/spring-example/src/test/java/com/apollographql/federation/springexample/GraphQLJavaToolsAppTest.java b/spring-example/src/test/java/com/apollographql/federation/springexample/GraphQLJavaToolsAppTest.java
new file mode 100644
index 00000000..82879f07
--- /dev/null
+++ b/spring-example/src/test/java/com/apollographql/federation/springexample/GraphQLJavaToolsAppTest.java
@@ -0,0 +1,24 @@
+package com.apollographql.federation.springexample;
+
+import com.graphql.spring.boot.test.GraphQLTest;
+import com.graphql.spring.boot.test.GraphQLTestTemplate;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Import;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.io.IOException;
+
+@RunWith(SpringRunner.class)
+@GraphQLTest(profiles = "graphql-java-tools")
+@Import(App.class)
+public class GraphQLJavaToolsAppTest extends BaseAppTest {
+ @Autowired
+ private GraphQLTestTemplate graphqlTestTemplate;
+
+ @Test
+ public void lookupPlanckProduct() throws IOException {
+ lookupPlanckProduct(graphqlTestTemplate);
+ }
+}
diff --git a/spring-example/src/test/resources/logback.xml b/spring-example/src/test/resources/logback.xml
new file mode 100644
index 00000000..215403c6
--- /dev/null
+++ b/spring-example/src/test/resources/logback.xml
@@ -0,0 +1,5 @@
+
+
+
+
+