GithubHelp home page GithubHelp logo

netflix / dgs-framework Goto Github PK

View Code? Open in Web Editor NEW
3.0K 230.0 284.0 6.51 MB

GraphQL for Java with Spring Boot made easy.

Home Page: https://netflix.github.io/dgs

License: Apache License 2.0

Kotlin 82.32% Java 15.99% HTML 0.78% JavaScript 0.16% TypeScript 0.18% Makefile 0.07% Python 0.49%
graphql java spring-boot dgs graphql-java

dgs-framework's Introduction

dgs-framework

CI GitHub release Apache 2.0

Documentation can be found here, including a getting started guide.

The DGS Framework (Domain Graph Service) is a GraphQL server framework for Spring Boot, developed by Netflix.

Features include:

  • Annotation based Spring Boot programming model
  • Test framework for writing query tests as unit tests
  • Gradle Code Generation plugin to create types from schema
  • Easy integration with GraphQL Federation
  • Integration with Spring Security
  • GraphQL subscriptions (WebSockets and SSE)
  • File uploads
  • Error handling
  • Many extension points

Getting Started

Follow the getting started guide!

Contributing, asking questions and reporting issues.

Please read our contributor guide!

dgs-framework's People

Contributors

amondnet avatar antholeole avatar ayushchaubey avatar berngp avatar callumforrester avatar danielthomas avatar dependabot[bot] avatar emily avatar gradle-update-robot avatar hantsy avatar heo-d avatar jord1e avatar jvalde avatar kailyak avatar kilink avatar lucatk avatar npwork avatar onobc avatar paulbakker avatar prokop7 avatar richardcresswell avatar samhon avatar sbilello avatar setchy avatar springmonster avatar srinivasankavitha avatar thejc avatar tinnou avatar wlsdnjs829 avatar xuchuanqiu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dgs-framework's Issues

Move default values to default properties file

We currently have a few configuration properties that are using SpEL property syntax with default values embedded in the SpEL. Rather than have the default spread about the codebase, lets create a dgs.default.properties for these values. An EnvironmentPostProcessor can load these up into a property source w/ least priority so that they are only used if not user-specified.

Here are the current locations that need updating:

Gotchas

  • We currently are specifying default values in our additional-spring-configuration-metadata.json. If we leave them in here then they data will be in 2 places and could get out of sync. If we remove them then IDE auto-completion will not show the default value
  • Once we add @ConfigurationProperties we will need to resist the urge to use @DefaultValue in the config props as that will override the default properties.

Original motivation from @berngp

Need a fix in documentation

First of all, what an awesome project. I've just started to play with this framework and I hope to use it in production, where I work.

So, while following the getting started guide, I saw a missing dependency that wasn't mentioned in the docs, which was com.apollographql.federation:federation-graphql-java-support:0.6.1. Also to mention that this was only available at jcenter so I had to add that as one of the gradle repositories in the following manner:

repositories {
	mavenCentral()
	jcenter()
}

Also the documentation said to add the dependency in the following manner for gradle:

dependencies {
    api "com.netflix.graphql.dgs:graphql-dgs-spring-boot-starter:latest.release"
}

In fact, I had to do the following for it work

dependencies {
    implementation "com.netflix.graphql.dgs:graphql-dgs-spring-boot-starter:latest.release"
}

I'm overall new to the Java ecosystem so there might be something that I'm missing. Thank you!

Make extensions field nullable

Hello,

I used the graphql client part of this library to consume a graphql API. When I received an error with this format :

{
  "data": {
    "result": null
  },
  "errors": [
    {
      "message": "some error message",
      "path": [
        "result"
      ],
      "locations": [
        {
          "column": 22,
          "line": 1
        }
      ]
    }
  ]
}

I got the following error message :

Instantiation of [simple type, class com.netflix.graphql.dgs.client.GraphQLError] value failed for JSON property extensions due to missing (therefore NULL) value for creator parameter extensions which is a non-nullable type

We got this error when extensions field is not present, I assume it's not always the case. Is that possible to make it nullable ?

Best regards,

Passing list of Input object does not serialize correctly

I have the following query request in my schema. As you can see it has orderBy argument that is list of input objects:

type Query {
    items(orderBy: [OrderByInput], first: Int = 10, offset: Int = 0) : ItemConnection!
}

input OrderByInput {
    field: String
    sortOrder: SortOrder
}

enum SortOrder {
    Asc
    Desc
}

My data fetcher procedure is:

@DgsComponent
class ItemDataFetcher {

// ...

