Skip to content

Document classpath* location for looking up GraphQL schemas across modules #31772

Closed
@estigma88

Description

@estigma88

Version
Spring Boot 2.7.1

Description
We created a new itest source set in Gradle and when we run the test using @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT), seems like the autoconfigure GraphQL components are not provisioned.

How to reproduce it
This project contains a pretty simple GraphQL controller, with two tests:

  • One inside the test source set, using RestAssured to call the GraphQL endpoint, which works fine (HTTP 200)
  • One inside the itest source set, using RestAssured to call the GraphQL endpoint, which doesn't work (HTTP 404)

Clues
I did some debugging and found that ConditionalOnGraphQlSchema returns true for the test source set, and false for the itest source set, it seems like this line on DefaultGraphQlSchemaCondition cannot find the GraphQL schema, and therefore, Spring Boot doesn't contribute the Graphql autoconfiguration.

My guess is this issue might be for Spring Boot and not Gradle configuration, as other resources work fine, like liquibase changelogs and application.yml files.

Activity

self-assigned this
on Jul 19, 2022
wilkinsona

wilkinsona commented on Jul 19, 2022

@wilkinsona
Member

It's a classpath ordering problem. Your itest task has the project's main resources on its classpath after all of its dependencies whereas the test task has the project's main resources on its classpath before all of its dependencies. This ordering matters because the graphql-java jar contains a graphql package. When it's on the classpath before the project's main resources, this package prevents the graphql/schema.graphqls file from being found as it ends up looking inside graphql-java for it as that's the first occurrence of graphql/ on the classpath.

You can fix the problem by creating your itest source set like this:

sourceSets {
	create("itest") {
		compileClasspath = sourceSets.main.get().output + compileClasspath
		runtimeClasspath = sourceSets.main.get().output + runtimeClasspath
	}
}

I'm going to leave this issue open as I think we should consider a different default schema location. "classpath*:graphql/**/" would be more robust, although it may be quite slow depending on the size of the classpath.

What do you think, @bclozel and @rstoyanchev?

removed their assignment
on Jul 19, 2022
bclozel

bclozel commented on Jul 19, 2022

@bclozel
Member
wilkinsona

wilkinsona commented on Jul 19, 2022

@wilkinsona
Member

Thanks for the link, Brian. That's the same problem indeed, just with a different source of the unwanted graphql package that stops the file from being found.

changed the title [-]@SpringBootTest with RANDOM_PORT doesn't autoconfigure GraphQL components on a different Gradle sourceSet[/-] [+]GraphQL schema files are not found when a root containing a graphql package appears on the classpath before the root that contains the schema files[/+] on Jul 19, 2022
rstoyanchev

rstoyanchev commented on Sep 20, 2022

@rstoyanchev
Contributor

That's the same problem indeed, just with a different source of the unwanted graphql package that stops the file from being found.

As of spring-projects/spring-graphql#338, we look in different places for schema vs test request vs client request files, which eliminates a very basic reason to shadowing graphql/ under main and test sources that most apps would run into otherwise.

For the rest, using classpath*: by default will find all possible candidates out of the box, including some that may not be intended for inclusion, while classpath: requires an explicit action to decide how to deal with such shadowing. I tend to think the more explicit opt-in option is preferable. I've already made an adjustment to the Spring for GraphQL docs to make that easier to spot.

bclozel

bclozel commented on Sep 20, 2022

@bclozel
Member

Thanks Rossen, I'll add a similar note in the Spring Boot reference docs, I'll turn this into a documentation issue then.

9 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Relationships

None yet

    Development

    No branches or pull requests

      Participants

      @bclozel@rstoyanchev@philwebb@wilkinsona@spring-projects-issues

      Issue actions

        Document classpath* location for looking up GraphQL schemas across modules · Issue #31772 · spring-projects/spring-boot