You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2022/01/23 13:44:53 UTC

[isis] 02/02: ISIS-2947: sets up schema only after metamodel fully introspected.

This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch ISIS-2947
in repository https://gitbox.apache.org/repos/asf/isis.git

commit c641861c9a4cb3143bf3903541c731bd448d6178
Author: Dan Haywood <da...@haywood-associates.co.uk>
AuthorDate: Sun Jan 23 13:44:36 2022 +0000

    ISIS-2947: sets up schema only after metamodel fully introspected.
---
 .../metamodel/specloader/SpecificationLoader.java  |   2 +
 .../viewer/source/GraphQlServiceForIsis.java       |  37 +++++++
 .../viewer/source/GraphQlSourceForIsis.java        | 123 +++++++++++++++++++++
 .../graphql/viewer/source/MyGraphSource.java       |  84 --------------
 .../viewer/source/dummydomain/LeaseRepository.java |   9 --
 5 files changed, 162 insertions(+), 93 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java
index a54d242..fec274a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java
@@ -18,6 +18,8 @@
  */
 package org.apache.isis.core.metamodel.specloader;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Optional;
 import java.util.function.Consumer;
 
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
new file mode 100644
index 0000000..260dad7
--- /dev/null
+++ b/incubator/viewers/graphql/viewer/src/main/java/org/apache/isis/viewer/graphql/viewer/source/GraphQlServiceForIsis.java
@@ -0,0 +1,37 @@
+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.execution.BatchLoaderRegistry;
+import org.springframework.graphql.execution.ExecutionGraphQlService;
+import org.springframework.graphql.execution.GraphQlSource;
+import org.springframework.stereotype.Service;
+
+import lombok.RequiredArgsConstructor;
+
+import reactor.core.publisher.Mono;
+
+/**
+ * Defers calling of {@link GraphQlSourceForIsis#schema()} until after the metamodel is fully introspected.
+ */
+@Service()
+@RequiredArgsConstructor(onConstructor_ = {@Inject})
+public class GraphQlServiceForIsis implements GraphQlService {
+
+    private final BatchLoaderRegistry batchLoaderRegistry;
+    private final GraphQlSource graphQlSource;
+
+    ExecutionGraphQlService delegate;
+
+    @Override
+    public Mono<RequestOutput> execute(RequestInput input) {
+        if(delegate == null) {
+            delegate = new ExecutionGraphQlService(graphQlSource);
+            delegate.addDataLoaderRegistrar(batchLoaderRegistry);
+        }
+        return delegate.execute(input);
+    }
+}
diff --git a/incubator/viewers/graphql/viewer/src/main/java/org/apache/isis/viewer/graphql/viewer/source/GraphQlSourceForIsis.java b/incubator/viewers/graphql/viewer/src/main/java/org/apache/isis/viewer/graphql/viewer/source/GraphQlSourceForIsis.java
new file mode 100644
index 0000000..82cd012
--- /dev/null
+++ b/incubator/viewers/graphql/viewer/src/main/java/org/apache/isis/viewer/graphql/viewer/source/GraphQlSourceForIsis.java
@@ -0,0 +1,123 @@
+package org.apache.isis.viewer.graphql.viewer.source;
+
+import java.util.concurrent.CountDownLatch;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+
+import org.springframework.graphql.execution.GraphQlSource;
+import org.springframework.stereotype.Service;
+
+import org.apache.isis.applib.services.registry.ServiceRegistry;
+import org.apache.isis.core.config.IsisConfiguration;
+import org.apache.isis.core.config.environment.IsisSystemEnvironment;
+import org.apache.isis.core.config.metamodel.specloader.IntrospectionMode;
+import org.apache.isis.core.metamodel.specloader.SpecificationLoaderDefault;
+
+import lombok.RequiredArgsConstructor;
+import lombok.val;
+
+import graphql.GraphQL;
+import graphql.Scalars;
+import graphql.execution.instrumentation.tracing.TracingInstrumentation;
+import graphql.schema.DataFetcher;
+import graphql.schema.GraphQLCodeRegistry;
+import graphql.schema.GraphQLFieldDefinition;
+import graphql.schema.GraphQLObjectType;
+import graphql.schema.GraphQLSchema;
+
+import static graphql.schema.FieldCoordinates.coordinates;
+
+@Service()
+@RequiredArgsConstructor(onConstructor_ = {@Inject})
+public class GraphQlSourceForIsis implements GraphQlSource {
+
+    private final ServiceRegistry serviceRegistry;
+    private final SpecificationLoaderDefault specificationLoader;
+    private final IsisConfiguration isisConfiguration;
+    private final IsisSystemEnvironment isisSystemEnvironment;
+    private final ExecutionStrategyResolvingWithinInteraction executionStrategy;
+
+    private final CountDownLatch countDownLatch = new CountDownLatch(1);
+
+    @PostConstruct
+    public void init() {
+        boolean fullyIntrospect = IntrospectionMode.isFullIntrospect(isisConfiguration, isisSystemEnvironment);
+        if (!fullyIntrospect) {
+            throw new IllegalStateException("GraphQL requires full introspection mode");
+        }
+    }
+
+    @Override
+    public GraphQL graphQl() {
+        return GraphQL.newGraphQL(schema())
+                .instrumentation(new TracingInstrumentation())
+                .queryExecutionStrategy(executionStrategy)
+                .build();
+    }
+
+    @Override
+    public GraphQLSchema schema() {
+
+        val fullyIntrospected = specificationLoader.isMetamodelFullyIntrospected();
+        if(!fullyIntrospected) {
+            throw new IllegalStateException("Metamodel is not fully introspected");
+        }
+
+//        // type LeaseRepository {
+//        //     numLeases: Int
+//        // }
+//        val leaseRepository_numLeases = GraphQLFieldDefinition.newFieldDefinition()
+//                .name("numLeases")
+//                .type(Scalars.GraphQLInt)
+//                .build();
+//        val leaseRepositoryType = GraphQLObjectType.newObject()
+//                .name("LeaseRepository")
+//                .field(leaseRepository_numLeases)
+//                .build();
+
+//        // type Query {
+//        //     leaseRepo: LeaseRepository
+//        // }
+//        val query_leaseRepo = GraphQLFieldDefinition.newFieldDefinition()
+//                .name("leaseRepo")
+//                .type(GraphQLTypeReference.typeRef(leaseRepositoryType.getName()))
+//                .build();
+//        GraphQLObjectType query = GraphQLObjectType.newObject()
+//                .name("Query")
+//                .field(query_leaseRepo)
+//                .build();
+//
+//        val codeRegistry = GraphQLCodeRegistry.newCodeRegistry()
+//                .dataFetcher(coordinates(query.getName(), query_leaseRepo.getName()),
+//                        (DataFetcher<Object>) environment -> leaseRepository)
+//                .dataFetcher(coordinates(leaseRepositoryType.getName(), leaseRepository_numLeases.getName()),
+//                        (DataFetcher<Object>) environment -> leaseRepository.numLeases)
+//                .build();
+
+        // type Query {
+        //     numServices: Int
+        // }
+        val query_numServices = GraphQLFieldDefinition.newFieldDefinition()
+                .name("numServices")
+                .type(Scalars.GraphQLInt)
+                .build();
+        GraphQLObjectType query = GraphQLObjectType.newObject()
+                .name("Query")
+                .field(query_numServices)
+                .build();
+
+
+        val codeRegistry = GraphQLCodeRegistry.newCodeRegistry()
+        .dataFetcher(coordinates(query.getName(), query_numServices.getName()),
+                (DataFetcher<Object>) environment -> this.serviceRegistry.streamRegisteredBeans().count())
+        .build();
+
+        return GraphQLSchema.newSchema()
+                .query(query)
+                // .additionalType(leaseRepositoryType)
+                .codeRegistry(codeRegistry)
+                .build();
+    }
+
+}
diff --git a/incubator/viewers/graphql/viewer/src/main/java/org/apache/isis/viewer/graphql/viewer/source/MyGraphSource.java b/incubator/viewers/graphql/viewer/src/main/java/org/apache/isis/viewer/graphql/viewer/source/MyGraphSource.java
deleted file mode 100644
index 18ae6f1..0000000
--- a/incubator/viewers/graphql/viewer/src/main/java/org/apache/isis/viewer/graphql/viewer/source/MyGraphSource.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package org.apache.isis.viewer.graphql.viewer.source;
-
-import javax.inject.Inject;
-
-import org.springframework.graphql.execution.GraphQlSource;
-import org.springframework.stereotype.Service;
-
-import org.apache.isis.viewer.graphql.viewer.source.dummydomain.LeaseRepository;
-
-import lombok.RequiredArgsConstructor;
-import lombok.val;
-
-import graphql.GraphQL;
-import graphql.Scalars;
-import graphql.execution.AsyncExecutionStrategy;
-import graphql.execution.instrumentation.tracing.TracingInstrumentation;
-import graphql.schema.DataFetcher;
-import graphql.schema.GraphQLCodeRegistry;
-import graphql.schema.GraphQLFieldDefinition;
-import graphql.schema.GraphQLObjectType;
-import graphql.schema.GraphQLSchema;
-import graphql.schema.GraphQLTypeReference;
-
-import static graphql.schema.FieldCoordinates.coordinates;
-
-@Service
-@RequiredArgsConstructor(onConstructor_ = {@Inject})
-public class MyGraphSource implements GraphQlSource {
-
-    private final LeaseRepository leaseRepository;
-    private final ExecutionStrategyResolvingWithinInteraction executionStrategy;
-
-    @Override
-    public GraphQL graphQl() {
-        // val asyncExecutionStrategy = new AsyncExecutionStrategy();
-        return GraphQL.newGraphQL(schema())
-                .instrumentation(new TracingInstrumentation())
-                .queryExecutionStrategy(executionStrategy)
-                .build();
-    }
-
-    @Override
-    public GraphQLSchema schema() {
-
-        // type LeaseRepository {
-        //     numLeases: Int
-        // }
-        val leaseRepository_numLeases = GraphQLFieldDefinition.newFieldDefinition()
-                .name("numLeases")
-                .type(Scalars.GraphQLInt)
-                .build();
-        val leaseRepositoryType = GraphQLObjectType.newObject()
-                .name("LeaseRepository")
-                .field(leaseRepository_numLeases)
-                .build();
-
-        // type Query {
-        //     leaseRepo: LeaseRepository
-        // }
-        val query_leaseRepo = GraphQLFieldDefinition.newFieldDefinition()
-                .name("leaseRepo")
-                .type(GraphQLTypeReference.typeRef(leaseRepositoryType.getName()))
-                .build();
-        GraphQLObjectType query = GraphQLObjectType.newObject()
-                .name("Query")
-                .field(query_leaseRepo)
-                .build();
-
-        val codeRegistry = GraphQLCodeRegistry.newCodeRegistry()
-                .dataFetcher(coordinates(query.getName(), query_leaseRepo.getName()),
-                        (DataFetcher<Object>) environment -> leaseRepository)
-                .dataFetcher(coordinates(leaseRepositoryType.getName(), leaseRepository_numLeases.getName()),
-                        (DataFetcher<Object>) environment -> leaseRepository.numLeases)
-                .build();
-
-
-        return GraphQLSchema.newSchema()
-                .query(query)
-                .additionalType(leaseRepositoryType)
-                .codeRegistry(codeRegistry)
-                .build();
-    }
-
-}
diff --git a/incubator/viewers/graphql/viewer/src/main/java/org/apache/isis/viewer/graphql/viewer/source/dummydomain/LeaseRepository.java b/incubator/viewers/graphql/viewer/src/main/java/org/apache/isis/viewer/graphql/viewer/source/dummydomain/LeaseRepository.java
deleted file mode 100644
index 2aceb33..0000000
--- a/incubator/viewers/graphql/viewer/src/main/java/org/apache/isis/viewer/graphql/viewer/source/dummydomain/LeaseRepository.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.apache.isis.viewer.graphql.viewer.source.dummydomain;
-
-import org.springframework.stereotype.Service;
-
-@Service
-public class LeaseRepository {
-
-    public int numLeases = 5;
-}