    @DgsData(parentType = "Query", field = "items")
    fun items(
        @InputArgument("orderBy") orderBy: List<OrderByInput>?,
        @InputArgument("first") first: Int?,
        @InputArgument("offset") offset: Int?,
        dfe: DgsDataFetchingEnvironment
    ): ItemConnection {

        orderBy?.let {
            it.forEach {
                log.info("Item class: {}", it.javaClass)
            }
        }

        return ItemConnection(
            totalCount = data.size.toLong(),
            nodes = data
        )

    }

// ...
}

When I run the following query, I get an exception, see below

query {
	items(
    orderBy: [
      {
        field: "id"
        sortOrder: Asc
      },
      {
        field: "name"
        sortOrder: Desc
      }
    ]
  )
  {
	nodes {
	  id
  	  name
    }
  }
}
2021-02-16 22:16:31.348  INFO 2883 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms
2021-02-16 22:16:31.469 ERROR 2883 --- [nio-8080-exec-1] g.d.e.DefaultDataFetcherExceptionHandler : Exception while executing data fetcher for /items: class java.util.LinkedHashMap cannot be cast to class example.OrderByInput (java.util.LinkedHashMap is in module java.base of loader 'bootstrap'; example.OrderByInput is in unnamed module of loader 'app')

java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class example.OrderByInput (java.util.LinkedHashMap is in module java.base of loader 'bootstrap'; example.OrderByInput is in unnamed module of loader 'app')
	at example.ItemDataFetcher.items(ItemDataFetcher.kt:42) ~[main/:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
	at com.netflix.graphql.dgs.internal.DgsSchemaProvider.invokeDataFetcher(DgsSchemaProvider.kt:283) ~[graphql-dgs-3.4.1.jar:3.4.1]
	at com.netflix.graphql.dgs.internal.DgsSchemaProvider.access$invokeDataFetcher(DgsSchemaProvider.kt:54) ~[graphql-dgs-3.4.1.jar:3.4.1]
	at com.netflix.graphql.dgs.internal.DgsSchemaProvider$createBasicDataFetcher$1.get(DgsSchemaProvider.kt:220) ~[graphql-dgs-3.4.1.jar:3.4.1]
	at graphql.execution.ExecutionStrategy.fetchField(ExecutionStrategy.java:270) ~[graphql-java-16.2.jar:na]
	at graphql.execution.ExecutionStrategy.resolveFieldWithInfo(ExecutionStrategy.java:203) ~[graphql-java-16.2.jar:na]
	at graphql.execution.AsyncExecutionStrategy.execute(AsyncExecutionStrategy.java:60) ~[graphql-java-16.2.jar:na]
	at graphql.execution.Execution.executeOperation(Execution.java:165) ~[graphql-java-16.2.jar:na]
	at graphql.execution.Execution.execute(Execution.java:104) ~[graphql-java-16.2.jar:na]
	at graphql.GraphQL.execute(GraphQL.java:557) ~[graphql-java-16.2.jar:na]
	at graphql.GraphQL.parseValidateAndExecute(GraphQL.java:482) ~[graphql-java-16.2.jar:na]
	at graphql.GraphQL.executeAsync(GraphQL.java:446) ~[graphql-java-16.2.jar:na]
	at graphql.GraphQL.execute(GraphQL.java:377) ~[graphql-java-16.2.jar:na]
	at com.netflix.graphql.dgs.internal.DefaultDgsQueryExecutor.execute(DefaultDgsQueryExecutor.kt:103) ~[graphql-dgs-3.4.1.jar:3.4.1]
	at com.netflix.graphql.dgs.internal.DefaultDgsQueryExecutor.execute(DefaultDgsQueryExecutor.kt:74) ~[graphql-dgs-3.4.1.jar:3.4.1]
	at com.netflix.graphql.dgs.mvc.DgsRestController$graphql$executionResult$1.invoke(DgsRestController.kt:140) ~[graphql-dgs-spring-webmvc-3.4.1.jar:3.4.1]
	at com.netflix.graphql.dgs.mvc.DgsRestController$graphql$executionResult$1.invoke(DgsRestController.kt:67) ~[graphql-dgs-spring-webmvc-3.4.1.jar:3.4.1]
	at com.netflix.graphql.dgs.internal.utils.TimeTracer.logTime(TimeTracer.kt:24) ~[graphql-dgs-3.4.1.jar:3.4.1]
	at com.netflix.graphql.dgs.mvc.DgsRestController.graphql(DgsRestController.kt:140) ~[graphql-dgs-spring-webmvc-3.4.1.jar:3.4.1]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1060) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:962) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:652) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:888) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]


And the reason is instead of List<OrderByInput> I get ArrayList<LinkedHashMap>:

Снимок экрана 2021-02-16 в 22 21 02

Is it a bug or am I doing something wrong?

