Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

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

Closed
estigma88 opened this issue Jul 16, 2022 · 5 comments
Closed
Assignees
Labels
type: documentation A documentation update
Milestone

Comments

@estigma88
Copy link

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.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jul 16, 2022
@wilkinsona wilkinsona self-assigned this Jul 19, 2022
@wilkinsona
Copy link
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?

@wilkinsona wilkinsona removed their assignment Jul 19, 2022
@wilkinsona wilkinsona added the for: team-attention An issue we'd like other members of the team to review label Jul 19, 2022
@bclozel
Copy link
Member

bclozel commented Jul 19, 2022

This might be related to spring-projects/spring-graphql#308 (comment)

@wilkinsona
Copy link
Member

wilkinsona commented Jul 19, 2022

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.

@wilkinsona wilkinsona 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 Jul 19, 2022
@philwebb philwebb removed the for: team-attention An issue we'd like other members of the team to review label Aug 22, 2022
@rstoyanchev
Copy link
Contributor

rstoyanchev commented Sep 20, 2022

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
Copy link
Member

bclozel commented Sep 20, 2022

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

@bclozel bclozel added type: documentation A documentation update and removed status: waiting-for-triage An issue we've not yet triaged labels Sep 20, 2022
@bclozel bclozel added this to the 2.7.4 milestone Sep 20, 2022
@bclozel bclozel changed the title 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 Document classpath* location for looking up schemas across modules Sep 21, 2022
@wilkinsona wilkinsona changed the title Document classpath* location for looking up schemas across modules Document classpath* location for looking up GraphQL schemas across modules Sep 22, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: documentation A documentation update
Projects
None yet
Development

No branches or pull requests

6 participants