From 1f7a7a851582007024de9300ee010b03f61e2dff Mon Sep 17 00:00:00 2001 From: Michiel Oliemans Date: Thu, 8 Nov 2018 10:33:58 +0100 Subject: [PATCH 1/4] Alternative construction --- .../servlet/AbstractGraphQLHttpServlet.java | 55 +++++++++++++----- .../servlet/DefaultGraphQLServlet.java | 33 +++++++++++ .../graphql/servlet/GraphQLConfiguration.java | 58 +++++++++++++++++++ .../servlet/OsgiGraphQLHttpServlet.java | 5 ++ .../servlet/SimpleAbstractGraphQLServlet.java | 20 ------- .../servlet/SimpleGraphQLHttpServlet.java | 50 +++++++++++++--- 6 files changed, 178 insertions(+), 43 deletions(-) create mode 100644 src/main/java/graphql/servlet/DefaultGraphQLServlet.java create mode 100644 src/main/java/graphql/servlet/GraphQLConfiguration.java delete mode 100644 src/main/java/graphql/servlet/SimpleAbstractGraphQLServlet.java diff --git a/src/main/java/graphql/servlet/AbstractGraphQLHttpServlet.java b/src/main/java/graphql/servlet/AbstractGraphQLHttpServlet.java index ffba1809..20777f6c 100644 --- a/src/main/java/graphql/servlet/AbstractGraphQLHttpServlet.java +++ b/src/main/java/graphql/servlet/AbstractGraphQLHttpServlet.java @@ -12,6 +12,7 @@ import javax.servlet.AsyncContext; import javax.servlet.Servlet; +import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @@ -50,26 +51,52 @@ public abstract class AbstractGraphQLHttpServlet extends HttpServlet implements private static final GraphQLRequest INTROSPECTION_REQUEST = new GraphQLRequest(IntrospectionQuery.INTROSPECTION_QUERY, new HashMap<>(), null); private static final String[] MULTIPART_KEYS = new String[]{"operations", "graphql", "query"}; + /** + * @deprecated use {@link #getConfiguration()} instead + */ + @Deprecated protected abstract GraphQLQueryInvoker getQueryInvoker(); + /** + * @deprecated use {@link #getConfiguration()} instead + */ + @Deprecated protected abstract GraphQLInvocationInputFactory getInvocationInputFactory(); + /** + * @deprecated use {@link #getConfiguration()} instead + */ + @Deprecated protected abstract GraphQLObjectMapper getGraphQLObjectMapper(); - private final List listeners; + /** + * @deprecated use {@link #getConfiguration()} instead + */ + @Deprecated + protected abstract boolean isAsyncServletMode(); + + protected abstract GraphQLConfiguration getConfiguration(); - private final HttpRequestHandler getHandler; - private final HttpRequestHandler postHandler; + /** + * @deprecated use {@link #getConfiguration()} instead + */ + @Deprecated + private final List listeners; - private final boolean asyncServletMode; + private HttpRequestHandler getHandler; + private HttpRequestHandler postHandler; public AbstractGraphQLHttpServlet() { - this(null, false); + this(null); } - public AbstractGraphQLHttpServlet(List listeners, boolean asyncServletMode) { + public AbstractGraphQLHttpServlet(List listeners) { this.listeners = listeners != null ? new ArrayList<>(listeners) : new ArrayList<>(); - this.asyncServletMode = asyncServletMode; + } + + @Override + public void init(ServletConfig config) { + GraphQLConfiguration configuration = getConfiguration(); this.getHandler = (request, response) -> { GraphQLInvocationInputFactory invocationInputFactory = getInvocationInputFactory(); @@ -116,8 +143,8 @@ public AbstractGraphQLHttpServlet(List listeners, boolea query(queryInvoker, graphQLObjectMapper, invocationInputFactory.create(new GraphQLRequest(query, null, null)), response); } else if (request.getContentType() != null && request.getContentType().startsWith("multipart/form-data") && !request.getParts().isEmpty()) { final Map> fileItems = request.getParts() - .stream() - .collect(Collectors.groupingBy(Part::getName)); + .stream() + .collect(Collectors.groupingBy(Part::getName)); for (String key : MULTIPART_KEYS) { // Check to see if there is a part under the key we seek @@ -134,14 +161,14 @@ public AbstractGraphQLHttpServlet(List listeners, boolea InputStream inputStream = asMarkableInputStream(queryItem.get().getInputStream()); final Optional>> variablesMap = - getFileItem(fileItems, "map").map(graphQLObjectMapper::deserializeMultipartMap); + getFileItem(fileItems, "map").map(graphQLObjectMapper::deserializeMultipartMap); if (isBatchedQuery(inputStream)) { List graphQLRequests = - graphQLObjectMapper.readBatchedGraphQLRequest(inputStream); + graphQLObjectMapper.readBatchedGraphQLRequest(inputStream); variablesMap.ifPresent(map -> graphQLRequests.forEach(r -> mapMultipartVariables(r, map, fileItems))); GraphQLBatchedInvocationInput invocationInput = - invocationInputFactory.create(graphQLRequests, request, response); + invocationInputFactory.create(graphQLRequests, request, response); invocationInput.getContext().setParts(fileItems); queryBatched(queryInvoker, graphQLObjectMapper, invocationInput, response); return; @@ -155,7 +182,7 @@ public AbstractGraphQLHttpServlet(List listeners, boolea variablesMap.ifPresent(m -> mapMultipartVariables(graphQLRequest, m, fileItems)); GraphQLSingleInvocationInput invocationInput = - invocationInputFactory.create(graphQLRequest, request, response); + invocationInputFactory.create(graphQLRequest, request, response); invocationInput.getContext().setParts(fileItems); query(queryInvoker, graphQLObjectMapper, invocationInput, response); return; @@ -255,7 +282,7 @@ public String executeQuery(String query) { } private void doRequestAsync(HttpServletRequest request, HttpServletResponse response, HttpRequestHandler handler) { - if (asyncServletMode) { + if (isAsyncServletMode()) { AsyncContext asyncContext = request.startAsync(); HttpServletRequest asyncRequest = (HttpServletRequest) asyncContext.getRequest(); HttpServletResponse asyncResponse = (HttpServletResponse) asyncContext.getResponse(); diff --git a/src/main/java/graphql/servlet/DefaultGraphQLServlet.java b/src/main/java/graphql/servlet/DefaultGraphQLServlet.java new file mode 100644 index 00000000..4b9ca838 --- /dev/null +++ b/src/main/java/graphql/servlet/DefaultGraphQLServlet.java @@ -0,0 +1,33 @@ +package graphql.servlet; + +import javax.servlet.ServletConfig; + +public class DefaultGraphQLServlet extends AbstractGraphQLHttpServlet { + + @Override + public void init(ServletConfig config) { + + super.init(config); + } + + @Override + protected GraphQLInvocationInputFactory getInvocationInputFactory() { + return null; + } + + @Override + protected GraphQLQueryInvoker getQueryInvoker() { + return GraphQLQueryInvoker.newBuilder().build(); + } + + @Override + protected GraphQLObjectMapper getGraphQLObjectMapper() { + return GraphQLObjectMapper.newBuilder().build(); + } + + @Override + protected boolean isAsyncServletMode() { + return false; + } + +} diff --git a/src/main/java/graphql/servlet/GraphQLConfiguration.java b/src/main/java/graphql/servlet/GraphQLConfiguration.java new file mode 100644 index 00000000..0d9beeeb --- /dev/null +++ b/src/main/java/graphql/servlet/GraphQLConfiguration.java @@ -0,0 +1,58 @@ +package graphql.servlet; + +import graphql.schema.GraphQLSchema; + +import java.util.ArrayList; +import java.util.List; + +public class GraphQLConfiguration { + + private GraphQLInvocationInputFactory invocationInputFactory; + private GraphQLQueryInvoker queryInvoker = GraphQLQueryInvoker.newBuilder().build(); + private GraphQLObjectMapper objectMapper = GraphQLObjectMapper.newBuilder().build(); + private List listeners; + private boolean asyncServletModeEnabled; + + public static GraphQLConfiguration.Builder with(GraphQLSchema schema) { + return with(new DefaultGraphQLSchemaProvider(schema)); + } + + public static GraphQLConfiguration.Builder with(GraphQLSchemaProvider schemaProvider) { + return new Builder(GraphQLInvocationInputFactory.newBuilder(schemaProvider)); + } + + + public static class Builder { + + private GraphQLInvocationInputFactory.Builder invocationInputFactoryBuilder; + private GraphQLQueryInvoker queryInvoker = GraphQLQueryInvoker.newBuilder().build(); + private GraphQLObjectMapper objectMapper = GraphQLObjectMapper.newBuilder().build(); + private List listeners = new ArrayList<>(); + private boolean asyncServletModeEnabled = false; + + private Builder(GraphQLInvocationInputFactory.Builder invocationInputFactoryBuilder) { + this.invocationInputFactoryBuilder = invocationInputFactoryBuilder; + } + + public Builder with(GraphQLQueryInvoker queryInvoker) { + this.queryInvoker = queryInvoker; + return this; + } + + public Builder with(GraphQLObjectMapper objectMapper) { + this.objectMapper = objectMapper; + return this; + } + + public Builder with(boolean asyncServletModeEnabled) { + this.asyncServletModeEnabled = asyncServletModeEnabled; + return this; + } + + public GraphQLConfiguration build() { + return null; + } + + } + +} diff --git a/src/main/java/graphql/servlet/OsgiGraphQLHttpServlet.java b/src/main/java/graphql/servlet/OsgiGraphQLHttpServlet.java index 76a6dbc0..2cec68bf 100644 --- a/src/main/java/graphql/servlet/OsgiGraphQLHttpServlet.java +++ b/src/main/java/graphql/servlet/OsgiGraphQLHttpServlet.java @@ -83,6 +83,11 @@ protected GraphQLObjectMapper getGraphQLObjectMapper() { return graphQLObjectMapper; } + @Override + protected boolean isAsyncServletMode() { + return false; + } + public OsgiGraphQLHttpServlet() { updateSchema(); diff --git a/src/main/java/graphql/servlet/SimpleAbstractGraphQLServlet.java b/src/main/java/graphql/servlet/SimpleAbstractGraphQLServlet.java deleted file mode 100644 index b00adf61..00000000 --- a/src/main/java/graphql/servlet/SimpleAbstractGraphQLServlet.java +++ /dev/null @@ -1,20 +0,0 @@ -package graphql.servlet; - -public abstract class SimpleAbstractGraphQLServlet extends AbstractGraphQLHttpServlet { - - @Override - protected GraphQLQueryInvoker getQueryInvoker() { - return null; - } - - @Override - protected GraphQLInvocationInputFactory getInvocationInputFactory() { - return null; - } - - @Override - protected GraphQLObjectMapper getGraphQLObjectMapper() { - return null; - } - -} diff --git a/src/main/java/graphql/servlet/SimpleGraphQLHttpServlet.java b/src/main/java/graphql/servlet/SimpleGraphQLHttpServlet.java index 24341660..43f6b2a8 100644 --- a/src/main/java/graphql/servlet/SimpleGraphQLHttpServlet.java +++ b/src/main/java/graphql/servlet/SimpleGraphQLHttpServlet.java @@ -3,22 +3,48 @@ import graphql.schema.GraphQLSchema; import java.util.List; +import java.util.Objects; /** * @author Andrew Potter */ public class SimpleGraphQLHttpServlet extends AbstractGraphQLHttpServlet { - private final GraphQLInvocationInputFactory invocationInputFactory; - private final GraphQLQueryInvoker queryInvoker; - private final GraphQLObjectMapper graphQLObjectMapper; + private GraphQLConfiguration configuration; - // protected to allow class to be extended - protected SimpleGraphQLHttpServlet(GraphQLInvocationInputFactory invocationInputFactory, GraphQLQueryInvoker queryInvoker, GraphQLObjectMapper graphQLObjectMapper, List listeners, boolean asyncServletMode) { - super(listeners, asyncServletMode); - this.invocationInputFactory = invocationInputFactory; - this.queryInvoker = queryInvoker; - this.graphQLObjectMapper = graphQLObjectMapper; +// private GraphQLInvocationInputFactory invocationInputFactory; +// private GraphQLQueryInvoker queryInvoker; +// private GraphQLObjectMapper graphQLObjectMapper; +// private boolean asyncServletMode; + + public SimpleGraphQLHttpServlet() { + super(null); + } + + /** + * @param invocationInputFactory + * @param queryInvoker + * @param graphQLObjectMapper + * @param listeners + * @param asyncServletMode + * @deprecated + */ + @Deprecated + public SimpleGraphQLHttpServlet(GraphQLInvocationInputFactory invocationInputFactory, GraphQLQueryInvoker queryInvoker, GraphQLObjectMapper graphQLObjectMapper, List listeners, boolean asyncServletMode) { + super(listeners); + this.configuration = GraphQLConfiguration.with(invocationInputFactory) + .with(queryInvoker) + .with(graphQLObjectMapper) + .with(asyncServletMode); + } + + private SimpleGraphQLHttpServlet(GraphQLConfiguration configuration) { + this.configuration = Objects.requireNonNull(configuration, "configuration is required"); + } + + @Override + protected GraphQLConfiguration getConfiguration() { + return configuration; } @Override @@ -36,6 +62,11 @@ protected GraphQLObjectMapper getGraphQLObjectMapper() { return graphQLObjectMapper; } + @Override + protected boolean isAsyncServletMode() { + return asyncServletMode; + } + public static Builder newBuilder(GraphQLSchema schema) { return new Builder(GraphQLInvocationInputFactory.newBuilder(schema).build()); } @@ -79,6 +110,7 @@ public Builder withListeners(List listeners) { return this; } + @Deprecated public SimpleGraphQLHttpServlet build() { return new SimpleGraphQLHttpServlet(invocationInputFactory, queryInvoker, graphQLObjectMapper, listeners, asyncServletMode); } From ba4e7329a3a7392ba37bb90b63156293d961b8fa Mon Sep 17 00:00:00 2001 From: Michiel Oliemans Date: Thu, 8 Nov 2018 19:55:37 +0100 Subject: [PATCH 2/4] Updated readme in line with new doc --- .../servlet/AbstractGraphQLHttpServlet.java | 70 ++++++++++--------- .../servlet/ConfiguredGraphQLHttpServlet.java | 18 +++++ .../servlet/DefaultGraphQLServlet.java | 4 +- .../graphql/servlet/GraphQLConfiguration.java | 58 ++++++++++++++- .../graphql/servlet/GraphQLHttpServlet.java | 45 ++++++++++++ .../servlet/SimpleGraphQLHttpServlet.java | 27 +++---- .../AbstractGraphQLHttpServletSpec.groovy | 3 +- .../groovy/graphql/servlet/TestUtils.groovy | 4 +- 8 files changed, 178 insertions(+), 51 deletions(-) create mode 100644 src/main/java/graphql/servlet/ConfiguredGraphQLHttpServlet.java create mode 100644 src/main/java/graphql/servlet/GraphQLHttpServlet.java diff --git a/src/main/java/graphql/servlet/AbstractGraphQLHttpServlet.java b/src/main/java/graphql/servlet/AbstractGraphQLHttpServlet.java index 20777f6c..7539c17e 100644 --- a/src/main/java/graphql/servlet/AbstractGraphQLHttpServlet.java +++ b/src/main/java/graphql/servlet/AbstractGraphQLHttpServlet.java @@ -25,7 +25,6 @@ import java.io.Writer; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -51,31 +50,40 @@ public abstract class AbstractGraphQLHttpServlet extends HttpServlet implements private static final GraphQLRequest INTROSPECTION_REQUEST = new GraphQLRequest(IntrospectionQuery.INTROSPECTION_QUERY, new HashMap<>(), null); private static final String[] MULTIPART_KEYS = new String[]{"operations", "graphql", "query"}; + private GraphQLConfiguration configuration; + /** - * @deprecated use {@link #getConfiguration()} instead + * @deprecated override {@link #getConfiguration()} instead */ @Deprecated protected abstract GraphQLQueryInvoker getQueryInvoker(); /** - * @deprecated use {@link #getConfiguration()} instead + * @deprecated override {@link #getConfiguration()} instead */ @Deprecated protected abstract GraphQLInvocationInputFactory getInvocationInputFactory(); /** - * @deprecated use {@link #getConfiguration()} instead + * @deprecated override {@link #getConfiguration()} instead */ @Deprecated protected abstract GraphQLObjectMapper getGraphQLObjectMapper(); /** - * @deprecated use {@link #getConfiguration()} instead + * @deprecated override {@link #getConfiguration()} instead */ @Deprecated protected abstract boolean isAsyncServletMode(); - protected abstract GraphQLConfiguration getConfiguration(); + protected GraphQLConfiguration getConfiguration() { + return GraphQLConfiguration.with(getInvocationInputFactory()) + .with(getQueryInvoker()) + .with(getGraphQLObjectMapper()) + .with(isAsyncServletMode()) + .with(listeners) + .build(); + } /** * @deprecated use {@link #getConfiguration()} instead @@ -95,13 +103,13 @@ public AbstractGraphQLHttpServlet(List listeners) { } @Override - public void init(ServletConfig config) { - GraphQLConfiguration configuration = getConfiguration(); + public void init(ServletConfig servletConfig) { + this.configuration = getConfiguration(); this.getHandler = (request, response) -> { - GraphQLInvocationInputFactory invocationInputFactory = getInvocationInputFactory(); - GraphQLObjectMapper graphQLObjectMapper = getGraphQLObjectMapper(); - GraphQLQueryInvoker queryInvoker = getQueryInvoker(); + GraphQLInvocationInputFactory invocationInputFactory = configuration.getInvocationInputFactory(); + GraphQLObjectMapper graphQLObjectMapper = configuration.getObjectMapper(); + GraphQLQueryInvoker queryInvoker = configuration.getQueryInvoker(); String path = request.getPathInfo(); if (path == null) { @@ -133,9 +141,9 @@ public void init(ServletConfig config) { }; this.postHandler = (request, response) -> { - GraphQLInvocationInputFactory invocationInputFactory = getInvocationInputFactory(); - GraphQLObjectMapper graphQLObjectMapper = getGraphQLObjectMapper(); - GraphQLQueryInvoker queryInvoker = getQueryInvoker(); + GraphQLInvocationInputFactory invocationInputFactory = configuration.getInvocationInputFactory(); + GraphQLObjectMapper graphQLObjectMapper = configuration.getObjectMapper(); + GraphQLQueryInvoker queryInvoker = configuration.getQueryInvoker(); try { if (APPLICATION_GRAPHQL.equals(request.getContentType())) { @@ -148,7 +156,7 @@ public void init(ServletConfig config) { for (String key : MULTIPART_KEYS) { // Check to see if there is a part under the key we seek - if(!fileItems.containsKey(key)) { + if (!fileItems.containsKey(key)) { continue; } @@ -174,7 +182,7 @@ public void init(ServletConfig config) { return; } else { GraphQLRequest graphQLRequest; - if("query".equals(key)) { + if ("query".equals(key)) { graphQLRequest = buildRequestFromQuery(inputStream, graphQLObjectMapper, fileItems); } else { graphQLRequest = graphQLObjectMapper.readGraphQLRequest(inputStream); @@ -217,8 +225,7 @@ private static InputStream asMarkableInputStream(InputStream inputStream) { private GraphQLRequest buildRequestFromQuery(InputStream inputStream, GraphQLObjectMapper graphQLObjectMapper, - Map> fileItems) throws IOException - { + Map> fileItems) throws IOException { GraphQLRequest graphQLRequest; String query = new String(ByteStreams.toByteArray(inputStream)); @@ -240,49 +247,48 @@ private GraphQLRequest buildRequestFromQuery(InputStream inputStream, private void mapMultipartVariables(GraphQLRequest request, Map> variablesMap, - Map> fileItems) - { + Map> fileItems) { Map variables = request.getVariables(); variablesMap.forEach((partName, objectPaths) -> { Part part = getFileItem(fileItems, partName) - .orElseThrow(() -> new RuntimeException("unable to find part name " + - partName + - " as referenced in the variables map")); + .orElseThrow(() -> new RuntimeException("unable to find part name " + + partName + + " as referenced in the variables map")); objectPaths.forEach(objectPath -> VariableMapper.mapVariable(objectPath, variables, part)); }); } public void addListener(GraphQLServletListener servletListener) { - listeners.add(servletListener); + configuration.add(servletListener); } public void removeListener(GraphQLServletListener servletListener) { - listeners.remove(servletListener); + configuration.remove(servletListener); } @Override public String[] getQueries() { - return getInvocationInputFactory().getSchemaProvider().getSchema().getQueryType().getFieldDefinitions().stream().map(GraphQLFieldDefinition::getName).toArray(String[]::new); + return configuration.getInvocationInputFactory().getSchemaProvider().getSchema().getQueryType().getFieldDefinitions().stream().map(GraphQLFieldDefinition::getName).toArray(String[]::new); } @Override public String[] getMutations() { - return getInvocationInputFactory().getSchemaProvider().getSchema().getMutationType().getFieldDefinitions().stream().map(GraphQLFieldDefinition::getName).toArray(String[]::new); + return configuration.getInvocationInputFactory().getSchemaProvider().getSchema().getMutationType().getFieldDefinitions().stream().map(GraphQLFieldDefinition::getName).toArray(String[]::new); } @Override public String executeQuery(String query) { try { - return getGraphQLObjectMapper().serializeResultAsJson(getQueryInvoker().query(getInvocationInputFactory().create(new GraphQLRequest(query, new HashMap<>(), null)))); + return configuration.getObjectMapper().serializeResultAsJson(configuration.getQueryInvoker().query(configuration.getInvocationInputFactory().create(new GraphQLRequest(query, new HashMap<>(), null)))); } catch (Exception e) { return e.getMessage(); } } private void doRequestAsync(HttpServletRequest request, HttpServletResponse response, HttpRequestHandler handler) { - if (isAsyncServletMode()) { + if (configuration.isAsyncServletModeEnabled()) { AsyncContext asyncContext = request.startAsync(); HttpServletRequest asyncRequest = (HttpServletRequest) asyncContext.getRequest(); HttpServletResponse asyncResponse = (HttpServletResponse) asyncContext.getResponse(); @@ -351,11 +357,7 @@ private void queryBatched(GraphQLQueryInvoker queryInvoker, GraphQLObjectMapper } private List runListeners(Function action) { - if (listeners == null) { - return Collections.emptyList(); - } - - return listeners.stream() + return configuration.getListeners().stream() .map(listener -> { try { return action.apply(listener); diff --git a/src/main/java/graphql/servlet/ConfiguredGraphQLHttpServlet.java b/src/main/java/graphql/servlet/ConfiguredGraphQLHttpServlet.java new file mode 100644 index 00000000..c00fdf1c --- /dev/null +++ b/src/main/java/graphql/servlet/ConfiguredGraphQLHttpServlet.java @@ -0,0 +1,18 @@ +package graphql.servlet; + +import java.util.Objects; + +class ConfiguredGraphQLHttpServlet extends GraphQLHttpServlet { + + private GraphQLConfiguration configuration; + + ConfiguredGraphQLHttpServlet(GraphQLConfiguration configuration) { + this.configuration = Objects.requireNonNull(configuration, "configuration is required"); + } + + @Override + protected GraphQLConfiguration getConfiguration() { + return configuration; + } + +} diff --git a/src/main/java/graphql/servlet/DefaultGraphQLServlet.java b/src/main/java/graphql/servlet/DefaultGraphQLServlet.java index 4b9ca838..76b11824 100644 --- a/src/main/java/graphql/servlet/DefaultGraphQLServlet.java +++ b/src/main/java/graphql/servlet/DefaultGraphQLServlet.java @@ -5,9 +5,9 @@ public class DefaultGraphQLServlet extends AbstractGraphQLHttpServlet { @Override - public void init(ServletConfig config) { + public void init(ServletConfig servletConfig) { - super.init(config); + super.init(servletConfig); } @Override diff --git a/src/main/java/graphql/servlet/GraphQLConfiguration.java b/src/main/java/graphql/servlet/GraphQLConfiguration.java index 0d9beeeb..6d93f323 100644 --- a/src/main/java/graphql/servlet/GraphQLConfiguration.java +++ b/src/main/java/graphql/servlet/GraphQLConfiguration.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Objects; public class GraphQLConfiguration { @@ -21,10 +22,50 @@ public static GraphQLConfiguration.Builder with(GraphQLSchemaProvider schemaProv return new Builder(GraphQLInvocationInputFactory.newBuilder(schemaProvider)); } + static GraphQLConfiguration.Builder with(GraphQLInvocationInputFactory invocationInputFactory) { + return new Builder(invocationInputFactory); + } + + private GraphQLConfiguration(GraphQLInvocationInputFactory invocationInputFactory, GraphQLQueryInvoker queryInvoker, GraphQLObjectMapper objectMapper, List listeners, boolean asyncServletModeEnabled) { + this.invocationInputFactory = invocationInputFactory; + this.queryInvoker = queryInvoker; + this.objectMapper = objectMapper; + this.listeners = listeners; + this.asyncServletModeEnabled = asyncServletModeEnabled; + } + + public GraphQLInvocationInputFactory getInvocationInputFactory() { + return invocationInputFactory; + } + + public GraphQLQueryInvoker getQueryInvoker() { + return queryInvoker; + } + + public GraphQLObjectMapper getObjectMapper() { + return objectMapper; + } + + public List getListeners() { + return new ArrayList<>(listeners); + } + + public boolean isAsyncServletModeEnabled() { + return asyncServletModeEnabled; + } + + public void add(GraphQLServletListener listener) { + listeners.add(listener); + } + + public boolean remove(GraphQLServletListener listener) { + return listeners.remove(listener); + } public static class Builder { private GraphQLInvocationInputFactory.Builder invocationInputFactoryBuilder; + private GraphQLInvocationInputFactory invocationInputFactory; private GraphQLQueryInvoker queryInvoker = GraphQLQueryInvoker.newBuilder().build(); private GraphQLObjectMapper objectMapper = GraphQLObjectMapper.newBuilder().build(); private List listeners = new ArrayList<>(); @@ -34,6 +75,10 @@ private Builder(GraphQLInvocationInputFactory.Builder invocationInputFactoryBuil this.invocationInputFactoryBuilder = invocationInputFactoryBuilder; } + private Builder(GraphQLInvocationInputFactory invocationInputFactory) { + this.invocationInputFactory = invocationInputFactory; + } + public Builder with(GraphQLQueryInvoker queryInvoker) { this.queryInvoker = queryInvoker; return this; @@ -44,13 +89,24 @@ public Builder with(GraphQLObjectMapper objectMapper) { return this; } + public Builder with(List listeners) { + this.listeners = Objects.requireNonNull(listeners, "listeners must not be null"); + return this; + } + public Builder with(boolean asyncServletModeEnabled) { this.asyncServletModeEnabled = asyncServletModeEnabled; return this; } public GraphQLConfiguration build() { - return null; + return new GraphQLConfiguration( + this.invocationInputFactory != null ? this.invocationInputFactory : invocationInputFactoryBuilder.build(), + queryInvoker, + objectMapper, + listeners, + asyncServletModeEnabled + ); } } diff --git a/src/main/java/graphql/servlet/GraphQLHttpServlet.java b/src/main/java/graphql/servlet/GraphQLHttpServlet.java new file mode 100644 index 00000000..0106c22e --- /dev/null +++ b/src/main/java/graphql/servlet/GraphQLHttpServlet.java @@ -0,0 +1,45 @@ +package graphql.servlet; + +import graphql.schema.GraphQLSchema; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * @author Michiel Oliemans + */ +public abstract class GraphQLHttpServlet extends AbstractGraphQLHttpServlet { + + public static GraphQLHttpServlet with(GraphQLSchema schema) { + return new ConfiguredGraphQLHttpServlet(GraphQLConfiguration.with(schema).build()); + } + + public static GraphQLHttpServlet with(GraphQLConfiguration configuration) { + return new ConfiguredGraphQLHttpServlet(configuration); + } + + @Override + protected abstract GraphQLConfiguration getConfiguration(); + + @Override + protected GraphQLQueryInvoker getQueryInvoker() { + throw new UnsupportedOperationException(); + } + + @Override + protected GraphQLInvocationInputFactory getInvocationInputFactory() { + throw new UnsupportedOperationException(); + } + + @Override + protected GraphQLObjectMapper getGraphQLObjectMapper() { + throw new UnsupportedOperationException(); + } + + @Override + protected boolean isAsyncServletMode() { + throw new UnsupportedOperationException(); + } + +} diff --git a/src/main/java/graphql/servlet/SimpleGraphQLHttpServlet.java b/src/main/java/graphql/servlet/SimpleGraphQLHttpServlet.java index 43f6b2a8..7a3cec1f 100644 --- a/src/main/java/graphql/servlet/SimpleGraphQLHttpServlet.java +++ b/src/main/java/graphql/servlet/SimpleGraphQLHttpServlet.java @@ -2,6 +2,7 @@ import graphql.schema.GraphQLSchema; +import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -12,13 +13,7 @@ public class SimpleGraphQLHttpServlet extends AbstractGraphQLHttpServlet { private GraphQLConfiguration configuration; -// private GraphQLInvocationInputFactory invocationInputFactory; -// private GraphQLQueryInvoker queryInvoker; -// private GraphQLObjectMapper graphQLObjectMapper; -// private boolean asyncServletMode; - public SimpleGraphQLHttpServlet() { - super(null); } /** @@ -35,7 +30,9 @@ public SimpleGraphQLHttpServlet(GraphQLInvocationInputFactory invocationInputFac this.configuration = GraphQLConfiguration.with(invocationInputFactory) .with(queryInvoker) .with(graphQLObjectMapper) - .with(asyncServletMode); + .with(listeners != null ? listeners : new ArrayList<>()) + .with(asyncServletMode) + .build(); } private SimpleGraphQLHttpServlet(GraphQLConfiguration configuration) { @@ -49,22 +46,22 @@ protected GraphQLConfiguration getConfiguration() { @Override protected GraphQLQueryInvoker getQueryInvoker() { - return queryInvoker; + return configuration.getQueryInvoker(); } @Override protected GraphQLInvocationInputFactory getInvocationInputFactory() { - return invocationInputFactory; + return configuration.getInvocationInputFactory(); } @Override protected GraphQLObjectMapper getGraphQLObjectMapper() { - return graphQLObjectMapper; + return configuration.getObjectMapper(); } @Override protected boolean isAsyncServletMode() { - return asyncServletMode; + return configuration.isAsyncServletModeEnabled(); } public static Builder newBuilder(GraphQLSchema schema) { @@ -112,7 +109,13 @@ public Builder withListeners(List listeners) { @Deprecated public SimpleGraphQLHttpServlet build() { - return new SimpleGraphQLHttpServlet(invocationInputFactory, queryInvoker, graphQLObjectMapper, listeners, asyncServletMode); + GraphQLConfiguration configuration = GraphQLConfiguration.with(invocationInputFactory) + .with(queryInvoker) + .with(graphQLObjectMapper) + .with(listeners != null ? listeners : new ArrayList<>()) + .with(asyncServletMode) + .build(); + return new SimpleGraphQLHttpServlet(configuration); } } } diff --git a/src/test/groovy/graphql/servlet/AbstractGraphQLHttpServletSpec.groovy b/src/test/groovy/graphql/servlet/AbstractGraphQLHttpServletSpec.groovy index 41f81763..b84a4277 100644 --- a/src/test/groovy/graphql/servlet/AbstractGraphQLHttpServletSpec.groovy +++ b/src/test/groovy/graphql/servlet/AbstractGraphQLHttpServletSpec.groovy @@ -893,6 +893,7 @@ class AbstractGraphQLHttpServletSpec extends Specification { servlet = SimpleGraphQLHttpServlet.newBuilder(GraphQLInvocationInputFactory.newBuilder { throw new TestException() }.build()).build() + servlet.init(null) request.setPathInfo('/schema.json') @@ -992,7 +993,7 @@ class AbstractGraphQLHttpServletSpec extends Specification { def "typeInfo is serialized correctly"() { expect: - servlet.getGraphQLObjectMapper().getJacksonMapper().writeValueAsString(ExecutionStepInfo.newExecutionStepInfo().type(new GraphQLNonNull(Scalars.GraphQLString)).build()) != "{}" + servlet.getConfiguration().getObjectMapper().getJacksonMapper().writeValueAsString(ExecutionStepInfo.newExecutionStepInfo().type(new GraphQLNonNull(Scalars.GraphQLString)).build()) != "{}" } @Ignore diff --git a/src/test/groovy/graphql/servlet/TestUtils.groovy b/src/test/groovy/graphql/servlet/TestUtils.groovy index f3a4df5a..3c04e421 100644 --- a/src/test/groovy/graphql/servlet/TestUtils.groovy +++ b/src/test/groovy/graphql/servlet/TestUtils.groovy @@ -8,7 +8,9 @@ class TestUtils { static def createServlet(DataFetcher queryDataFetcher = { env -> env.arguments.arg }, DataFetcher mutationDataFetcher = { env -> env.arguments.arg }) { - return SimpleGraphQLHttpServlet.newBuilder(createGraphQlSchema(queryDataFetcher, mutationDataFetcher)).build() + GraphQLHttpServlet servlet = GraphQLHttpServlet.with(createGraphQlSchema(queryDataFetcher, mutationDataFetcher)) + servlet.init(null) + return servlet } static def createGraphQlSchema(DataFetcher queryDataFetcher = { env -> env.arguments.arg }, From 16c3ac4930d48f4f4679d7e0e228798a6df2178b Mon Sep 17 00:00:00 2001 From: Michiel Oliemans Date: Thu, 8 Nov 2018 20:14:32 +0100 Subject: [PATCH 3/4] Bumped version to 7.0.0 because of breaking changes in graphql-java --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index baa679d7..2aab8daa 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -version = 6.2.1-SNAPSHOT +version = 7.0.0-SNAPSHOT group = com.graphql-java-kickstart LIB_GRAPHQL_JAVA_VER = 11.0 From 4ab1a96ba1ee7429d6d1224e8d97dc12a9846750 Mon Sep 17 00:00:00 2001 From: Michiel Oliemans Date: Thu, 8 Nov 2018 20:18:15 +0100 Subject: [PATCH 4/4] Upgraded jackson to 2.9.7 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 2aab8daa..065725ec 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ version = 7.0.0-SNAPSHOT group = com.graphql-java-kickstart LIB_GRAPHQL_JAVA_VER = 11.0 -LIB_JACKSON_VER = 2.8.11 +LIB_JACKSON_VER = 2.9.7