To reproduce this you can get the following project: (https://github.com/maxixcom/dgs-test)

BatchLoaderWithContext causes java.lang.NoSuchMethodError

The file ExampleLoaderWithContext.java from example.

errors:
java.lang.NoSuchMethodError: 'void kotlin.jvm.internal.FunctionReferenceImpl.(int, java.lang.Object, java.lang.Class, java.lang.String, java.lang.String, int)'
at com.netflix.graphql.dgs.internal.DgsDataLoaderProvider$createDataLoader$options$1.(DgsDataLoaderProvider.kt) ~[graphql-dgs-3.7.1.jar:3.7.1]
at com.netflix.graphql.dgs.internal.DgsDataLoaderProvider.createDataLoader(DgsDataLoaderProvider.kt:145) ~[graphql-dgs-3.7.1.jar:3.7.1]
at com.netflix.graphql.dgs.internal.DgsDataLoaderProvider.buildRegistryWithContextSupplier(DgsDataLoaderProvider.kt:54) ~[graphql-dgs-3.7.1.jar:3.7.1]
at com.netflix.graphql.dgs.internal.DefaultDgsQueryExecutor.execute(DefaultDgsQueryExecutor.kt:100) ~[graphql-dgs-3.7.1.jar:3.7.1]
at com.netflix.graphql.dgs.internal.DefaultDgsQueryExecutor.execute(DefaultDgsQueryExecutor.kt:78) ~[graphql-dgs-3.7.1.jar:3.7.1].

am i missing something?

[CodeGen] Unable to supply arguments for fields in projection nor supply aliases

Inspecting the generated code, looks like there is no ability to supply arguments to fields in projections nor is there ability to supply aliases either.
https://graphql.org/learn/queries/#arguments
https://graphql.org/learn/queries/#aliases

This behavior can be reproduced by tweaking the example from the Getting started guide:
type Votes { starRating(min: Float): Float nrOfVotes: Int }
After generating for this example, there is no way to set min on the field starRating via the TicksEdgesNodeRouteVotesProjection.java methods.

Runtime class not found exception with 3.5.1 version

I've created the new application from start.spring.io with the following dependencies plus DGS 3.5.1:

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-data-mongodb")
    implementation("org.springframework.boot:spring-boot-starter-security")
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    implementation("org.springframework.cloud:spring-cloud-starter-config")
    implementation("org.springframework.cloud:spring-cloud-starter-netflix-eureka-client")
    annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testImplementation("org.springframework.security:spring-security-test")

    // DGS
    implementation("com.netflix.graphql.dgs:graphql-dgs-spring-boot-starter:3.5.1")
}
Full build.gradle.kts

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    id("org.springframework.boot") version "2.4.3"
    id("io.spring.dependency-management") version "1.0.11.RELEASE"
    kotlin("jvm") version "1.4.30"
    kotlin("plugin.spring") version "1.4.30"
}

group = "studio.buket.apps.bazar"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_11

configurations {
    compileOnly {
        extendsFrom(configurations.annotationProcessor.get())
    }
}

repositories {
    mavenCentral()
    jcenter()
}

extra["springCloudVersion"] = "2020.0.1"

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-data-mongodb")
    implementation("org.springframework.boot:spring-boot-starter-security")
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    implementation("org.springframework.cloud:spring-cloud-starter-config")
    implementation("org.springframework.cloud:spring-cloud-starter-netflix-eureka-client")
    annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testImplementation("org.springframework.security:spring-security-test")

    // graphql
    implementation("com.netflix.graphql.dgs:graphql-dgs-spring-boot-starter:3.5.1")
//    implementation("com.netflix.graphql.dgs:graphql-dgs-spring-boot-starter:3.4.1")
}

dependencyManagement {
    imports {
        mavenBom("org.springframework.cloud:spring-cloud-dependencies:${property("springCloudVersion")}")
    }
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs = listOf("-Xjsr305=strict")
        jvmTarget = "11"
    }
}

tasks.withType<Test> {
    useJUnitPlatform()
}

And after starting the application I've got ClassNotFoundException for net.minidev.json.writer.JsonReader. As I see it comes from net.mindev:json-smart pakage as a dependency of DGS.
It's interesting if I switch back to 3.4.1 I've got no error and it seems everything starts working.

The project I use you can take here: https://github.com/maxixcom/baz-mart

