Skip to content

Alternative construction #127

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
version = 6.2.1-SNAPSHOT
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
109 changes: 69 additions & 40 deletions src/main/java/graphql/servlet/AbstractGraphQLHttpServlet.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -24,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;
Expand All @@ -50,31 +50,66 @@ 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 override {@link #getConfiguration()} instead
*/
@Deprecated
protected abstract GraphQLQueryInvoker getQueryInvoker();

/**
* @deprecated override {@link #getConfiguration()} instead
*/
@Deprecated
protected abstract GraphQLInvocationInputFactory getInvocationInputFactory();

/**
* @deprecated override {@link #getConfiguration()} instead
*/
@Deprecated
protected abstract GraphQLObjectMapper getGraphQLObjectMapper();

private final List<GraphQLServletListener> listeners;
/**
* @deprecated override {@link #getConfiguration()} instead
*/
@Deprecated
protected abstract boolean isAsyncServletMode();

protected GraphQLConfiguration getConfiguration() {
return GraphQLConfiguration.with(getInvocationInputFactory())
.with(getQueryInvoker())
.with(getGraphQLObjectMapper())
.with(isAsyncServletMode())
.with(listeners)
.build();
}

private final HttpRequestHandler getHandler;
private final HttpRequestHandler postHandler;
/**
* @deprecated use {@link #getConfiguration()} instead
*/
@Deprecated
private final List<GraphQLServletListener> listeners;

private final boolean asyncServletMode;
private HttpRequestHandler getHandler;
private HttpRequestHandler postHandler;

public AbstractGraphQLHttpServlet() {
this(null, false);
this(null);
}

public AbstractGraphQLHttpServlet(List<GraphQLServletListener> listeners, boolean asyncServletMode) {
public AbstractGraphQLHttpServlet(List<GraphQLServletListener> listeners) {
this.listeners = listeners != null ? new ArrayList<>(listeners) : new ArrayList<>();
this.asyncServletMode = asyncServletMode;
}

@Override
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) {
Expand Down Expand Up @@ -106,22 +141,22 @@ public AbstractGraphQLHttpServlet(List<GraphQLServletListener> listeners, boolea
};

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())) {
String query = CharStreams.toString(request.getReader());
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<String, List<Part>> 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
if(!fileItems.containsKey(key)) {
if (!fileItems.containsKey(key)) {
continue;
}

Expand All @@ -134,28 +169,28 @@ public AbstractGraphQLHttpServlet(List<GraphQLServletListener> listeners, boolea
InputStream inputStream = asMarkableInputStream(queryItem.get().getInputStream());

final Optional<Map<String, List<String>>> variablesMap =
getFileItem(fileItems, "map").map(graphQLObjectMapper::deserializeMultipartMap);
getFileItem(fileItems, "map").map(graphQLObjectMapper::deserializeMultipartMap);

if (isBatchedQuery(inputStream)) {
List<GraphQLRequest> 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;
} else {
GraphQLRequest graphQLRequest;
if("query".equals(key)) {
if ("query".equals(key)) {
graphQLRequest = buildRequestFromQuery(inputStream, graphQLObjectMapper, fileItems);
} else {
graphQLRequest = graphQLObjectMapper.readGraphQLRequest(inputStream);
}

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;
Expand Down Expand Up @@ -190,8 +225,7 @@ private static InputStream asMarkableInputStream(InputStream inputStream) {

private GraphQLRequest buildRequestFromQuery(InputStream inputStream,
GraphQLObjectMapper graphQLObjectMapper,
Map<String, List<Part>> fileItems) throws IOException
{
Map<String, List<Part>> fileItems) throws IOException {
GraphQLRequest graphQLRequest;
String query = new String(ByteStreams.toByteArray(inputStream));

Expand All @@ -213,49 +247,48 @@ private GraphQLRequest buildRequestFromQuery(InputStream inputStream,

private void mapMultipartVariables(GraphQLRequest request,
Map<String, List<String>> variablesMap,
Map<String, List<Part>> fileItems)
{
Map<String, List<Part>> fileItems) {
Map<String, Object> 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 (asyncServletMode) {
if (configuration.isAsyncServletModeEnabled()) {
AsyncContext asyncContext = request.startAsync();
HttpServletRequest asyncRequest = (HttpServletRequest) asyncContext.getRequest();
HttpServletResponse asyncResponse = (HttpServletResponse) asyncContext.getResponse();
Expand Down Expand Up @@ -324,11 +357,7 @@ private void queryBatched(GraphQLQueryInvoker queryInvoker, GraphQLObjectMapper
}

private <R> List<R> runListeners(Function<? super GraphQLServletListener, R> action) {
if (listeners == null) {
return Collections.emptyList();
}

return listeners.stream()
return configuration.getListeners().stream()
.map(listener -> {
try {
return action.apply(listener);
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/graphql/servlet/ConfiguredGraphQLHttpServlet.java
Original file line number Diff line number Diff line change
@@ -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;
}

}
33 changes: 33 additions & 0 deletions src/main/java/graphql/servlet/DefaultGraphQLServlet.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package graphql.servlet;

import javax.servlet.ServletConfig;

public class DefaultGraphQLServlet extends AbstractGraphQLHttpServlet {

@Override
public void init(ServletConfig servletConfig) {

super.init(servletConfig);
}

@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;
}

}
Loading