diff --git a/README.md b/README.md index ab5009c..cb4de0a 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,30 @@ GraphQLResponseEntity responseEntity = graphQLTemplate.query(reques ### Annotations to configure fields +#### `@GraphQLOperation(name="name", method=GraphQLTemplate.GraphQLMethod, property=@GraphQLProperty, varibales={@GraphQLVariable})` +> Used above classes for more complex queries with variables.
name (required): GraphQL operation name
method (optional): GraphQL operation method (Query, Mutation) defaults to Query.
property (optional): Define property for the operation. Overrides @GraphQLProperty. Defaults to the class name.
variables (optional): Variables to use in the operation. + +*example:* +```java + ... + @GraphQLOperation(name="MyUserQuery", + property = @GraphQLProperty(name = "User", arguments = { + @GraphQLArgument(name = "name", variable="name") + }), + variables={@GraphQLVariable(name = "name", scalar = "String")}) + class User { + ... + } +``` + +*result:* +``` +query MyUserQuery($name:String){ + UserQuery(name: $name) { + ... + } +``` + #### `@GraphQLArgument(name="name", value="defaultVal", type="String")` > Used above property fields
name (required): GraphQL argument name
value (optional): default value to set the argument to
type (optional): how to parse the optional value. Accepts an enum of "String", "Boolean", "Integer", or "Float" - defaults to be parsed as a string.
You can specify fields arguments directly inline using this. This is good for static field arguments such as result display settings, for instance the format of a date or the locale of a message. @@ -150,8 +174,7 @@ query { ``` #### `@GraphQLVariable(name="name", scalar="Float!")` -> Used above property fields
name (required): GraphQL variable name
type (required): GraphQL scalar type. Including optional and required parsing (!)
This is good for sharing the same variables across multiple input parameters in a query. - +> (deprecated) Used above property fields
name (required): GraphQL variable name
type (required): GraphQL scalar type. Including optional and required parsing (!)
This is good for sharing the same variables across multiple input parameters in a query. *example:* ```java ... @@ -168,7 +191,49 @@ query($isPublic: Boolean) { ... ``` -#### `@GraphQLVariables({@GraphQLVariable})` +> (Preferred) Use `@GraphQLArgument` in models to define the placeholder, then Use w/ `@GraphQLOperation` when specifying variables used in the operation. Finally link the argument w/ the variable when building the request. + ```java + @GraphQLArguments({ + @GraphQLArgument(name="isPublic", value="true", type="Boolean"), + @GraphQLArgument(name="name") + }) + class User { + ... + }; + + @GraphQLOperation(name = "FindUserByName", variables = { + @GraphQLVariable(name = "nameFilter", scalar = "String") + }) + class UserByName extends User { + } + + class UserRepo { + public User findUserByName(String name) { + GraphQLTemplate graphQLTemplate = new GraphQLTemplate(); + + GraphQLRequestEntity requestEntity = GraphQLRequestEntity.Builder() + .url("http://graphql.example.com/graphql"); + .variables(new Variable("nameFilter", name)) + .arguments(new Arguments("UserByName", + new Argument("name", null, "nameFilter"))) + .request(UserByName.class) + .build(); + GraphQLResponseEntity responseEntity = graphQLTemplate.query(requestEntity, UserByName.class); + } + } + ``` + + *result:* + ``` + query FindUserByName($nameFilter: String) { + UserByName(name: $nameFilter) { + ... + } + } + ``` + + +#### `@GraphQLVariables({@GraphQLVariable})` (deprecated) > Used above property fields
Annotation for allowing mutliple variables for a given field. *example:* diff --git a/nodes/src/main/java/io/aexp/nodes/graphql/Argument.java b/nodes/src/main/java/io/aexp/nodes/graphql/Argument.java index f7f7ab2..12cb9b8 100644 --- a/nodes/src/main/java/io/aexp/nodes/graphql/Argument.java +++ b/nodes/src/main/java/io/aexp/nodes/graphql/Argument.java @@ -14,10 +14,19 @@ package io.aexp.nodes.graphql; public class Argument extends Parameter { + private String variable; public Argument(String key, T value) { super(key, value); } + public String getVariable() { + return variable; + } + + public void setVariable(String variable) { + this.variable = variable; + } + @Override public String toString() { return super.toString(this.getClass().getSimpleName()); diff --git a/nodes/src/main/java/io/aexp/nodes/graphql/GraphQLRequestEntity.java b/nodes/src/main/java/io/aexp/nodes/graphql/GraphQLRequestEntity.java index 25fe7ef..0d46242 100644 --- a/nodes/src/main/java/io/aexp/nodes/graphql/GraphQLRequestEntity.java +++ b/nodes/src/main/java/io/aexp/nodes/graphql/GraphQLRequestEntity.java @@ -25,12 +25,7 @@ import java.util.List; import java.util.Map; -import io.aexp.nodes.graphql.annotations.GraphQLArgument; -import io.aexp.nodes.graphql.annotations.GraphQLArguments; -import io.aexp.nodes.graphql.annotations.GraphQLIgnore; -import io.aexp.nodes.graphql.annotations.GraphQLProperty; -import io.aexp.nodes.graphql.annotations.GraphQLVariable; -import io.aexp.nodes.graphql.annotations.GraphQLVariables; +import io.aexp.nodes.graphql.annotations.*; import io.aexp.nodes.graphql.exceptions.GraphQLException; public final class GraphQLRequestEntity { @@ -42,9 +37,8 @@ public static RequestBuilder Builder() { private final URL url; private final Map headers; private final Map variables; - private final Property property = new Property(); private final List scalars; - private GraphQLTemplate.GraphQLMethod requestMethod = GraphQLTemplate.GraphQLMethod.QUERY; + private final Operation operation = new Operation(); private String request; GraphQLRequestEntity(RequestBuilder builder) { @@ -55,7 +49,7 @@ public static RequestBuilder Builder() { if (builder.request != null) { this.request = builder.request; } else { - setPropertiesFromClass(builder.clazz); + setOperationFromClass(builder.clazz); } if (builder.arguments != null) { for (Arguments arguments : builder.arguments) { @@ -76,7 +70,7 @@ public String getRequest() { if (this.request != null) { return this.request; } - return property.getMessage(null); + return operation.getMessage(); } public Map getVariables() { @@ -88,8 +82,7 @@ public List getScalars() { } void setRequestMethod(GraphQLTemplate.GraphQLMethod requestMethod) { - this.requestMethod = requestMethod; - property.setMethod(requestMethod); + operation.setMethod(requestMethod); } @Override @@ -102,6 +95,53 @@ public String toString() { // Utility + /** + * Builds the request tree from the provided class. + * + * @param clazz the class used to construct the request + */ + private void setOperationFromClass(Class clazz) { + Map propertyVariables = new HashMap(); + Map children = this.getChildren(clazz, propertyVariables); + + GraphQLProperty graphQLProperty = (GraphQLProperty) clazz.getAnnotation(GraphQLProperty.class); + GraphQLOperation graphQLOperation = (GraphQLOperation) clazz.getAnnotation(GraphQLOperation.class); + GraphQLProperty operationGraphQLProperty = null; + + if(graphQLOperation != null) { + operation.setName(graphQLOperation.name()); + operation.setMethod(graphQLOperation.method()); + + for(GraphQLVariable graphQLVariable : graphQLOperation.variables()) { + propertyVariables.put("$" + graphQLVariable.name(), graphQLVariable.scalar()); + } + + operationGraphQLProperty = graphQLOperation.property(); + if(operationGraphQLProperty != null){ + Property classProperty = annotationToProperty(operationGraphQLProperty); + // fix for RequestBuilderTest tests that expectation top level property has no resource name (alias) + // TODO - remove when RequestBuilderTests are fixed + classProperty.setResourceName(null); + classProperty.setChildren(children); + operation.getChildren().put(operationGraphQLProperty.name(), classProperty); + } + } + + if(operationGraphQLProperty == null && graphQLProperty != null) { + Property classProperty = annotationToProperty(graphQLProperty); + // fix for RequestBuilderTest tests that expectation top level property has no resource name (alias) + // TODO - remove when RequestBuilderTests are fixed + classProperty.setResourceName(null); + classProperty.setChildren(children); + operation.getChildren().put(graphQLProperty.name(), classProperty); + } else if(operationGraphQLProperty == null){ + operation.setChildren(children); + } + + operation.setVariables(propertyVariables); + operation.setChildren(Collections.unmodifiableMap(operation.getChildren())); + } + /** * Set arguments on a field in the request. * @@ -113,11 +153,28 @@ public String toString() { * @throws GraphQLException is thrown at runtime if the dotPath does not correlate to a field accepting arguments */ private void setArguments(String dotPath, List arguments) throws GraphQLException { - Property argProp = property; String[] path = dotPath.split("\\."); + Map children = operation.getChildren(); + Property argProp = null; + + if(path.length == 0) { + if(children.size() > 1) { + throw new GraphQLException("Operation contains more than one property, dot path must specify a top level property"); + } + + Map.Entry entry = children.entrySet().iterator().next(); + argProp = entry.getValue(); + } + + int childrenIndex = 0; for (String key: path) { - argProp = argProp.getChildren().get(key); + if(childrenIndex++ == 0) { + argProp = children.get(key); + } else if(argProp != null) { + argProp = argProp.getChildren().get(key); + } } + if (argProp == null) throw new GraphQLException("'" + dotPath + "' is an invalid property path"); List args = argProp.getArguments(); if (args == null) { @@ -129,6 +186,7 @@ private void setArguments(String dotPath, List arguments) throws Graph if (index == -1) throw new GraphQLException("Argument '" + argument + "' doesn't exist on path '" + dotPath + "'"); Argument propArg = args.get(index); propArg.setValue(argument.getValue()); + propArg.setVariable(argument.getVariable()); } } @@ -143,36 +201,6 @@ private Integer indexOfArg(List arguments, String key) { return -1; } - /** - * Builds the request tree from the provided class. - * - * @param clazz the class used to construct the request - */ - private void setPropertiesFromClass(Class clazz) { - Map propertyVariables = new HashMap(); - Map children = this.getChildren(clazz, propertyVariables); - GraphQLProperty graphQLProperty = (GraphQLProperty) clazz.getAnnotation(GraphQLProperty.class); - if (graphQLProperty != null) { - Property resourceProperty = new Property(); - List arguments = null; - String resourceName = graphQLProperty.name(); - if (graphQLProperty.arguments().length > 0) { - arguments = new ArrayList(); - for (GraphQLArgument graphQLArgument : graphQLProperty.arguments()) { - arguments = setArgument(arguments, graphQLArgument); - } - } - resourceProperty.setArguments(arguments); - resourceProperty.setChildren(children); - Map resourceChild = new HashMap(); - resourceChild.put(resourceName, resourceProperty); - children = resourceChild; - } - property.setChildren(Collections.unmodifiableMap(children)); - property.setMethod(requestMethod); - property.setVariables(Collections.unmodifiableMap(propertyVariables)); - } - private Map variableListToMap(List variables) { Map variableMap = new HashMap(); for (Variable variable : variables) { @@ -181,6 +209,27 @@ private Map variableListToMap(List variables) { return variableMap; } + private Property annotationToProperty(GraphQLProperty annotation) { + Property property = new Property(); + property.setChildren(new HashMap()); + property.setArguments(new ArrayList()); + + if( annotation == null) { + return property; + } + + List arguments = new ArrayList(); + String name = annotation.name(); + property.setResourceName(name); + + for (GraphQLArgument graphQLArgument : annotation.arguments()) { + arguments = setArgument(arguments, graphQLArgument); + } + + property.setArguments(arguments); + return property; + } + private boolean isList(Field field) { String simpleName = field.getType().getSimpleName(); return simpleName.equalsIgnoreCase("ArrayList") || @@ -202,7 +251,7 @@ private boolean isProperty(Class clazz) { } /** - * Adds the arguments into the argument list from the GraphQLArgument annotation to provide the correct type + * Adds the arguments into the argument list from the GraphQLArgument annotation to provide the correct method * * @param arguments list of arguments to add the annotated argument to * @param graphQLArgument annotated argument to add to the request construction @@ -210,15 +259,20 @@ private boolean isProperty(Class clazz) { */ private List setArgument(List arguments, GraphQLArgument graphQLArgument) { String type = graphQLArgument.type(); + Argument argument; if ("Boolean".equalsIgnoreCase(type)) { - arguments.add(new Argument(graphQLArgument.name(), Boolean.valueOf(graphQLArgument.value()))); + argument = new Argument(graphQLArgument.name(), Boolean.valueOf(graphQLArgument.value())); } else if ("Integer".equalsIgnoreCase(type)) { - arguments.add(new Argument(graphQLArgument.name(), Integer.valueOf(graphQLArgument.value()))); + argument = new Argument(graphQLArgument.name(), Integer.valueOf(graphQLArgument.value())); } else if ("Float".equalsIgnoreCase(type)) { - arguments.add(new Argument(graphQLArgument.name(), Float.valueOf(graphQLArgument.value()))); + argument = new Argument(graphQLArgument.name(), Float.valueOf(graphQLArgument.value())); } else { - arguments.add(new Argument(graphQLArgument.name(), graphQLArgument.value())); + argument = new Argument(graphQLArgument.name(), graphQLArgument.value()); } + + argument.setVariable(graphQLArgument.variable()); + + arguments.add(argument); return arguments; } diff --git a/nodes/src/main/java/io/aexp/nodes/graphql/Operation.java b/nodes/src/main/java/io/aexp/nodes/graphql/Operation.java new file mode 100644 index 0000000..29cd370 --- /dev/null +++ b/nodes/src/main/java/io/aexp/nodes/graphql/Operation.java @@ -0,0 +1,97 @@ +package io.aexp.nodes.graphql; + +import io.aexp.nodes.graphql.exceptions.GraphQLException; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +final class Operation { + private String name; + private GraphQLTemplate.GraphQLMethod method; + private Map variables; + private Map children; + private StringBuilder message = new StringBuilder(); + + public Operation() { + this.name = null; + this.variables = null; + this.children = new HashMap(); + this.method = GraphQLTemplate.GraphQLMethod.QUERY; + } + + public void setName(String name) { + this.name = name; + } + + public void setVariables(Map variables) { + this.variables = variables; + } + + public void setChildren(Map children) { + this.children = children; + } + + public void setMethod(GraphQLTemplate.GraphQLMethod method) { + this.method = method; + } + + public Map getChildren() { + return children; + } + + protected String getMessage() { + // fail early + if(children == null) { + throw new GraphQLException("Operation must specify one or more properties"); + } + + if(method != null) { + message.append(method.getValue()).append(" "); + } + + if(name != null) { + message.append(name).append(" "); + } + + if (variables != null && !variables.isEmpty()) { + message.append("("); + List variableList = new ArrayList(); + for (Map.Entry entry : variables.entrySet()) { + variableList.add(entry.getKey() + ":" + entry.getValue()); + } + message.append(StringUtil.joinStringArray(",", variableList)); + message.append(")"); + } + + // process children + message.append("{ "); + for (Map.Entry entry : children.entrySet()) { + message.append(entry.getValue().getMessage(entry.getKey())); + } + message.append("} "); + + // return copy of message & rest + String res = message.toString(); + message.setLength(0); + return res; + } + + @Override + public String toString() { + return String.format("Operations{" + + "name='%s', " + + "method='%s', " + + "variables='%s', " + + "children='%s', " + + "message='%s'" + + "}", + name, + method, + variables, + children, + getMessage() + ); + } +} diff --git a/nodes/src/main/java/io/aexp/nodes/graphql/Property.java b/nodes/src/main/java/io/aexp/nodes/graphql/Property.java index 8712865..1220b75 100644 --- a/nodes/src/main/java/io/aexp/nodes/graphql/Property.java +++ b/nodes/src/main/java/io/aexp/nodes/graphql/Property.java @@ -50,12 +50,14 @@ protected String getMessage(String field) { message.append(StringUtil.joinStringArray(",", variableList)); message.append(")"); } - if (this.resourceName != null) message.append(": ").append(resourceName); + if (this.resourceName != null) { // && !this.resourceName.equals(field)) { + message.append(": ").append(resourceName); + } if (this.arguments != null && !this.arguments.isEmpty()) { message.append("("); List argumentList = new ArrayList(); for (Argument argument: arguments) { - argumentList.add(StringUtil.formatGraphQLParameter(argument.getKey(), argument.getValue())); + argumentList.add(StringUtil.formatGraphQLParameter(argument.getKey(), argument.getValue(), argument.getVariable())); } message.append(StringUtil.joinStringArray(",", argumentList)); message.append(") "); diff --git a/nodes/src/main/java/io/aexp/nodes/graphql/StringUtil.java b/nodes/src/main/java/io/aexp/nodes/graphql/StringUtil.java index 2a8d6b4..96582f3 100644 --- a/nodes/src/main/java/io/aexp/nodes/graphql/StringUtil.java +++ b/nodes/src/main/java/io/aexp/nodes/graphql/StringUtil.java @@ -58,6 +58,14 @@ static String formatGraphQLParameter(String key, T value) { return stringBuilder.toString(); } + static String formatGraphQLParameter(String key, T value, String variable) { + if(variable != null && !variable.equals("") && !variable.equals("null")) { + StringBuilder stringBuilder = new StringBuilder(); + return stringBuilder.append(key).append(":").append("$").append(variable).toString(); + } + return formatGraphQLParameter(key, value); + } + /** * Formats a list of values to confirm with GraphQL specification based on the type of each value * diff --git a/nodes/src/main/java/io/aexp/nodes/graphql/annotations/GraphQLArgument.java b/nodes/src/main/java/io/aexp/nodes/graphql/annotations/GraphQLArgument.java index f8ddcc5..afe221a 100644 --- a/nodes/src/main/java/io/aexp/nodes/graphql/annotations/GraphQLArgument.java +++ b/nodes/src/main/java/io/aexp/nodes/graphql/annotations/GraphQLArgument.java @@ -26,4 +26,5 @@ String name(); String value() default "null"; String type() default "null"; + String variable() default "null"; } diff --git a/nodes/src/main/java/io/aexp/nodes/graphql/annotations/GraphQLOperation.java b/nodes/src/main/java/io/aexp/nodes/graphql/annotations/GraphQLOperation.java new file mode 100644 index 0000000..e8002de --- /dev/null +++ b/nodes/src/main/java/io/aexp/nodes/graphql/annotations/GraphQLOperation.java @@ -0,0 +1,19 @@ +package io.aexp.nodes.graphql.annotations; + +import io.aexp.nodes.graphql.GraphQLTemplate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +@Target({ElementType.TYPE}) +@Retention(RUNTIME) +public @interface GraphQLOperation { + + String name(); + GraphQLTemplate.GraphQLMethod method() default GraphQLTemplate.GraphQLMethod.QUERY; + GraphQLVariable[] variables() default {}; + GraphQLProperty property(); +} diff --git a/nodes/src/test/java/io/aexp/nodes/graphql/GraphQLTemplateTest.java b/nodes/src/test/java/io/aexp/nodes/graphql/GraphQLTemplateTest.java index 960fadd..2bf456a 100644 --- a/nodes/src/test/java/io/aexp/nodes/graphql/GraphQLTemplateTest.java +++ b/nodes/src/test/java/io/aexp/nodes/graphql/GraphQLTemplateTest.java @@ -22,6 +22,7 @@ import okhttp3.mockwebserver.MockWebServer; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import java.net.MalformedURLException; @@ -56,7 +57,7 @@ public void successfulMutationWithErrors() throws GraphQLException, MalformedURL " }," + " \"errors\": [\n" + " {\n" + - " \"message\": \"Cannot query field \\\"invalid\\\" on type \\\"TestTO\\\".\",\n" + + " \"message\": \"Cannot query field \\\"invalid\\\" on method \\\"TestTO\\\".\",\n" + " \"locations\": [\n" + " {\n" + " \"line\": 1,\n" + @@ -74,7 +75,7 @@ public void successfulMutationWithErrors() throws GraphQLException, MalformedURL .build(); GraphQLResponseEntity response = graphQLTemplate.mutate(requestEntity, TestModel.class); assertEquals("mutation ($andAnothaVariable:status,$anothaVariable:Int,$andAListVariable:[String],$variableName:String!){ test (id:null) { testShort testCharacter testList { anotherTestString (variableName:$variableName) andAnothaOne (anothaVariable:$anothaVariable,andAnothaVariable:$andAnothaVariable,andAListVariable:$andAListVariable) } testInteger testBoolean nestedTest { anotherTestString (variableName:$variableName) andAnothaOne (anothaVariable:$anothaVariable,andAnothaVariable:$andAnothaVariable,andAListVariable:$andAListVariable) } testByte testString : testString(anotherOne:null,default:\"default\",defaultList:null) testArrayList testFloat testDouble testLong } } ", requestEntity.getRequest().toString()); - assertEquals("GraphQLResponseEntity{errors=[Error{message='Cannot query field \"invalid\" on type \"TestTO\".', locations=[Location{line='1', column='1'}]}], response=TestTO{testString='String', testByte=null, testShort=null, testInteger=null, testLong=null, testCharacter=\u0000, testFloat=null, testDouble=null, testBoolean=null, nestedTest=null, testArrayList=null, testList=null, ignoredField='null'}}", response.toString()); + assertEquals("GraphQLResponseEntity{errors=[Error{message='Cannot query field \"invalid\" on method \"TestTO\".', locations=[Location{line='1', column='1'}]}], response=TestTO{testString='String', testByte=null, testShort=null, testInteger=null, testLong=null, testCharacter=\u0000, testFloat=null, testDouble=null, testBoolean=null, nestedTest=null, testArrayList=null, testList=null, ignoredField='null'}}", response.toString()); } @Test diff --git a/nodes/src/test/java/io/aexp/nodes/graphql/models/TestOperation.java b/nodes/src/test/java/io/aexp/nodes/graphql/models/TestOperation.java new file mode 100644 index 0000000..4b365dd --- /dev/null +++ b/nodes/src/test/java/io/aexp/nodes/graphql/models/TestOperation.java @@ -0,0 +1,16 @@ +package io.aexp.nodes.graphql.models; + +import io.aexp.nodes.graphql.GraphQLTemplate; +import io.aexp.nodes.graphql.annotations.*; + +@GraphQLOperation(name = "TestOperationName", method = GraphQLTemplate.GraphQLMethod.QUERY, + variables = { + @GraphQLVariable(name = "inputTestName", scalar = "String!") + }, + property = @GraphQLProperty(name = "FindTest", arguments = { + @GraphQLArgument(name = "testName", type = "String", variable="inputTestName") + }) +) +public class TestOperation { + public String aStringProperty; +} diff --git a/nodes/src/test/java/io/aexp/nodes/graphql/scenarios/OperationAnnotationTest.java b/nodes/src/test/java/io/aexp/nodes/graphql/scenarios/OperationAnnotationTest.java new file mode 100644 index 0000000..860f649 --- /dev/null +++ b/nodes/src/test/java/io/aexp/nodes/graphql/scenarios/OperationAnnotationTest.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018 American Express Travel Related Services Company, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package io.aexp.nodes.graphql.scenarios; + +import io.aexp.nodes.graphql.GraphQLRequestEntity; +import io.aexp.nodes.graphql.exceptions.GraphQLException; +import io.aexp.nodes.graphql.models.TestOperation; +import org.junit.Test; +import static org.junit.Assert.assertThat; +import static org.hamcrest.CoreMatchers.containsString; + +import java.net.MalformedURLException; + + +public class OperationAnnotationTest { + + private String EXAMPLE_URL = "https://graphql.example.com"; + + @Test + public void operationWithVariablesAndProperties() throws GraphQLException, MalformedURLException { + GraphQLRequestEntity requestEntity = GraphQLRequestEntity.Builder() + .url(EXAMPLE_URL) + .variables() + .request(TestOperation.class) + .build(); + System.out.println("Request Entity:" + requestEntity.toString()); + assertThat(requestEntity.toString(), containsString("'query TestOperationName ($inputTestName:String!){ FindTest (testName:$inputTestName) {")); + } + +} diff --git a/pom.xml b/pom.xml index c6931d5..3819c50 100644 --- a/pom.xml +++ b/pom.xml @@ -20,6 +20,8 @@ UTF-8 UTF-8 + 1.7 + 1.7