And full exception is:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerAdapter' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter]: Factory method 'requestMappingHandlerAdapter' threw exception; nested exception is java.lang.NoClassDefFoundError: net/minidev/json/writer/JsonReader
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658) ~[spring-beans-5.3.4.jar:5.3.4]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:638) ~[spring-beans-5.3.4.jar:5.3.4]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1334) ~[spring-beans-5.3.4.jar:5.3.4]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177) ~[spring-beans-5.3.4.jar:5.3.4]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564) ~[spring-beans-5.3.4.jar:5.3.4]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.4.jar:5.3.4]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.4.jar:5.3.4]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.4.jar:5.3.4]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.4.jar:5.3.4]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.4.jar:5.3.4]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) ~[spring-beans-5.3.4.jar:5.3.4]
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:917) ~[spring-context-5.3.4.jar:5.3.4]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:582) ~[spring-context-5.3.4.jar:5.3.4]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144) ~[spring-boot-2.4.3.jar:2.4.3]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767) ~[spring-boot-2.4.3.jar:2.4.3]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) ~[spring-boot-2.4.3.jar:2.4.3]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426) ~[spring-boot-2.4.3.jar:2.4.3]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:326) ~[spring-boot-2.4.3.jar:2.4.3]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1311) ~[spring-boot-2.4.3.jar:2.4.3]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) ~[spring-boot-2.4.3.jar:2.4.3]
	at studio.buket.apps.bazar.bazmart.BazMartApplicationKt.main(BazMartApplication.kt:13) ~[main/:na]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter]: Factory method 'requestMappingHandlerAdapter' threw exception; nested exception is java.lang.NoClassDefFoundError: net/minidev/json/writer/JsonReader
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.3.4.jar:5.3.4]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) ~[spring-beans-5.3.4.jar:5.3.4]
	... 20 common frames omitted
Caused by: java.lang.NoClassDefFoundError: net/minidev/json/writer/JsonReader
	at com.jayway.jsonpath.spi.mapper.JsonSmartMappingProvider.<clinit>(JsonSmartMappingProvider.java:32) ~[json-path-2.4.0.jar:2.4.0]
	at com.jayway.jsonpath.internal.DefaultsImpl.<init>(DefaultsImpl.java:17) ~[json-path-2.4.0.jar:2.4.0]
	at com.jayway.jsonpath.internal.DefaultsImpl.<clinit>(DefaultsImpl.java:15) ~[json-path-2.4.0.jar:2.4.0]
	at com.jayway.jsonpath.Configuration.getEffectiveDefaults(Configuration.java:48) ~[json-path-2.4.0.jar:2.4.0]
	at com.jayway.jsonpath.Configuration.access$000(Configuration.java:34) ~[json-path-2.4.0.jar:2.4.0]
	at com.jayway.jsonpath.Configuration$ConfigurationBuilder.build(Configuration.java:229) ~[json-path-2.4.0.jar:2.4.0]
	at org.springframework.data.web.JsonProjectingMethodInterceptorFactory.<init>(JsonProjectingMethodInterceptorFactory.java:75) ~[spring-data-commons-2.4.5.jar:2.4.5]
	at org.springframework.data.web.ProjectingJackson2HttpMessageConverter.initProjectionFactory(ProjectingJackson2HttpMessageConverter.java:87) ~[spring-data-commons-2.4.5.jar:2.4.5]
	at org.springframework.data.web.ProjectingJackson2HttpMessageConverter.<init>(ProjectingJackson2HttpMessageConverter.java:72) ~[spring-data-commons-2.4.5.jar:2.4.5]
	at org.springframework.data.web.config.SpringDataWebConfiguration.extendMessageConverters(SpringDataWebConfiguration.java:169) ~[spring-data-commons-2.4.5.jar:2.4.5]
	at org.springframework.web.servlet.config.annotation.WebMvcConfigurerComposite.extendMessageConverters(WebMvcConfigurerComposite.java:144) ~[spring-webmvc-5.3.4.jar:5.3.4]
	at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration.extendMessageConverters(DelegatingWebMvcConfiguration.java:123) ~[spring-webmvc-5.3.4.jar:5.3.4]
	at org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.getMessageConverters(WebMvcConfigurationSupport.java:865) ~[spring-webmvc-5.3.4.jar:5.3.4]
	at org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.requestMappingHandlerAdapter(WebMvcConfigurationSupport.java:669) ~[spring-webmvc-5.3.4.jar:5.3.4]
	at org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration.requestMappingHandlerAdapter(WebMvcAutoConfiguration.java:369) ~[spring-boot-autoconfigure-2.4.3.jar:2.4.3]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.4.jar:5.3.4]
	... 21 common frames omitted
Caused by: java.lang.ClassNotFoundException: net.minidev.json.writer.JsonReader
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581) ~[na:na]
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178) ~[na:na]
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) ~[na:na]
	... 41 common frames omitted

Could you help me to understand how to fix the problem?

Provide access to WebRequest in DgsCustomContextBuilder

Is it possible to provide access to the original request in the DgsCustomContextBuilder?

Background:
In the company where I work, we use Apollo Federation Gateway to generate certain headers related to the client and also forward certain user-level cookies over to the Federated Services.

