You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2022/04/22 07:50:50 UTC
[isis] branch master updated: Bump spring-graphql 1.0.0-M4 -> 1.0.0-RC1
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/master by this push:
new df9f5e8530 Bump spring-graphql 1.0.0-M4 -> 1.0.0-RC1
df9f5e8530 is described below
commit df9f5e8530e063dcbe0c306a1999e4b3fe487e95
Author: Andi Huber <ah...@apache.org>
AuthorDate: Fri Apr 22 09:50:43 2022 +0200
Bump spring-graphql 1.0.0-M4 -> 1.0.0-RC1
---
core/pom.xml | 6 +
extensions/core/command-log/applib/pom.xml | 24 ++-
extensions/core/command-log/jdo/pom.xml | 24 ++-
extensions/core/command-log/jpa/pom.xml | 26 +--
extensions/core/command-log/pom.xml | 12 --
incubator/viewers/graphql/pom.xml | 4 +-
incubator/viewers/graphql/viewer/pom.xml | 101 ++-------
.../viewer/source/GraphQlServiceForIsis.java | 18 +-
.../viewer/spring/GraphQlAutoConfiguration.java | 157 +++++++-------
.../spring/GraphQlWebMvcAutoConfiguration.java | 236 +++++++++++----------
10 files changed, 286 insertions(+), 322 deletions(-)
diff --git a/core/pom.xml b/core/pom.xml
index 4f6853c648..81f280d0dc 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -675,6 +675,12 @@
<version>2.0.0-SNAPSHOT</version>
<type>pom</type>
</dependency>
+ <dependency>
+ <groupId>org.apache.isis.testing</groupId>
+ <artifactId>isis-testing</artifactId>
+ <version>2.0.0-SNAPSHOT</version>
+ <type>pom</type>
+ </dependency>
<!-- THIRD PARTY DEPENDENCIES -->
diff --git a/extensions/core/command-log/applib/pom.xml b/extensions/core/command-log/applib/pom.xml
index 86be82e515..51b7437517 100644
--- a/extensions/core/command-log/applib/pom.xml
+++ b/extensions/core/command-log/applib/pom.xml
@@ -71,19 +71,21 @@
<artifactId>javax.jdo</artifactId>
</dependency>
- <!-- Testing -->
-
- <dependency>
- <groupId>org.apache.isis.testing</groupId>
- <artifactId>isis-testing-unittestsupport-applib</artifactId>
+ <!-- TESTING -->
+
+ <dependency>
+ <groupId>org.apache.isis.mavendeps</groupId>
+ <artifactId>isis-mavendeps-unittests</artifactId>
+ <type>pom</type>
<scope>test</scope>
- </dependency>
-
- <dependency>
- <groupId>org.apache.isis.testing</groupId>
- <artifactId>isis-testing-integtestsupport-applib</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.isis.mavendeps</groupId>
+ <artifactId>isis-mavendeps-integtests</artifactId>
+ <type>pom</type>
<scope>test</scope>
- </dependency>
+ </dependency>
</dependencies>
diff --git a/extensions/core/command-log/jdo/pom.xml b/extensions/core/command-log/jdo/pom.xml
index 430b875cc7..5649ec4471 100644
--- a/extensions/core/command-log/jdo/pom.xml
+++ b/extensions/core/command-log/jdo/pom.xml
@@ -58,19 +58,21 @@
<artifactId>isis-persistence-jdo-datanucleus</artifactId>
</dependency>
- <!-- Testing -->
-
- <dependency>
- <groupId>org.apache.isis.testing</groupId>
- <artifactId>isis-testing-unittestsupport-applib</artifactId>
+ <!-- TESTING -->
+
+ <dependency>
+ <groupId>org.apache.isis.mavendeps</groupId>
+ <artifactId>isis-mavendeps-unittests</artifactId>
+ <type>pom</type>
<scope>test</scope>
- </dependency>
-
- <dependency>
- <groupId>org.apache.isis.testing</groupId>
- <artifactId>isis-testing-integtestsupport-applib</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.isis.mavendeps</groupId>
+ <artifactId>isis-mavendeps-integtests</artifactId>
+ <type>pom</type>
<scope>test</scope>
- </dependency>
+ </dependency>
</dependencies>
diff --git a/extensions/core/command-log/jpa/pom.xml b/extensions/core/command-log/jpa/pom.xml
index a06f71e273..6c50de6606 100644
--- a/extensions/core/command-log/jpa/pom.xml
+++ b/extensions/core/command-log/jpa/pom.xml
@@ -57,20 +57,22 @@
<groupId>org.apache.isis.persistence</groupId>
<artifactId>isis-persistence-jpa-eclipselink</artifactId>
</dependency>
-
- <!-- Testing -->
-
- <dependency>
- <groupId>org.apache.isis.testing</groupId>
- <artifactId>isis-testing-unittestsupport-applib</artifactId>
+
+ <!-- TESTING -->
+
+ <dependency>
+ <groupId>org.apache.isis.mavendeps</groupId>
+ <artifactId>isis-mavendeps-unittests</artifactId>
+ <type>pom</type>
<scope>test</scope>
- </dependency>
-
- <dependency>
- <groupId>org.apache.isis.testing</groupId>
- <artifactId>isis-testing-integtestsupport-applib</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.isis.mavendeps</groupId>
+ <artifactId>isis-mavendeps-integtests</artifactId>
+ <type>pom</type>
<scope>test</scope>
- </dependency>
+ </dependency>
</dependencies>
diff --git a/extensions/core/command-log/pom.xml b/extensions/core/command-log/pom.xml
index b12024a044..396de63fb0 100644
--- a/extensions/core/command-log/pom.xml
+++ b/extensions/core/command-log/pom.xml
@@ -27,18 +27,6 @@
<packaging>pom</packaging>
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>org.apache.isis.testing</groupId>
- <artifactId>isis-testing</artifactId>
- <version>2.0.0-SNAPSHOT</version>
- <scope>import</scope>
- <type>pom</type>
- </dependency>
- </dependencies>
- </dependencyManagement>
-
<modules>
<module>applib</module>
<module>jdo</module>
diff --git a/incubator/viewers/graphql/pom.xml b/incubator/viewers/graphql/pom.xml
index 74ad74e736..2053282575 100644
--- a/incubator/viewers/graphql/pom.xml
+++ b/incubator/viewers/graphql/pom.xml
@@ -77,8 +77,8 @@
<dependency>
<groupId>org.springframework.graphql</groupId>
- <artifactId>spring-graphql</artifactId>
- <version>1.0.0-M5</version>
+ <artifactId>spring-graphql</artifactId>
+ <version>1.0.0-RC1</version>
</dependency>
<dependency>
diff --git a/incubator/viewers/graphql/viewer/pom.xml b/incubator/viewers/graphql/viewer/pom.xml
index 175ba5f755..480e100407 100644
--- a/incubator/viewers/graphql/viewer/pom.xml
+++ b/incubator/viewers/graphql/viewer/pom.xml
@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor
- license agreements. See the NOTICE file distributed with this work for additional
- information regarding copyright ownership. The ASF licenses this file to
- you under the Apache License, Version 2.0 (the "License"); you may not use
- this file except in compliance with the License. You may obtain a copy of
- the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required
- by applicable law or agreed to in writing, software distributed under the
- License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
- OF ANY KIND, either express or implied. See the License for the specific
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor
+ license agreements. See the NOTICE file distributed with this work for additional
+ information regarding copyright ownership. The ASF licenses this file to
+ you under the Apache License, Version 2.0 (the "License"); you may not use
+ this file except in compliance with the License. You may obtain a copy of
+ the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required
+ by applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ OF ANY KIND, either express or implied. See the License for the specific
language governing permissions and limitations under the License. -->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
@@ -52,22 +52,23 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-logging</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
+
+ <!-- TESTING -->
+
<dependency>
- <groupId>org.junit.jupiter</groupId>
- <artifactId>junit-jupiter-api</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.junit.jupiter</groupId>
- <artifactId>junit-jupiter-engine</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.junit.jupiter</groupId>
- <artifactId>junit-jupiter-params</artifactId>
+ <groupId>org.apache.isis.mavendeps</groupId>
+ <artifactId>isis-mavendeps-unittests</artifactId>
+ <type>pom</type>
<scope>test</scope>
</dependency>
+
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
@@ -78,46 +79,7 @@
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
-<!-- <dependency>-->
-<!-- <groupId>org.springframework.boot</groupId>-->
-<!-- <artifactId>spring-boot-test</artifactId>-->
-<!-- <scope>test</scope>-->
-<!-- </dependency>-->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <exclusions>
- <exclusion>
- <groupId>org.ow2.asm</groupId>
- <artifactId>asm</artifactId>
- </exclusion>
- <exclusion>
- <!-- when spring-boot release lags behind spring-core release explicitly
- spring-test added below -->
- <groupId>org.springframework</groupId>
- <artifactId>spring-test</artifactId>
- </exclusion>
- <exclusion>
- <!-- when spring-boot release lags behind spring-core release explicitly
- spring-test added below -->
- <groupId>org.springframework</groupId>
- <artifactId>spring-core</artifactId>
- </exclusion>
- <exclusion>
- <!-- we use log4j-2 instead -->
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-logging</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.junit.vintage</groupId>
- <artifactId>junit-vintage-engine</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
+
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
@@ -154,23 +116,6 @@
<scope>test</scope>
</dependency>
-<!-- <dependency> -->
-<!-- <groupId>com.google.guava</groupId> -->
-<!-- <artifactId>guava</artifactId> -->
-<!-- <scope>test</scope> -->
-<!-- </dependency> -->
-
-<!-- <dependency> -->
-<!-- <groupId>com.fasterxml.jackson.core</groupId> -->
-<!-- <artifactId>jackson-core</artifactId> -->
-<!-- <scope>test</scope> -->
-<!-- </dependency> -->
-<!-- <dependency> -->
-<!-- <groupId>com.fasterxml.jackson.core</groupId> -->
-<!-- <artifactId>jackson-databind</artifactId> -->
-<!-- <scope>test</scope> -->
-<!-- </dependency> -->
-
</dependencies>
diff --git a/incubator/viewers/graphql/viewer/src/main/java/org/apache/isis/viewer/graphql/viewer/source/GraphQlServiceForIsis.java b/incubator/viewers/graphql/viewer/src/main/java/org/apache/isis/viewer/graphql/viewer/source/GraphQlServiceForIsis.java
index 260dad74cf..a49ffb4f3d 100644
--- a/incubator/viewers/graphql/viewer/src/main/java/org/apache/isis/viewer/graphql/viewer/source/GraphQlServiceForIsis.java
+++ b/incubator/viewers/graphql/viewer/src/main/java/org/apache/isis/viewer/graphql/viewer/source/GraphQlServiceForIsis.java
@@ -2,11 +2,11 @@ package org.apache.isis.viewer.graphql.viewer.source;
import javax.inject.Inject;
-import org.springframework.graphql.GraphQlService;
-import org.springframework.graphql.RequestInput;
-import org.springframework.graphql.RequestOutput;
+import org.springframework.graphql.ExecutionGraphQlRequest;
+import org.springframework.graphql.ExecutionGraphQlResponse;
+import org.springframework.graphql.ExecutionGraphQlService;
import org.springframework.graphql.execution.BatchLoaderRegistry;
-import org.springframework.graphql.execution.ExecutionGraphQlService;
+import org.springframework.graphql.execution.DefaultExecutionGraphQlService;
import org.springframework.graphql.execution.GraphQlSource;
import org.springframework.stereotype.Service;
@@ -19,19 +19,19 @@ import reactor.core.publisher.Mono;
*/
@Service()
@RequiredArgsConstructor(onConstructor_ = {@Inject})
-public class GraphQlServiceForIsis implements GraphQlService {
+public class GraphQlServiceForIsis implements ExecutionGraphQlService {
private final BatchLoaderRegistry batchLoaderRegistry;
private final GraphQlSource graphQlSource;
- ExecutionGraphQlService delegate;
+ DefaultExecutionGraphQlService delegate;
@Override
- public Mono<RequestOutput> execute(RequestInput input) {
+ public Mono<ExecutionGraphQlResponse> execute(final ExecutionGraphQlRequest request) {
if(delegate == null) {
- delegate = new ExecutionGraphQlService(graphQlSource);
+ delegate = new DefaultExecutionGraphQlService(graphQlSource);
delegate.addDataLoaderRegistrar(batchLoaderRegistry);
}
- return delegate.execute(input);
+ return delegate.execute(request);
}
}
diff --git a/incubator/viewers/graphql/viewer/src/main/java/org/apache/isis/viewer/graphql/viewer/spring/GraphQlAutoConfiguration.java b/incubator/viewers/graphql/viewer/src/main/java/org/apache/isis/viewer/graphql/viewer/spring/GraphQlAutoConfiguration.java
index 75fd295605..a6c8b2e2b6 100644
--- a/incubator/viewers/graphql/viewer/src/main/java/org/apache/isis/viewer/graphql/viewer/spring/GraphQlAutoConfiguration.java
+++ b/incubator/viewers/graphql/viewer/src/main/java/org/apache/isis/viewer/graphql/viewer/spring/GraphQlAutoConfiguration.java
@@ -19,33 +19,35 @@ package org.apache.isis.viewer.graphql.viewer.spring;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.convert.ApplicationConversionService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;
-import org.springframework.format.support.DefaultFormattingConversionService;
-import org.springframework.graphql.GraphQlService;
+import org.springframework.graphql.ExecutionGraphQlService;
import org.springframework.graphql.data.method.annotation.support.AnnotatedControllerConfigurer;
import org.springframework.graphql.execution.BatchLoaderRegistry;
import org.springframework.graphql.execution.DataFetcherExceptionResolver;
import org.springframework.graphql.execution.DefaultBatchLoaderRegistry;
-import org.springframework.graphql.execution.ExecutionGraphQlService;
+import org.springframework.graphql.execution.DefaultExecutionGraphQlService;
import org.springframework.graphql.execution.GraphQlSource;
-import org.springframework.graphql.execution.MissingSchemaException;
import org.springframework.graphql.execution.RuntimeWiringConfigurer;
import graphql.GraphQL;
import graphql.execution.instrumentation.Instrumentation;
+import graphql.schema.idl.RuntimeWiring.Builder;
import graphql.schema.visibility.NoIntrospectionGraphqlFieldVisibility;
/**
@@ -62,74 +64,83 @@ public class GraphQlAutoConfiguration {
private static final Log logger = LogFactory.getLog(GraphQlAutoConfiguration.class);
- private final BatchLoaderRegistry batchLoaderRegistry = new DefaultBatchLoaderRegistry();
-
- @Bean
- @ConditionalOnMissingBean
- public GraphQlSource graphQlSource(ResourcePatternResolver resourcePatternResolver, GraphQlProperties properties,
- ObjectProvider<DataFetcherExceptionResolver> exceptionResolversProvider,
- ObjectProvider<Instrumentation> instrumentationsProvider,
- ObjectProvider<RuntimeWiringConfigurer> wiringConfigurers,
- ObjectProvider<GraphQlSourceBuilderCustomizer> sourceCustomizers) {
-
- List<Resource> schemaResources = resolveSchemaResources(resourcePatternResolver,
- properties.getSchema().getLocations(), properties.getSchema().getFileExtensions());
- GraphQlSource.Builder builder = GraphQlSource.builder()
- .schemaResources(schemaResources.toArray(new Resource[0]))
- .exceptionResolvers(exceptionResolversProvider.orderedStream().collect(Collectors.toList()))
- .instrumentation(instrumentationsProvider.orderedStream().collect(Collectors.toList()));
- if (!properties.getSchema().getIntrospection().isEnabled()) {
- builder.configureRuntimeWiring((wiring) -> wiring
- .fieldVisibility(NoIntrospectionGraphqlFieldVisibility.NO_INTROSPECTION_FIELD_VISIBILITY));
- }
- wiringConfigurers.orderedStream().forEach(builder::configureRuntimeWiring);
- sourceCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
- try {
- return builder.build();
- }
- catch (MissingSchemaException exc) {
- throw new InvalidSchemaLocationsException(properties.getSchema().getLocations(), resourcePatternResolver,
- exc);
- }
- }
-
- @Bean
- @ConditionalOnMissingBean
- public BatchLoaderRegistry batchLoaderRegistry() {
- return this.batchLoaderRegistry;
- }
-
- @Bean
- @ConditionalOnMissingBean
- public GraphQlService graphQlService(GraphQlSource graphQlSource) {
- ExecutionGraphQlService service = new ExecutionGraphQlService(graphQlSource);
- service.addDataLoaderRegistrar(this.batchLoaderRegistry);
- return service;
- }
-
- @Bean
- @ConditionalOnMissingBean
- public AnnotatedControllerConfigurer annotatedControllerConfigurer() {
- AnnotatedControllerConfigurer annotatedControllerConfigurer = new AnnotatedControllerConfigurer();
- annotatedControllerConfigurer.setConversionService(new DefaultFormattingConversionService());
- return annotatedControllerConfigurer;
- }
-
- private List<Resource> resolveSchemaResources(ResourcePatternResolver resolver, String[] schemaLocations,
- String[] fileExtensions) {
- List<Resource> schemaResources = new ArrayList<>();
- 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;
- }
+ private final ListableBeanFactory beanFactory;
+
+ public GraphQlAutoConfiguration(final ListableBeanFactory beanFactory) {
+ this.beanFactory = beanFactory;
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public GraphQlSource graphQlSource(final ResourcePatternResolver resourcePatternResolver, final GraphQlProperties properties,
+ final ObjectProvider<DataFetcherExceptionResolver> exceptionResolvers,
+ final ObjectProvider<Instrumentation> instrumentations, final ObjectProvider<RuntimeWiringConfigurer> wiringConfigurers,
+ final ObjectProvider<GraphQlSourceBuilderCustomizer> sourceCustomizers) {
+ String[] schemaLocations = properties.getSchema().getLocations();
+ Resource[] schemaResources = resolveSchemaResources(resourcePatternResolver, schemaLocations,
+ properties.getSchema().getFileExtensions());
+ GraphQlSource.SchemaResourceBuilder builder = GraphQlSource.schemaResourceBuilder()
+ .schemaResources(schemaResources).exceptionResolvers(toList(exceptionResolvers))
+ .instrumentation(toList(instrumentations));
+ if (!properties.getSchema().getIntrospection().isEnabled()) {
+ builder.configureRuntimeWiring(this::enableIntrospection);
+ }
+ wiringConfigurers.orderedStream().forEach(builder::configureRuntimeWiring);
+ sourceCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
+ return builder.build();
+ }
+
+ private Builder enableIntrospection(final Builder wiring) {
+ return wiring.fieldVisibility(NoIntrospectionGraphqlFieldVisibility.NO_INTROSPECTION_FIELD_VISIBILITY);
+ }
+
+ private Resource[] resolveSchemaResources(final ResourcePatternResolver resolver, final String[] locations,
+ final String[] extensions) {
+ List<Resource> resources = new ArrayList<>();
+ for (String location : locations) {
+ for (String extension : extensions) {
+ resources.addAll(resolveSchemaResources(resolver, location + "*" + extension));
+ }
+ }
+ return resources.toArray(new Resource[0]);
+ }
+
+ private List<Resource> resolveSchemaResources(final ResourcePatternResolver resolver, final String pattern) {
+ try {
+ return Arrays.asList(resolver.getResources(pattern));
+ }
+ catch (IOException ex) {
+ logger.debug("Could not resolve schema location: '" + pattern + "'", ex);
+ return Collections.emptyList();
+ }
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public BatchLoaderRegistry batchLoaderRegistry() {
+ return new DefaultBatchLoaderRegistry();
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public ExecutionGraphQlService executionGraphQlService(final GraphQlSource graphQlSource,
+ final BatchLoaderRegistry batchLoaderRegistry) {
+ DefaultExecutionGraphQlService service = new DefaultExecutionGraphQlService(graphQlSource);
+ service.addDataLoaderRegistrar(batchLoaderRegistry);
+ return service;
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public AnnotatedControllerConfigurer annotatedControllerConfigurer() {
+ AnnotatedControllerConfigurer controllerConfigurer = new AnnotatedControllerConfigurer();
+ controllerConfigurer
+ .addFormatterRegistrar((registry) -> ApplicationConversionService.addBeans(registry, this.beanFactory));
+ return controllerConfigurer;
+ }
+
+ private <T> List<T> toList(final ObjectProvider<T> provider) {
+ return provider.orderedStream().collect(Collectors.toList());
+ }
}
diff --git a/incubator/viewers/graphql/viewer/src/main/java/org/apache/isis/viewer/graphql/viewer/spring/GraphQlWebMvcAutoConfiguration.java b/incubator/viewers/graphql/viewer/src/main/java/org/apache/isis/viewer/graphql/viewer/spring/GraphQlWebMvcAutoConfiguration.java
index 65c49edf4e..f4db88443b 100644
--- a/incubator/viewers/graphql/viewer/src/main/java/org/apache/isis/viewer/graphql/viewer/spring/GraphQlWebMvcAutoConfiguration.java
+++ b/incubator/viewers/graphql/viewer/src/main/java/org/apache/isis/viewer/graphql/viewer/spring/GraphQlWebMvcAutoConfiguration.java
@@ -36,20 +36,22 @@ import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.core.io.ResourceLoader;
-import org.springframework.graphql.GraphQlService;
+import org.springframework.core.log.LogMessage;
+import org.springframework.graphql.ExecutionGraphQlService;
import org.springframework.graphql.execution.GraphQlSource;
import org.springframework.graphql.execution.ThreadLocalAccessor;
-import org.springframework.graphql.web.WebGraphQlHandler;
-import org.springframework.graphql.web.WebInterceptor;
-import org.springframework.graphql.web.webmvc.GraphQlHttpHandler;
-import org.springframework.graphql.web.webmvc.GraphQlWebSocketHandler;
-import org.springframework.graphql.web.webmvc.GraphiQlHandler;
-import org.springframework.graphql.web.webmvc.SchemaHandler;
+import org.springframework.graphql.server.WebGraphQlHandler;
+import org.springframework.graphql.server.WebGraphQlInterceptor;
+import org.springframework.graphql.server.webmvc.GraphQlHttpHandler;
+import org.springframework.graphql.server.webmvc.GraphQlWebSocketHandler;
+import org.springframework.graphql.server.webmvc.GraphiQlHandler;
+import org.springframework.graphql.server.webmvc.SchemaHandler;
+import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.converter.GenericHttpMessageConverter;
+import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
@@ -57,11 +59,11 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.function.RequestPredicates;
import org.springframework.web.servlet.function.RouterFunction;
import org.springframework.web.servlet.function.RouterFunctions;
+import org.springframework.web.servlet.function.ServerRequest;
import org.springframework.web.servlet.function.ServerResponse;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;
import org.springframework.web.socket.server.support.WebSocketHandlerMapping;
-import org.springframework.web.socket.server.support.WebSocketHttpRequestHandler;
import graphql.GraphQL;
@@ -77,116 +79,122 @@ import graphql.GraphQL;
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass({ GraphQL.class, GraphQlHttpHandler.class })
-@ConditionalOnBean(GraphQlService.class)
+@ConditionalOnBean(ExecutionGraphQlService.class)
@AutoConfigureAfter(GraphQlAutoConfiguration.class)
@EnableConfigurationProperties(GraphQlCorsProperties.class)
public class GraphQlWebMvcAutoConfiguration {
private static final Log logger = LogFactory.getLog(GraphQlWebMvcAutoConfiguration.class);
- @Bean
- @ConditionalOnMissingBean
- public GraphQlHttpHandler graphQlHttpHandler(WebGraphQlHandler webGraphQlHandler) {
- return new GraphQlHttpHandler(webGraphQlHandler);
- }
-
- @Bean
- @ConditionalOnMissingBean
- public WebGraphQlHandler webGraphQlHandler(GraphQlService service,
- ObjectProvider<WebInterceptor> interceptorsProvider,
- ObjectProvider<ThreadLocalAccessor> accessorsProvider) {
- return WebGraphQlHandler.builder(service)
- .interceptors(interceptorsProvider.orderedStream().collect(Collectors.toList()))
- .threadLocalAccessors(accessorsProvider.orderedStream().collect(Collectors.toList())).build();
- }
-
- @Bean
- public RouterFunction<ServerResponse> graphQlRouterFunction(GraphQlHttpHandler handler, GraphQlSource graphQlSource,
- GraphQlProperties properties, ResourceLoader resourceLoader) {
-
- String graphQLPath = properties.getPath();
- if (logger.isInfoEnabled()) {
- logger.info("GraphQL endpoint HTTP POST " + graphQLPath);
- }
-
- RouterFunctions.Builder builder = RouterFunctions.route()
- .GET(graphQLPath,
- (request) -> ServerResponse.status(HttpStatus.METHOD_NOT_ALLOWED)
- .headers((headers) -> headers.setAllow(Collections.singleton(HttpMethod.POST))).build())
- .POST(graphQLPath, RequestPredicates.contentType(MediaType.APPLICATION_JSON)
- .and(RequestPredicates.accept(MediaType.APPLICATION_JSON)), handler::handleRequest);
-
- if (properties.getGraphiql().isEnabled()) {
- GraphiQlHandler graphiQLHandler = new GraphiQlHandler(graphQLPath, properties.getWebsocket().getPath());
- builder = builder.GET(properties.getGraphiql().getPath(), graphiQLHandler::handleRequest);
- }
-
- if (properties.getSchema().getPrinter().isEnabled()) {
- SchemaHandler schemaHandler = new SchemaHandler(graphQlSource);
- builder = builder.GET(graphQLPath + "/schema", schemaHandler::handleRequest);
- }
-
- return builder.build();
- }
-
- @Configuration(proxyBeanMethods = false)
- public static class GraphQlEndpointCorsConfiguration implements WebMvcConfigurer {
-
- final GraphQlProperties graphQlProperties;
-
- final GraphQlCorsProperties corsProperties;
-
- public GraphQlEndpointCorsConfiguration(GraphQlProperties graphQlProps, GraphQlCorsProperties corsProps) {
- this.graphQlProperties = graphQlProps;
- this.corsProperties = corsProps;
- }
-
- @Override
- public void addCorsMappings(CorsRegistry registry) {
- CorsConfiguration configuration = this.corsProperties.toCorsConfiguration();
- if (configuration != null) {
- registry.addMapping(this.graphQlProperties.getPath()).combine(configuration);
- }
- }
-
- }
-
- @Configuration(proxyBeanMethods = false)
- @ConditionalOnClass({ ServerContainer.class, WebSocketHandler.class })
- @ConditionalOnProperty(prefix = "spring.graphql.websocket", name = "path")
- public static class WebSocketConfiguration {
-
- @Bean
- @ConditionalOnMissingBean
- public GraphQlWebSocketHandler graphQlWebSocketHandler(WebGraphQlHandler webGraphQlHandler,
- GraphQlProperties properties, HttpMessageConverters converters) {
-
- return new GraphQlWebSocketHandler(webGraphQlHandler, getJsonConverter(converters),
- properties.getWebsocket().getConnectionInitTimeout());
- }
-
- @SuppressWarnings("unchecked")
- private static GenericHttpMessageConverter<Object> getJsonConverter(HttpMessageConverters converters) {
- return converters.getConverters().stream()
- .filter((candidate) -> candidate.canRead(Map.class, MediaType.APPLICATION_JSON)).findFirst()
- .map((converter) -> (GenericHttpMessageConverter<Object>) converter)
- .orElseThrow(() -> new IllegalStateException("No JSON converter"));
- }
-
- @Bean
- public HandlerMapping graphQlWebSocketMapping(GraphQlWebSocketHandler handler, GraphQlProperties properties) {
- String path = properties.getWebsocket().getPath();
- if (logger.isInfoEnabled()) {
- logger.info("GraphQL endpoint WebSocket " + path);
- }
- WebSocketHandlerMapping mapping = new WebSocketHandlerMapping();
- mapping.setWebSocketUpgradeMatch(true);
- mapping.setUrlMap(Collections.singletonMap(path,
- new WebSocketHttpRequestHandler(handler, new DefaultHandshakeHandler())));
- mapping.setOrder(2); // Ahead of HTTP endpoint ("routerFunctionMapping" bean)
- return mapping;
- }
-
- }
+ private static MediaType[] SUPPORTED_MEDIA_TYPES = new MediaType[] { MediaType.APPLICATION_GRAPHQL,
+ MediaType.APPLICATION_JSON };
+
+ @Bean
+ @ConditionalOnMissingBean
+ public GraphQlHttpHandler graphQlHttpHandler(final WebGraphQlHandler webGraphQlHandler) {
+ return new GraphQlHttpHandler(webGraphQlHandler);
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public WebGraphQlHandler webGraphQlHandler(final ExecutionGraphQlService service,
+ final ObjectProvider<WebGraphQlInterceptor> interceptorsProvider,
+ final ObjectProvider<ThreadLocalAccessor> accessorsProvider) {
+ return WebGraphQlHandler.builder(service)
+ .interceptors(interceptorsProvider.orderedStream().collect(Collectors.toList()))
+ .threadLocalAccessors(accessorsProvider.orderedStream().collect(Collectors.toList())).build();
+ }
+
+ @Bean
+ public RouterFunction<ServerResponse> graphQlRouterFunction(final GraphQlHttpHandler httpHandler,
+ final GraphQlSource graphQlSource, final GraphQlProperties properties) {
+ String path = properties.getPath();
+ logger.info(LogMessage.format("GraphQL endpoint HTTP POST %s", path));
+ RouterFunctions.Builder builder = RouterFunctions.route();
+ builder = builder.GET(path, this::onlyAllowPost);
+ builder = builder.POST(path, RequestPredicates.contentType(SUPPORTED_MEDIA_TYPES)
+ .and(RequestPredicates.accept(SUPPORTED_MEDIA_TYPES)), httpHandler::handleRequest);
+ if (properties.getGraphiql().isEnabled()) {
+ GraphiQlHandler graphiQLHandler = new GraphiQlHandler(path, properties.getWebsocket().getPath());
+ builder = builder.GET(properties.getGraphiql().getPath(), graphiQLHandler::handleRequest);
+ }
+ if (properties.getSchema().getPrinter().isEnabled()) {
+ SchemaHandler schemaHandler = new SchemaHandler(graphQlSource);
+ builder = builder.GET(path + "/schema", schemaHandler::handleRequest);
+ }
+ return builder.build();
+ }
+
+ private ServerResponse onlyAllowPost(final ServerRequest request) {
+ return ServerResponse.status(HttpStatus.METHOD_NOT_ALLOWED).headers(this::onlyAllowPost).build();
+ }
+
+ private void onlyAllowPost(final HttpHeaders headers) {
+ headers.setAllow(Collections.singleton(HttpMethod.POST));
+ }
+
+ @Configuration(proxyBeanMethods = false)
+ public static class GraphQlEndpointCorsConfiguration implements WebMvcConfigurer {
+
+ final GraphQlProperties graphQlProperties;
+
+ final GraphQlCorsProperties corsProperties;
+
+ public GraphQlEndpointCorsConfiguration(final GraphQlProperties graphQlProps, final GraphQlCorsProperties corsProps) {
+ this.graphQlProperties = graphQlProps;
+ this.corsProperties = corsProps;
+ }
+
+ @Override
+ public void addCorsMappings(final CorsRegistry registry) {
+ CorsConfiguration configuration = this.corsProperties.toCorsConfiguration();
+ if (configuration != null) {
+ registry.addMapping(this.graphQlProperties.getPath()).combine(configuration);
+ }
+ }
+
+ }
+
+ @Configuration(proxyBeanMethods = false)
+ @ConditionalOnClass({ ServerContainer.class, WebSocketHandler.class })
+ @ConditionalOnProperty(prefix = "spring.graphql.websocket", name = "path")
+ public static class WebSocketConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean
+ public GraphQlWebSocketHandler graphQlWebSocketHandler(final WebGraphQlHandler webGraphQlHandler,
+ final GraphQlProperties properties, final HttpMessageConverters converters) {
+ return new GraphQlWebSocketHandler(webGraphQlHandler, getJsonConverter(converters),
+ properties.getWebsocket().getConnectionInitTimeout());
+ }
+
+ private GenericHttpMessageConverter<Object> getJsonConverter(final HttpMessageConverters converters) {
+ return converters.getConverters().stream().filter(this::canReadJsonMap).findFirst()
+ .map(this::asGenericHttpMessageConverter)
+ .orElseThrow(() -> new IllegalStateException("No JSON converter"));
+ }
+
+ private boolean canReadJsonMap(final HttpMessageConverter<?> candidate) {
+ return candidate.canRead(Map.class, MediaType.APPLICATION_JSON);
+ }
+
+ @SuppressWarnings("unchecked")
+ private GenericHttpMessageConverter<Object> asGenericHttpMessageConverter(final HttpMessageConverter<?> converter) {
+ return (GenericHttpMessageConverter<Object>) converter;
+ }
+
+ @Bean
+ public HandlerMapping graphQlWebSocketMapping(final GraphQlWebSocketHandler handler, final GraphQlProperties properties) {
+ String path = properties.getWebsocket().getPath();
+ logger.info(LogMessage.format("GraphQL endpoint WebSocket %s", path));
+ WebSocketHandlerMapping mapping = new WebSocketHandlerMapping();
+ mapping.setWebSocketUpgradeMatch(true);
+ mapping.setUrlMap(Collections.singletonMap(path,
+ handler.asWebSocketHttpRequestHandler(new DefaultHandshakeHandler())));
+ mapping.setOrder(2); // Ahead of HTTP endpoint ("routerFunctionMapping" bean)
+ return mapping;
+ }
+
+ }
}