please support specifying a collection of resolved `Resource` instances for the individual schema files for Spring Native usage
Hi, when I want to use Spring GraphQL in a Spring Native environment, the native build fails at runtime. It cant find the graphql/schema.graphqls file. This is because its doing classpath scanning in the GraphqlProperties class. In Spring Native, there's no classpath. ClassPathResources can be made to work by providing Spring Native a configuration hint saying that a particular file is to be included in the native binary's memory, e.g,: graphql/schema.graphqls, but ResourcePatternResolver doesn't work.
So, the simplest solution is to just change the GraphQLProperties to also support a pre-determined array of graphqls schema files, instead of the prefix and extension combos.
Something like this
private List<Resource> resolveSchemaResources(ResourcePatternResolver resolver, Resource[] schemas, String[] schemaLocations, String[] fileExtensions) {
List<Resource> schemaResources = new ArrayList<>();
// new
if (schemas!=null && schemas.length > 0){
for ( Resource resource : schemas)
schemaResources.add(resource);
}
else {
// old
for (String location : schemaLocations) {
for (String extension : fileExtensions) {
String resourcePattern = location + "*" + extension;
try {
schemaResources.addAll(Arrays.asList(resolver.getResources(resourcePattern)));
}
catch (IOException ex) {
logger.debug("Could not resolve schema location: '" + resourcePattern + "'", ex);
}
}
}
}
return schemaResources;
}
Then, a user could easily just say spring.graphql.schema.schemas=classpath:graphql/schema.graphqls and it would work in a graalvm spring native app, or they could use the fall through scenario searching for lcoations and extensions on the jre
I know this works because I replaced the GraphQLSource bean definition in the auto config by copying and pasting the existing bean and then simply hardcoding the return values from private List<Resource> resolveSchemaResources. Once I did that, and then added the following hint - @ResourceHint(patterns = "graphql/schema.graphqls") - it built and started up just fine.
If you want to reproduce, go to start.spring.io, add the experimental Spring Native support checkbox, add Webflux, and manually add the GraphQL dependency. then run mvn -Pnative clean package on a machine with GraalVM (im using the latest, which supports java 17) installed on which you've run gu install native-image
Hey Josh,
We haven't experimented much with native so far, so thanks for sharing your experience here. Would the following work without the properties change?
@ResourceHint(patterns = {"graphql/*.graphqls", "graphql/*.gqls"})
This is a short term solution, as it won't stay aligned with the configuration properties if the values are changed. I think we should leverage any future AOT infrastructure and prepare this work at build time in the future. Lots should be done as well with our future client support.
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.
Hi - let me try that out now. I don't think it'll make a difference as I've tried using @ResourceHint before and I was told it has more to do that were doing classpath scanning (where there is nothing to scan in the native world) in this case, not that we're loading multiple resources (which @ResourcehInt would help with)
Sorry for the late update: yeeah, this doesn't work. we need to not be doing the scanning, i think.
pading @aclement who might know more about why that is, exactly
I see that since this issue was filed, the autoconfiguration has improved to support conditional registration of the GraphQlSource and to be decoupled from the registration of the GraphQlProperties. I've sent a (trivial, but hopefully useful) PR to support a bit of indirection in resolving the schema files. This indirection would let me use Spring GraalVM with Spring Native and I wouldn't need to recreate the GraphQlSource. Thanks in advance for your consideration
Superseded by #495