Generally we are able to create a custom GraphQLInvocation and get access to the WebRequest via which we can read all these details and then do things with the WebRequest such as authenticating the cookies and perform some side effects that are common for all DataFetchers.

I'm not entirely sure if this currently possible and whether such a functionality is possible.

Add ability to configure GraphQL and GraphiQL paths

Summary

As a follow on to gh-88 lets add the ability to configure the paths to the GraphQL and GraphiQL endpoints such as:

dgs.graphql.path = /graphql
dgs.graphql.graphiql.path = /graphiql

Notes

ℹ️ See the recent changes to DgsRestSchemaJsonController.kt for example path configuration.
ℹ️ A bit of care must be taken around the /graphql path change as it needs to work w/in graphiql (details)

Acceptance Criteria

JsonPath is bringing in problematic transitive libraries

We are getting ready to use DGS for our Spring Boot applications at my company and I am super excited about what you all have put together - thank you.

One concern I have is around some of the transitive library baggage that is coming along for the ride in the starter. Namely json-path, which itself imposes a messy transitive library chain along with it.

|    |    |    +--- com.jayway.jsonpath:json-path:2.5.0
|    |    |    |    +--- net.minidev:json-smart:2.3
|    |    |    |    |    \--- net.minidev:accessors-smart:1.2
|    |    |    |    |         \--- org.ow2.asm:asm:5.0.4 -> 9.0

Background

  • The com.jayway.jsonpath:json-path lib seems to be the only solid Java based JSONPath implementation so I understand why its used here. It's also used in Spring Boot test modules and in Spring Cloud Contract Verifier modules.

  • Up until recently it had not seen a release in 3 years.

  • It brings in json-smart which brings in accessors-smart both of which have not been released on Maven central since 2017. However, each of these do have recent releases on RedHat GA repository. It is hard to tell what the state of the libs are, if they are maintained, etc.

  • The smart-accessors in turn brings in ancient asm 5.

Problem

The last item has caused quite a few issues for consumers of json-path as the current state of the world is asm 9. Typically version alignment handle this when using Gradle (as above 5.0.4 -> 9.0) and Maven can be configured to do the same. It still can cause issues though. An example where other frameworks have insulated this detail is in spring-core shading of cglib/asm.

It looks like DSG has done a good job of not exposing JsonPath and its only used internally in graphql-dgs-client. This qualifies it as a candidate for shading. It's truly an internal implementation detail that consuming applications should not have to deal with.

Possible Solution

Option 1

I would ❤️ to submit a PR that shades JsonPath-and-company. Thoughts?

Option 2

Exclude the transitive json-smart lib and switch JsonPath's JsonProvider off of json-smart and to Jackson instead.

Option 3

Improve JsonPath to hide its internals. However, this is not easy as some of its API exposes JsonSmart I believe.

Option N (theres always more options)

I am willing to submit a PR for whatever approach we land on in this discussion. We are going to be consumers of DGS and as such I would love to contribute.

Provide support for Spring's @RequestHeader annotation.

Currently to get a request header I have to do the following:

@DsgData(parentType = "Query", field = "shows")
public List<Show> shows(DataFetchingEnvironment env) {
    DgsContext context = env.getContext();
    DefaultRequestData requestData = (RequestData)context.getCustomContext();
    HttpHeaders headers = requestDatagetHeader();
    var someHeader = headers.get("some-header");
    
    //...
}    

Spring provides a @RequestHeader annotation that makes this a lot cleaner.

I would expect it to work similar to @InputArgument:

@DsgData(parentType = "Query", field = "shows")
public List<Show> shows(DataFetchingEnvironment env,
                        @RequestHeader(name = "some-header") String someHeader) {
    //...
}    

Way to integration with @AuthenticationPrincipal

I just learn this framework for some days and I think this is such a great framework and I'd like to make my current spring-boot-realworld-example-app to support graphql with this framework.

But after learning the docs I still feel confusing about the authentication integration. I am using jwt as the token system and I implement a JwtTokenFilter to make the @AuthenticationPrincipal injection work in spring mvc controller:

    @GetMapping
    public ResponseEntity<?> article(@PathVariable("slug") String slug,
                                     @AuthenticationPrincipal User user) {
        return articleQueryService.findBySlug(slug, user)
            .map(articleData -> ResponseEntity.ok(articleResponse(articleData)))
            .orElseThrow(ResourceNotFoundException::new);
    }

Is there some tips or resources for me to support @AuthenticationPrincipal or similar mechanism to easily access current user in every Query Mutation Subscription.

Custom DataFetchingExceptionHandler not used when querying with DgsQueryExecutor on tests

