com.oembedler.moon.graphql.boot.GraphQLServerController.java Source code

Java tutorial

Introduction

Here is the source code for com.oembedler.moon.graphql.boot.GraphQLServerController.java

Source

/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2016 oEmbedler Inc. and Contributors
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 *  documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
 *  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
 *  persons to whom the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
package com.oembedler.moon.graphql.boot;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.oembedler.moon.graphql.engine.GraphQLSchemaHolder;
import com.oembedler.moon.graphql.engine.execute.GraphQLQueryExecutor;
import graphql.ExecutionResult;
import graphql.ExecutionResultImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author <a href="mailto:java.lang.RuntimeException@gmail.com">oEmbedler Inc.</a>
 */
@RestController
@RequestMapping("${graphql.server.mapping:/graphql}")
public class GraphQLServerController {

    private static final Logger LOGGER = LoggerFactory.getLogger(GraphQLServerController.class);

    public static final String DEFAULT_QUERY_KEY = "query";
    public static final String DEFAULT_VARIABLES_KEY = "variables";
    public static final String DEFAULT_OPERATION_NAME_KEY = "operationName";
    public static final String DEFAULT_DATA_KEY = "data";
    public static final String DEFAULT_FILENAME_UPLOAD_KEY = "file";
    public static final String DEFAULT_ERRORS_KEY = "errors";
    public static final String HEADER_SCHEMA_NAME = "graphql-schema";

    // ---

    @Autowired
    private GraphQLProperties graphQLProperties;
    @Autowired
    private GraphQLSchemaLocator graphQLSchemaLocator;

    private ObjectMapper objectMapper = new ObjectMapper();

    // ---

    @RequestMapping(method = RequestMethod.GET)
    public ResponseEntity<Map<String, Object>> getJson(@RequestParam(DEFAULT_QUERY_KEY) String query,
            @RequestParam(value = DEFAULT_VARIABLES_KEY, required = false) String variables,
            @RequestParam(value = DEFAULT_OPERATION_NAME_KEY, required = false) String operationName,
            @RequestHeader(value = HEADER_SCHEMA_NAME, required = false) String graphQLSchemaName,
            HttpServletRequest httpServletRequest) throws IOException {

        final GraphQLContext graphQLContext = new GraphQLContext();
        graphQLContext.setHttpRequest(httpServletRequest);

        final Map<String, Object> result = evaluateAndBuildResponseMap(query, operationName, graphQLContext,
                decodeIntoMap(variables), graphQLSchemaName);
        return ResponseEntity.ok(result);
    }

    @RequestMapping(method = RequestMethod.POST, consumes = "application/graphql")
    public ResponseEntity<Map<String, Object>> postGraphQL(@RequestBody String query,
            @RequestParam(value = DEFAULT_OPERATION_NAME_KEY, required = false) String operationName,
            @RequestHeader(value = HEADER_SCHEMA_NAME, required = false) String graphQLSchemaName,
            HttpServletRequest httpServletRequest) {

        final GraphQLContext graphQLContext = new GraphQLContext();
        graphQLContext.setHttpRequest(httpServletRequest);

        final Map<String, Object> result = evaluateAndBuildResponseMap(query, operationName, graphQLContext,
                new HashMap<>(), graphQLSchemaName);
        return ResponseEntity.ok(result);
    }

    @RequestMapping(method = RequestMethod.POST, consumes = "application/json")
    public ResponseEntity<Map<String, Object>> postJson(@RequestBody Map<String, Object> body,
            @RequestHeader(value = HEADER_SCHEMA_NAME, required = false) String graphQLSchemaName,
            HttpServletRequest httpServletRequest) {

        final String query = (String) body.get(getQueryKey());
        final String operationName = (String) body.get(DEFAULT_OPERATION_NAME_KEY);

        Map<String, Object> variables = null;
        Object variablesObject = body.get(getVariablesKey());
        if (variablesObject != null && variablesObject instanceof Map)
            variables = (Map<String, Object>) variablesObject;

        final GraphQLContext graphQLContext = new GraphQLContext();
        graphQLContext.setHttpRequest(httpServletRequest);

        final Map<String, Object> result = evaluateAndBuildResponseMap(query, operationName, graphQLContext,
                variables, graphQLSchemaName);

        return ResponseEntity.ok(result);
    }

