Skip to content

Commit

Permalink
Contribute GraphQL resources during AOT phase
Browse files Browse the repository at this point in the history
This commit ensures that the default locations for GraphQL schema files
and the GraphiQL UI HTML page are included in the native image by
registering resource hints during the AOT phase.

Fixes gh-33208
  • Loading branch information
bclozel committed Nov 16, 2022
1 parent 934b601 commit 2004581
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 0 deletions.
Expand Up @@ -29,6 +29,8 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfiguration;
Expand Down Expand Up @@ -143,4 +145,13 @@ public AnnotatedControllerConfigurer annotatedControllerConfigurer() {
return controllerConfigurer;
}

static class GraphQlResourcesRuntimeHints implements RuntimeHintsRegistrar {

@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
hints.resources().registerPattern("graphql/*.graphqls").registerPattern("graphql/*.gqls");
}

}

}
Expand Up @@ -23,6 +23,8 @@
import org.apache.commons.logging.LogFactory;
import reactor.core.publisher.Mono;

import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
Expand All @@ -37,6 +39,7 @@
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportRuntimeHints;
import org.springframework.core.annotation.Order;
import org.springframework.core.log.LogMessage;
import org.springframework.graphql.ExecutionGraphQlService;
Expand Down Expand Up @@ -79,6 +82,7 @@
@ConditionalOnClass({ GraphQL.class, GraphQlHttpHandler.class })
@ConditionalOnBean(ExecutionGraphQlService.class)
@EnableConfigurationProperties(GraphQlCorsProperties.class)
@ImportRuntimeHints(GraphQlWebFluxAutoConfiguration.GraphiQlResourceHints.class)
public class GraphQlWebFluxAutoConfiguration {

private static final RequestPredicate SUPPORTS_MEDIATYPES = accept(MediaType.APPLICATION_GRAPHQL,
Expand Down Expand Up @@ -175,4 +179,13 @@ public HandlerMapping graphQlWebSocketEndpoint(GraphQlWebSocketHandler graphQlWe

}

static class GraphiQlResourceHints implements RuntimeHintsRegistrar {

@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
hints.resources().registerPattern("graphiql/index.html");
}

}

}
Expand Up @@ -24,6 +24,8 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
Expand All @@ -39,6 +41,7 @@
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportRuntimeHints;
import org.springframework.core.annotation.Order;
import org.springframework.core.log.LogMessage;
import org.springframework.graphql.ExecutionGraphQlService;
Expand Down Expand Up @@ -80,6 +83,7 @@
@ConditionalOnClass({ GraphQL.class, GraphQlHttpHandler.class })
@ConditionalOnBean(ExecutionGraphQlService.class)
@EnableConfigurationProperties(GraphQlCorsProperties.class)
@ImportRuntimeHints(GraphQlWebMvcAutoConfiguration.GraphiQlResourceHints.class)
public class GraphQlWebMvcAutoConfiguration {

private static final Log logger = LogFactory.getLog(GraphQlWebMvcAutoConfiguration.class);
Expand Down Expand Up @@ -193,4 +197,13 @@ public HandlerMapping graphQlWebSocketMapping(GraphQlWebSocketHandler handler, G

}

static class GraphiQlResourceHints implements RuntimeHintsRegistrar {

@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
hints.resources().registerPattern("graphiql/index.html");
}

}

}
Expand Up @@ -28,7 +28,10 @@
import org.assertj.core.api.InstanceOfAssertFactories;
import org.junit.jupiter.api.Test;

import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.graphql.GraphQlAutoConfiguration.GraphQlResourcesRuntimeHints;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
Expand Down Expand Up @@ -182,6 +185,14 @@ void shouldConfigureCustomBatchLoaderRegistry() {
});
}

@Test
void shouldRegisterHints() {
RuntimeHints hints = new RuntimeHints();
new GraphQlResourcesRuntimeHints().registerHints(hints, getClass().getClassLoader());
assertThat(RuntimeHintsPredicates.resource().forResource("graphql/sample/schema.gqls")).accepts(hints);
assertThat(RuntimeHintsPredicates.resource().forResource("graphql/other.graphqls")).accepts(hints);
}

@Configuration(proxyBeanMethods = false)
static class CustomGraphQlBuilderConfiguration {

Expand Down
Expand Up @@ -23,6 +23,8 @@
import graphql.schema.idl.TypeRuntimeWiring;
import org.junit.jupiter.api.Test;

import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.graphql.GraphQlAutoConfiguration;
import org.springframework.boot.autoconfigure.graphql.GraphQlTestDataFetchers;
Expand Down Expand Up @@ -161,6 +163,13 @@ void routerFunctionShouldHaveOrderZero() {
});
}

@Test
void shouldRegisterHints() {
RuntimeHints hints = new RuntimeHints();
new GraphQlWebFluxAutoConfiguration.GraphiQlResourceHints().registerHints(hints, getClass().getClassLoader());
assertThat(RuntimeHintsPredicates.resource().forResource("graphiql/index.html")).accepts(hints);
}

private void testWithWebClient(Consumer<WebTestClient> consumer) {
this.contextRunner.run((context) -> {
WebTestClient client = WebTestClient.bindToApplicationContext(context).configureClient()
Expand Down
Expand Up @@ -22,6 +22,8 @@
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;

import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.graphql.GraphQlAutoConfiguration;
import org.springframework.boot.autoconfigure.graphql.GraphQlTestDataFetchers;
Expand Down Expand Up @@ -168,6 +170,13 @@ void routerFunctionShouldHaveOrderZero() {
});
}

@Test
void shouldRegisterHints() {
RuntimeHints hints = new RuntimeHints();
new GraphQlWebMvcAutoConfiguration.GraphiQlResourceHints().registerHints(hints, getClass().getClassLoader());
assertThat(RuntimeHintsPredicates.resource().forResource("graphiql/index.html")).accepts(hints);
}

private void testWith(MockMvcConsumer mockMvcConsumer) {
this.contextRunner.run((context) -> {
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).defaultRequest(
Expand Down

0 comments on commit 2004581

Please sign in to comment.