I've created a custom DataFetchingExceptionHandler according to the doc in here: https://netflix.github.io/dgs/error-handling/ It works perfectly when querying /graphql. When I try to write tests around it though, and use DgsQueryExecutor, the handler is not triggers, and the query instead throws the exception. Here's the query:

        val graphQLQueryRequest = GraphQLQueryRequest(
                GetAllInWindowGraphQLQuery
                        .Builder()
                        .from("2021-04-03T10:00:00.000Z")
                        .to("2021-02-01T10:00:00.000Z")
                        .build(),
                GetProjectionRoot()
                        .id()
        )

        val allFields = dgsQueryExecutor.executeAndExtractJsonPath<List<String>>(
                query = graphQLQueryRequest.serialize(),
                jsonPath = "errors"
        )

How can I make it use the custom handler?

connecting a postgres db to persist data

Hi,
Just started working with DGS and relatively new to Spring too. I wanted to connect a postgres db to persist data but am not sure how to. Any leads on this would be appreciated.

Introduce config properties

The DGS framework takes a hard stance on how to configure itself:

  • Hardcoded /graphql path
  • Hardcoded /schema.json path and whether it is enabled or not
  • Hardcoded /graphiql path and whether it is enabled or not
  • Hardcoded classpath*:schema/**/*.graphql* to load the schema files from

It would be nice if DGS would offer some configuration options like:

dgs.graphql.path = /graphql
dgs.graphql.schema-location = classpath*:schema/**/*.graphql*
dgs.graphql.schema-json.enabled = true
dgs.graphql.schema-json.path = /schema.json
dgs.graphql.graphiql.enabled = true
dgs.graphql.graphiql.path = /graphiql

Rationale is to be able to change paths, but also to disable certain functionality.
E.g. GraphiQL is very useful during development but it might be desired or required to disable this in production because of security requirements or customized GraphiQL pages served differently (same for /schema.json).
For the schema-location, some might want to use a different location like classpath:graphql/schema.graphqls to reduce classpath scanning.

Probably there are more hardcoded things that could be moved to @ConfigrationProperties (websockets?)

Upgrade Java to latest accepted version

I am not sure if community contributions are accepted. But are there any specific reasons for using Java 8?. It's quite old and most frameworks have already started supporting the latest stable release version of Java.

Shorthand Annotations

In an effort to make code less verbose and easier to read: in addition to @DgsData annotation please consider adding the following two:

  • @DgsQuery
  • @DgsMutation

which are to serve as shorthands for parentType="Query" and parentType="Mutation", respectively.

Further, it would be great to have a field parameter for the above annotations (as well as for @DgsData) as optional and have it to default to the annotated method's name.

This way the following annotation:

@DgsData(parentType = "Query", field = "shows")
public List<Show> shows()

Becomes:

@DgsQuery
public List<Show> shows()

Which is much more compact and follows the same approach that Spring Framework takes for composed annotations @GetMapping/@PostMapping vs @RequestMapping(...)

Upgrading to 3.5.1 gives ClassNotFoundException: net.minidev.json.writer.JsonReaderI

2021-02-23 17:22:55.585 ERROR 6480 --- [  restartedMain] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 
'requestMappingHandlerAdapter' defined in class path resource 
[org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: 
Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: 
Failed to instantiate [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter]: Factory 
method 'requestMappingHandlerAdapter' threw exception; nested exception is java.lang.NoClassDefFoundError: 
net/minidev/json/writer/JsonReaderI
Caused by: java.lang.ClassNotFoundException: net.minidev.json.writer.JsonReaderI
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606) ~[na:na]
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168) ~[na:na]
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522) ~[na:na]
        ... 45 common frames omitted

This happens when running ./gradlew clean bootRun with a simple project using JDK 15.

Could this be related to Exclude json-smart transitive dependency from json-path?

Maven plugin for code generation similar to the Gradle plugin

Hi
Thank you so much for making DGS public!

It would very helpful for the maven based projects to also have a maven plugin available for code generation like the gradle projects do.

Is that in the pipeline or even on the roadmap?
Is there a suggested workaround on how to run the gradle plugin from a maven build?

Thank you in advance.

Consider moving away from hosting your artifacts on JCenter, as it's being decommissioned

Task Description

You should consider moving away from hosting your artifacts on JCenter as soon as possible, as it's being decommissioned.

Please, have a look at these links:

Task List

  • Re-publish all releases to Maven Central.
  • Make all future releases to Maven Central.
  • Update the documentation and the examples.

Provide an easy way to access the input arguments on the query in child data fetchers.

Currently, we can access this information via this:

// This gives you the first field that was selected on the query
Field result = (Field)(dfe.getOperationDefinition().getSelectionSet().getSelections().get(0));
// This gives you the first argument's value and so on
result.getArguments().get(0).getValue();

We could either enhance the DgsDataFetchingEnvironment or add @RootInputArgument annotation to easily access this.