    @RequestMapping(method = RequestMethod.POST, consumes = "multipart/form-data")
    public ResponseEntity<Map<String, Object>> uploadFile(
            @RequestParam(DEFAULT_FILENAME_UPLOAD_KEY) MultipartFile file,
            @RequestParam(DEFAULT_QUERY_KEY) String query,
            @RequestParam(value = DEFAULT_VARIABLES_KEY, required = false) String variables,
            @RequestParam(value = DEFAULT_OPERATION_NAME_KEY, required = false) String operationName,
            @RequestHeader(value = HEADER_SCHEMA_NAME, required = false) String graphQLSchemaName,
            HttpServletRequest httpServletRequest) throws IOException {

        final GraphQLContext graphQLContext = new GraphQLContext();
        graphQLContext.setUploadedFile(file);
        graphQLContext.setHttpRequest(httpServletRequest);

        final Map<String, Object> result = evaluateAndBuildResponseMap(query, operationName, graphQLContext,
                decodeIntoMap(variables), graphQLSchemaName);
        return ResponseEntity.ok(result);
    }

    @RequestMapping(method = RequestMethod.POST, consumes = "application/x-www-form-urlencoded")
    public ResponseEntity<Map<String, Object>> uploadSmallFile(@RequestParam(DEFAULT_QUERY_KEY) String query,
            @RequestParam(value = DEFAULT_VARIABLES_KEY, required = false) String variables,
            @RequestParam(value = DEFAULT_OPERATION_NAME_KEY, required = false) String operationName,
            @RequestHeader(value = HEADER_SCHEMA_NAME, required = false) String graphQLSchemaName,
            HttpServletRequest httpServletRequest) throws IOException {

        final GraphQLContext graphQLContext = new GraphQLContext();
        graphQLContext.setHttpRequest(httpServletRequest);

        final Map<String, Object> result = evaluateAndBuildResponseMap(query, operationName, graphQLContext,
                decodeIntoMap(variables), graphQLSchemaName);
        return ResponseEntity.ok(result);
    }

    private Map<String, Object> decodeIntoMap(final String variablesParam) throws IOException {
        return objectMapper.readValue(variablesParam, Map.class);
    }

    private Map<String, Object> evaluateAndBuildResponseMap(final String query, final String operationName,
            final GraphQLContext graphQLContext, final Map<String, Object> variables,
            final String graphQLSchemaName) {
        final Map<String, Object> result = new LinkedHashMap<>();
        final GraphQLSchemaHolder graphQLSchemaHolder = getGraphQLSchemaContainer(graphQLSchemaName);
        final ExecutionResult executionResult = evaluate(query, operationName, graphQLContext, variables,
                graphQLSchemaHolder);

        if (executionResult.getErrors().size() > 0) {
            result.put(DEFAULT_ERRORS_KEY, executionResult.getErrors());
            LOGGER.error("Errors: {}", executionResult.getErrors());
        }

        result.put(DEFAULT_DATA_KEY, executionResult.getData());
        return result;
    }

    private ExecutionResult evaluate(final String query, final String operationName,
            final GraphQLContext graphQLContext, final Map<String, Object> variables,
            final GraphQLSchemaHolder graphQLSchemaHolder) {
        ExecutionResult executionResult;

        if (graphQLSchemaHolder == null) {
            executionResult = new ExecutionResultImpl(Lists.newArrayList(new ErrorGraphQLSchemaUndefined()));
        } else {
            try {
                GraphQLQueryExecutor graphQLQueryExecutor = GraphQLQueryExecutor.create(graphQLSchemaHolder)
                        .query(query).context(graphQLContext);

                if (variables != null)
                    graphQLQueryExecutor.arguments(variables);

                if (StringUtils.hasText(operationName))
                    graphQLQueryExecutor.operation(operationName);

                executionResult = graphQLQueryExecutor.execute();

            } catch (Exception e) {
                LOGGER.error("Error occurred evaluating query: {}", query);
                executionResult = new ExecutionResultImpl(Lists.newArrayList(new ErrorGraphQLQueryEvaluation()));
            }
        }

        return executionResult;
    }

    private String getQueryKey() {
        return StringUtils.hasText(graphQLProperties.getServer().getQueryKey())
                ? graphQLProperties.getServer().getQueryKey()
                : DEFAULT_QUERY_KEY;
    }

    private String getVariablesKey() {
        return StringUtils.hasText(graphQLProperties.getServer().getVariablesKey())
                ? graphQLProperties.getServer().getVariablesKey()
                : DEFAULT_VARIABLES_KEY;
    }

    public GraphQLSchemaHolder getGraphQLSchemaContainer(String graphQLSchema) {
        if (StringUtils.hasText(graphQLSchema))
            return graphQLSchemaLocator.getGraphQLSchemaHolder(graphQLSchema);
        else if (graphQLSchemaLocator.getTotalNumberOfSchemas() == 1)
            return graphQLSchemaLocator.getSingleSchema();

        return null;
    }
}