Skip to content

Commit

Permalink
Merge pull request #3538 from graphql-java/21.x-pull-in-21.3-commits
Browse files Browse the repository at this point in the history
21.x pull in 21.3 commits
  • Loading branch information
dondonz committed Mar 19, 2024
2 parents ddc53be + a79bebf commit 5876cc8
Show file tree
Hide file tree
Showing 82 changed files with 3,341 additions and 553 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/invoke_test_runner.yml
Expand Up @@ -34,7 +34,7 @@ jobs:
if: github.repository == 'graphql-java/graphql-java'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: actions/setup-node@v3
with:
node-version: '14'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/master.yml
Expand Up @@ -13,7 +13,7 @@ jobs:
MAVEN_CENTRAL_PGP_KEY: ${{ secrets.MAVEN_CENTRAL_PGP_KEY }}

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: gradle/wrapper-validation-action@v1
- name: Set up JDK 11
uses: actions/setup-java@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pull_request.yml
Expand Up @@ -16,7 +16,7 @@ jobs:
buildAndTest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: gradle/wrapper-validation-action@v1
- name: Set up JDK 11
uses: actions/setup-java@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Expand Up @@ -17,7 +17,7 @@ jobs:
RELEASE_VERSION: ${{ github.event.inputs.version }}

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: gradle/wrapper-validation-action@v1
- name: Set up JDK 11
uses: actions/setup-java@v3
Expand Down
8 changes: 5 additions & 3 deletions README.md
Expand Up @@ -5,15 +5,17 @@ Discuss and ask questions in our Discussions: https://github.com/graphql-java/gr
This is a [GraphQL](https://github.com/graphql/graphql-spec) Java implementation.

[![Build](https://github.com/graphql-java/graphql-java/actions/workflows/master.yml/badge.svg)](https://github.com/graphql-java/graphql-java/actions/workflows/master.yml)
[![Latest Release](https://img.shields.io/maven-central/v/com.graphql-java/graphql-java?versionPrefix=20.)](https://maven-badges.herokuapp.com/maven-central/com.graphql-java/graphql-java/)
[![Latest Release](https://img.shields.io/maven-central/v/com.graphql-java/graphql-java?versionPrefix=21.)](https://maven-badges.herokuapp.com/maven-central/com.graphql-java/graphql-java/)
[![Latest Snapshot](https://img.shields.io/maven-central/v/com.graphql-java/graphql-java?label=maven-central%20snapshot&versionPrefix=0)](https://maven-badges.herokuapp.com/maven-central/com.graphql-java/graphql-java/)
[![MIT licensed](https://img.shields.io/badge/license-MIT-green)](https://github.com/graphql-java/graphql-java/blob/master/LICENSE.md)

### Documentation

We have a tutorial for beginners: [Getting started with GraphQL Java and Spring Boot](https://www.graphql-java.com/tutorials/getting-started-with-spring-boot/)
See our tutorial for beginners: [Getting started with GraphQL Java and Spring Boot](https://www.graphql-java.com/tutorials/getting-started-with-spring-boot/)

For details how to use `graphql-java` please look at the documentation: https://www.graphql-java.com/documentation/getting-started
For further details, please see the documentation: https://www.graphql-java.com/documentation/getting-started

If you're looking to learn more, we (the maintainers) have written a book! [GraphQL with Java and Spring](https://leanpub.com/graphql-java) includes everything you need to know to build a production ready GraphQL service. The book is available on [Leanpub](https://leanpub.com/graphql-java) and [Amazon](https://www.amazon.com/GraphQL-Java-Spring-Andreas-Marek-ebook/dp/B0C96ZYWPF/).

Please take a look at our [list of releases](https://github.com/graphql-java/graphql-java/releases) if you want to learn more about new releases and the changelog.

Expand Down
8 changes: 1 addition & 7 deletions SECURITY.md
Expand Up @@ -2,13 +2,7 @@

## Supported Versions

We support the latest release with security updates.

We retain the discretion to backport security updates, this is decided on a case-by-case basis.

| Version | Supported |
| ------- | ------------------ |
| v20.x | :white_check_mark: |
As stated in our [Release Policy](https://www.graphql-java.com/blog/release-policy/), we will backport critical bugfixes and security fixes for versions dating back 18 months. These fixes will be backported depending on severity and demand.

## Reporting a Vulnerability

Expand Down
70 changes: 44 additions & 26 deletions build.gradle
Expand Up @@ -20,37 +20,52 @@ java {
}
}

def makeDevelopmentVersion(parts) {
def version = String.join("-", parts)
println "created development version: $version"
return version
}

def getDevelopmentVersion() {
def dateTime = new SimpleDateFormat('yyyy-MM-dd\'T\'HH-mm-ss').format(new Date())
def gitCheckOutput = new StringBuilder()
def gitCheckError = new StringBuilder()
def gitCheck = ["git", "rev-parse", "--is-inside-work-tree"].execute()
def gitCheck = ["git", "-C", projectDir.toString(), "rev-parse", "--is-inside-work-tree"].execute()
gitCheck.waitForProcessOutput(gitCheckOutput, gitCheckError)
def isGit = gitCheckOutput.toString().trim()
if (isGit != "true") {
def version = "0.0.0-" + new SimpleDateFormat('yyyy-MM-dd\'T\'HH-mm-ss').format(new Date()) + "-no-git"
println "created development version: $version"
return version
return makeDevelopmentVersion(["0.0.0", dateTime, "no-git"])
}

def gitHashOutput = new StringBuilder()
def gitHashError = new StringBuilder()
def gitShortHash = ["git", "-C", projectDir.toString(), "rev-parse", "--short", "HEAD"].execute()
gitShortHash.waitForProcessOutput(gitHashOutput, gitHashError)
def gitHash = gitHashOutput.toString().trim()
if (gitHash.isEmpty()) {
println "git hash is empty: error: ${error.toString()}"
throw new IllegalStateException("git hash could not be determined")
def isCi = Boolean.parseBoolean(System.env.CI)
if (isCi) {
def gitHashOutput = new StringBuilder()
def gitHashError = new StringBuilder()
def gitShortHash = ["git", "-C", projectDir.toString(), "rev-parse", "--short", "HEAD"].execute()
gitShortHash.waitForProcessOutput(gitHashOutput, gitHashError)
def gitHash = gitHashOutput.toString().trim()
if (gitHash.isEmpty()) {
println "git hash is empty: error: ${gitHashError.toString()}"
throw new IllegalStateException("git hash could not be determined")
}

return makeDevelopmentVersion(["0.0.0", dateTime, gitHash])
}
def version = "0.0.0-" + new SimpleDateFormat('yyyy-MM-dd\'T\'HH-mm-ss').format(new Date()) + "-" + gitHash
println "created development version: $version"
version

def gitRevParseOutput = new StringBuilder()
def gitRevParseError = new StringBuilder()
def gitRevParse = ["git", "-C", projectDir.toString(), "rev-parse", "--abbrev-ref", "HEAD"].execute()
gitRevParse.waitForProcessOutput(gitRevParseOutput, gitRevParseError)
def branchName = gitRevParseOutput.toString().trim()

return makeDevelopmentVersion(["0.0.0", branchName, "SNAPSHOT"])
}

def reactiveStreamsVersion = '1.0.3'
def slf4jVersion = '2.0.7'
def releaseVersion = System.env.RELEASE_VERSION
def antlrVersion = '4.11.1' // https://mvnrepository.com/artifact/org.antlr/antlr4-runtime
def guavaVersion = '32.1.1-jre'
def guavaVersion = '32.1.2-jre'
version = releaseVersion ? releaseVersion : getDevelopmentVersion()
group = 'com.graphql-java'

Expand Down Expand Up @@ -87,17 +102,17 @@ dependencies {
compileOnly 'org.jetbrains:annotations:24.0.1'
implementation 'org.antlr:antlr4-runtime:' + antlrVersion
implementation 'org.slf4j:slf4j-api:' + slf4jVersion
api 'com.graphql-java:java-dataloader:3.2.0'
api 'com.graphql-java:java-dataloader:3.2.1'
api 'org.reactivestreams:reactive-streams:' + reactiveStreamsVersion
antlr 'org.antlr:antlr4:' + antlrVersion
implementation 'com.google.guava:guava:' + guavaVersion
testImplementation group: 'junit', name: 'junit', version: '4.13.2'
testImplementation 'org.spockframework:spock-core:2.0-groovy-3.0'
testImplementation 'org.codehaus.groovy:groovy:3.0.18'
testImplementation 'org.codehaus.groovy:groovy-json:3.0.18'
testImplementation 'org.codehaus.groovy:groovy:3.0.19'
testImplementation 'org.codehaus.groovy:groovy-json:3.0.19'
testImplementation 'com.google.code.gson:gson:2.10.1'
testImplementation 'org.eclipse.jetty:jetty-server:11.0.15'
testImplementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2'
testImplementation 'com.fasterxml.jackson.core:jackson-databind:2.15.3'
testImplementation 'org.slf4j:slf4j-simple:' + slf4jVersion
testImplementation 'org.awaitility:awaitility-groovy:4.2.0'
testImplementation 'com.github.javafaker:javafaker:1.0.2'
Expand All @@ -107,10 +122,10 @@ dependencies {

testImplementation 'org.testng:testng:7.8.0' // use for reactive streams test inheritance

testImplementation 'org.openjdk.jmh:jmh-core:1.36'
testAnnotationProcessor 'org.openjdk.jmh:jmh-generator-annprocess:1.36'
jmh 'org.openjdk.jmh:jmh-core:1.36'
jmh 'org.openjdk.jmh:jmh-generator-annprocess:1.36'
testImplementation 'org.openjdk.jmh:jmh-core:1.37'
testAnnotationProcessor 'org.openjdk.jmh:jmh-generator-annprocess:1.37'
jmh 'org.openjdk.jmh:jmh-core:1.37'
jmh 'org.openjdk.jmh:jmh-generator-annprocess:1.37'
}

shadowJar {
Expand Down Expand Up @@ -155,7 +170,7 @@ shadowJar {
bnd('''
-exportcontents: graphql.*
-removeheaders: Private-Package
Import-Package: !com.google.*,!org.checkerframework.*,!javax.annotation.*,!graphql.com.google.*,!org.antlr.*,!graphql.org.antlr.*,!sun.misc.*,*
Import-Package: !android.os.*,!com.google.*,!org.checkerframework.*,!javax.annotation.*,!graphql.com.google.*,!org.antlr.*,!graphql.org.antlr.*,!sun.misc.*,*
''')
}

Expand Down Expand Up @@ -203,7 +218,10 @@ generateGrammarSource {
arguments += ["-visitor"]
outputDirectory = file("${project.buildDir}/generated-src/antlr/main/graphql/parser/antlr")
}
generateGrammarSource.inputs.dir('src/main/antlr')
generateGrammarSource.inputs
.dir('src/main/antlr')
.withPropertyName('sourceDir')
.withPathSensitivity(PathSensitivity.RELATIVE)


task sourcesJar(type: Jar) {
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/graphql/Directives.java
Expand Up @@ -15,6 +15,7 @@
import static graphql.introspection.Introspection.DirectiveLocation.FRAGMENT_SPREAD;
import static graphql.introspection.Introspection.DirectiveLocation.INLINE_FRAGMENT;
import static graphql.introspection.Introspection.DirectiveLocation.INPUT_FIELD_DEFINITION;
import static graphql.introspection.Introspection.DirectiveLocation.INPUT_OBJECT;
import static graphql.introspection.Introspection.DirectiveLocation.SCALAR;
import static graphql.language.DirectiveLocation.newDirectiveLocation;
import static graphql.language.InputValueDefinition.newInputValueDefinition;
Expand All @@ -31,10 +32,13 @@ public class Directives {

private static final String SPECIFIED_BY = "specifiedBy";
private static final String DEPRECATED = "deprecated";
private static final String ONE_OF = "oneOf";

public static final String NO_LONGER_SUPPORTED = "No longer supported";
public static final DirectiveDefinition DEPRECATED_DIRECTIVE_DEFINITION;
public static final DirectiveDefinition SPECIFIED_BY_DIRECTIVE_DEFINITION;
@ExperimentalApi
public static final DirectiveDefinition ONE_OF_DIRECTIVE_DEFINITION;


static {
Expand Down Expand Up @@ -65,6 +69,12 @@ public class Directives {
.type(newNonNullType(newTypeName().name("String").build()).build())
.build())
.build();

ONE_OF_DIRECTIVE_DEFINITION = DirectiveDefinition.newDirectiveDefinition()
.name(ONE_OF)
.directiveLocation(newDirectiveLocation().name(INPUT_OBJECT.name()).build())
.description(createDescription("Indicates an Input Object is a OneOf Input Object."))
.build();
}

public static final GraphQLDirective IncludeDirective = GraphQLDirective.newDirective()
Expand Down Expand Up @@ -119,6 +129,14 @@ public class Directives {
.definition(SPECIFIED_BY_DIRECTIVE_DEFINITION)
.build();

@ExperimentalApi
public static final GraphQLDirective OneOfDirective = GraphQLDirective.newDirective()
.name(ONE_OF)
.description("Indicates an Input Object is a OneOf Input Object.")
.validLocations(INPUT_OBJECT)
.definition(ONE_OF_DIRECTIVE_DEFINITION)
.build();

private static Description createDescription(String s) {
return new Description(s, null, false);
}
Expand Down
51 changes: 27 additions & 24 deletions src/main/java/graphql/GraphQL.java
@@ -1,6 +1,7 @@
package graphql;

import graphql.execution.AbortExecutionException;
import graphql.execution.Async;
import graphql.execution.AsyncExecutionStrategy;
import graphql.execution.AsyncSerialExecutionStrategy;
import graphql.execution.DataFetcherExceptionHandler;
Expand Down Expand Up @@ -421,31 +422,33 @@ public CompletableFuture<ExecutionResult> executeAsync(ExecutionInput executionI
if (logNotSafe.isDebugEnabled()) {
logNotSafe.debug("Executing request. operation name: '{}'. query: '{}'. variables '{}'", executionInput.getOperationName(), executionInput.getQuery(), executionInput.getVariables());
}
executionInput = ensureInputHasId(executionInput);
ExecutionInput executionInputWithId = ensureInputHasId(executionInput);

InstrumentationState instrumentationState = instrumentation.createState(new InstrumentationCreateStateParameters(this.graphQLSchema, executionInput));
try {
InstrumentationExecutionParameters inputInstrumentationParameters = new InstrumentationExecutionParameters(executionInput, this.graphQLSchema, instrumentationState);
executionInput = instrumentation.instrumentExecutionInput(executionInput, inputInstrumentationParameters, instrumentationState);

CompletableFuture<ExecutionResult> beginExecutionCF = new CompletableFuture<>();
InstrumentationExecutionParameters instrumentationParameters = new InstrumentationExecutionParameters(executionInput, this.graphQLSchema, instrumentationState);
InstrumentationContext<ExecutionResult> executionInstrumentation = nonNullCtx(instrumentation.beginExecution(instrumentationParameters, instrumentationState));
executionInstrumentation.onDispatched(beginExecutionCF);

GraphQLSchema graphQLSchema = instrumentation.instrumentSchema(this.graphQLSchema, instrumentationParameters, instrumentationState);

CompletableFuture<ExecutionResult> executionResult = parseValidateAndExecute(executionInput, graphQLSchema, instrumentationState);
//
// finish up instrumentation
executionResult = executionResult.whenComplete(completeInstrumentationCtxCF(executionInstrumentation, beginExecutionCF));
//
// allow instrumentation to tweak the result
executionResult = executionResult.thenCompose(result -> instrumentation.instrumentExecutionResult(result, instrumentationParameters, instrumentationState));
return executionResult;
} catch (AbortExecutionException abortException) {
return handleAbortException(executionInput, instrumentationState, abortException);
}
CompletableFuture<InstrumentationState> instrumentationStateCF = instrumentation.createStateAsync(new InstrumentationCreateStateParameters(this.graphQLSchema, executionInput));
return Async.orNullCompletedFuture(instrumentationStateCF).thenCompose(instrumentationState -> {
try {
InstrumentationExecutionParameters inputInstrumentationParameters = new InstrumentationExecutionParameters(executionInputWithId, this.graphQLSchema, instrumentationState);
ExecutionInput instrumentedExecutionInput = instrumentation.instrumentExecutionInput(executionInputWithId, inputInstrumentationParameters, instrumentationState);

CompletableFuture<ExecutionResult> beginExecutionCF = new CompletableFuture<>();
InstrumentationExecutionParameters instrumentationParameters = new InstrumentationExecutionParameters(instrumentedExecutionInput, this.graphQLSchema, instrumentationState);
InstrumentationContext<ExecutionResult> executionInstrumentation = nonNullCtx(instrumentation.beginExecution(instrumentationParameters, instrumentationState));
executionInstrumentation.onDispatched(beginExecutionCF);

GraphQLSchema graphQLSchema = instrumentation.instrumentSchema(this.graphQLSchema, instrumentationParameters, instrumentationState);

CompletableFuture<ExecutionResult> executionResult = parseValidateAndExecute(instrumentedExecutionInput, graphQLSchema, instrumentationState);
//
// finish up instrumentation
executionResult = executionResult.whenComplete(completeInstrumentationCtxCF(executionInstrumentation, beginExecutionCF));
//
// allow instrumentation to tweak the result
executionResult = executionResult.thenCompose(result -> instrumentation.instrumentExecutionResult(result, instrumentationParameters, instrumentationState));
return executionResult;
} catch (AbortExecutionException abortException) {
return handleAbortException(executionInput, instrumentationState, abortException);
}
});
}

private CompletableFuture<ExecutionResult> handleAbortException(ExecutionInput executionInput, InstrumentationState instrumentationState, AbortExecutionException abortException) {
Expand Down
13 changes: 13 additions & 0 deletions src/main/java/graphql/execution/Async.java
Expand Up @@ -2,6 +2,8 @@

import graphql.Assert;
import graphql.Internal;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.Collection;
Expand Down Expand Up @@ -207,4 +209,15 @@ public static <T> CompletableFuture<T> exceptionallyCompletedFuture(Throwable ex
return result;
}

/**
* If the passed in CompletableFuture is null then it creates a CompletableFuture that resolves to null
*
* @param completableFuture the CF to use
* @param <T> for two
*
* @return the completableFuture if it's not null or one that always resoles to null
*/
public static <T> @NotNull CompletableFuture<T> orNullCompletedFuture(@Nullable CompletableFuture<T> completableFuture) {
return completableFuture != null ? completableFuture : CompletableFuture.completedFuture(null);
}
}

0 comments on commit 5876cc8

Please sign in to comment.