@InputArgument to default to parameter name

It would be great for @InputArgument's value to default parameter name -- similar to Spring Framework's @PathVariable and @RequestParam annotations. So we can compact

public List<Show> shows(@InputArgument("titleFilter") String titleFilter)

to

public List<Show> shows(@InputArgument String titleFilter)

@InputArgument should work with MultipartFile

Using an @InputArgument of type MultipartFile fails because it tries to JSON deserialize the input. MultipartFile needs to be special cased for file upload use cases.

Workaround

Use DataFetchingEnvironment instead of InputArgument

GraphQLQueryRequest serialization error

I expect ShowsGraphQLQuery.Builder().build(); makes query { shows { title }} but It actually makes query { shows() { title }}.

I'm using 3.4.1

If I replace new ShowsGraphQLQuery.Builder().build() with new ShowsGraphQLQuery.Builder().titleFilter("").build();, the test passed
.

Thank you.

@Testvoid showWithQueryApiUsingMock() throws Exception {
   
  Mockito.when(showService.shows()).thenAnswer(invocation -> List.of(new Show("mock title", 2020)));

   
  GraphQLQueryRequest graphQLQueryRequest = new GraphQLQueryRequest(
            
    new ShowsGraphQLQuery.Builder().build(),
            
    new ShowsProjectionRoot().title()
    );

    
  List<String> titles = dgsQueryExecutor.executeAndExtractJsonPath(graphQLQueryRequest.serialize(), "data.shows[*].title");
  assertThat(titles).containsExactly("mock title");

}
2021-02-22 14:28:10.519  WARN 37916 --- [    Test worker] notprivacysafe.graphql.GraphQL           : Query failed to parse : 'query {shows(){ title } }'

Invalid Syntax : offending token ')' at line 1 column 14
com.netflix.graphql.dgs.exceptions.QueryException: Invalid Syntax : offending token ')' at line 1 column 14
	at com.netflix.graphql.dgs.internal.DefaultDgsQueryExecutor.getJsonResult(DefaultDgsQueryExecutor.kt:177)
	at com.netflix.graphql.dgs.internal.DefaultDgsQueryExecutor.executeAndExtractJsonPath(DefaultDgsQueryExecutor.kt:122)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:686)
	at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
	at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
	at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:212)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:208)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:137)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:71)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:220)
	at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:188)
	at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:202)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:181)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:102)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:82)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:78)
	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
	at com.sun.proxy.$Proxy2.stop(Unknown Source)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:132)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)
	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)
	at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:412)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
	at java.base/java.lang.Thread.run(Thread.java:834)

Custom scalars not usable as mutation input

Hey guys,

First of all, I really like your framework! I was trying to add a custom scalar (LocalDateTime) to my project, using the latest dgs release 3.5.1. I followed instructions on https://netflix.github.io/dgs/scalars/ and made changes accordingly. However when I tested it it threw exceptions. Then I tried the other method mentioned in https://github.com/Netflix/dgs-examples-java/blob/main/src/main/java/com/example/demo/scalars/DateTimeScalar.java and got the same error.

I've been able to reproduce the issue using my fork of the dgs-examples repo: https://github.com/faust2199/dgs-examples-java/tree/dgs-issue . After adding submittedDate to the input type, the following mutation causes an internal error:

mutation {
  addReview (review: {
    showId: 1
    username: "dgs-user"
    starScore: 0
    submittedDate: "1999-02-01T05:43:53.28Z"
  }) {
    username
    submittedDate
  }
}
{
  "errors": [
    {
      "message": "java.lang.IllegalArgumentException: Cannot construct instance of `java.time.OffsetDateTime` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)\n at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: com.example.demo.generated.types.SubmittedReview[\"submittedDate\"])",
      "locations": [],
      "path": [
        "addReview"
      ],
      "extensions": {
        "errorType": "INTERNAL"
      }
    }
  ],
  "data": {
    "addReview": null
  }
}

By the way, I ran across the following piece of code when looking at the stack trace.

jacksonObjectMapper().convertValue(parameterValue, parameter.type)

Is it creating a new ObjectMapper on every request? I think it is more efficient to reuse.

Thanks in advance!

Bad request on opening a WS subscription

Hello, so we've started experimenting with DGS and Subscriptions and ran into some issues which we can't directly see the reason for. A few bits from the code (should be reproducible):

type Subscription {
    livePlayers: Player
}

type Player {
    id: String!
    x: Int!
    y: Int!
}
data class Player(
        val id: String,
        val x: Int = 0,
        val y: Int = 0
)

@DgsComponent
class PlayerDataFetcher(
) {
    @DgsData(field = "livePlayers", parentType = "Subscription")
    fun livePlayers(): Publisher<Player> {
        return Flux.interval(Duration.ofSeconds(0), Duration.ofSeconds(1)).map{ Player("1")};
    }
}
@SpringBootApplication
class KotlinGraphqlApplication

fun main(args: Array<String>) {
    runApplication<KotlinGraphqlApplication>(*args)
}

@Configuration
class LocalHostCorsConfig {
    @Bean
    fun corsFilter(): FilterRegistrationBean<*> {
        val source = UrlBasedCorsConfigurationSource()
        val config = CorsConfiguration()
        config.addAllowedOrigin("http://localhost:3000")
        config.addAllowedOrigin("https://localhost:8444")
        config.addAllowedHeader("Accept")
        config.addAllowedHeader("Content-Type")
        config.addAllowedHeader("X-Requested-With")
        config.addAllowedHeader("Authorization")
        config.addAllowedMethod("GET")
        config.addAllowedMethod("POST")
        config.addAllowedMethod("OPTIONS")
        source.registerCorsConfiguration("/**", config)
        return FilterRegistrationBean(CorsFilter(source))
    }
}

When running the example from a local playground we receive a 400:

image

Upon some investigation it seems that DgsRestController.kt returns early due to missing body:

image

Does anyone have a clue what we might be wrong here? Could it be that the UPDGRADE call from the client (would not contain a body) is causing this?

Invalid link in code documentation

There are some documentation in code contains a link to a manual. For example, this one. I assume this link is from the internal netflix manual. Is there any plan to make these internal documentations open source? or else, is it possible to remove these links from the codes (this might be a bit confusing otherwise)?
Thank you. 😄

Directives APIs

It seem that DGS framework does not provide any API to access Graphql Directives

Is there any plan to support GraphQLDirective binding in DataFetcher in additional to existing InputArgument ?

Doc: example of separate field resolver

Ok, so I read the documentation, all of it last night. I may have been tired, and may not have been thorough, so I apologize if this is covered. I saw a case for this in the Federation examples in the blog post, but not if Federation isn't being used. If you have a field on an object that needs its own resolver/data fetcher, because it's doing another query, how do you do that? if it's documented can you point me to that? if not I think it would be a good page to add. I think I know how to do it, I just can't find the documentation. Here's an example (we could talk about how this is the wrong model, but it's just an example).

type Query {
    shows(titleFilter: String): [Show]
}

type Show {
    title: String
    releaseYear: Int
    watchedTimes: Int # I'm not stored in the same table, in fact, I'm just another query, and I shouldn't be fetched unless I'm asked for by the client
}

GraphQL query with arguments named `input` or `operation` conflict with members in generated Kotlin

A graphql mutation or query with an argument named input or operation will result in a compile error when generating Kotlin.

Example

type Query {
    foo(input: String!, operation: String!): Int
}
generateJava {
    ....
    language = "KOTLIN"
    generateClient = true   // Enable generating the type safe query API
}

Expected Result

Generated code compiles.

Actual Result

Compile errors:

FooGraphqlQuery.kt: 'input' hides member of supertype 'GraphQLQuery' and needs 'override' modifier
FooGraphqlQuery.kt: 'operation' hides member of supertype 'GraphQLQuery' and needs 'override' modifier

changing the endpoint for running tests

I follow the testing examples from the documentation, and I use the "DgsQueryExecutor" to run the queries.
I know spring runs a local service, but I would like to run the tests against a remote service and (as part of our CI/CD pipeline).

Is there an option to change the URL used by the "DgsQueryExecutor" to execute queries against a remote server? if not, can we have such an option?

Custom scalars not coerced if used as mutation input

Hey guys,

First of all, I really like your framework! One thing that bugs me though, it seems that custom scalars are not coerced in the mutation. As per documentation the @InputArgument can be used in mutations see docs

Give the schema with mutation such as

type Mutation {
    scalarAsInput(scalar: [UUID]): [UUID]
}

scalar UUID

and registering the UUIDScalar using the @DgsScalar(name="UUID") and finally writing a DataFetcher

@DgsComponent
public class ScalarDataFetcher {
    @DgsData(parentType = DgsConstants.MUTATION.TYPE_NAME, field = DgsConstants.MUTATION.ScalarAsInput)
    public List<UUID> customScalarMutation(@InputArgument("scalar") List<UUID> scalar) {
        return scalar;
    }
}

I am getting the following error

    "errors": [
        {
            "message": "Can't serialize value (/scalarAsInput[0]) : Not a valid UUID",
            "path": [
                "scalarAsInput",
                0
            ],
            "extensions": {
                "classification": "DataFetchingException"
            }
        }
    ],

When debugging I can see that the DataFetchingEnvironment has the argument properly coerced from String to UUID

image

I forked the examples repository to reproduce the issue here

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.