You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2020/05/28 14:11:28 UTC
[sling-whiteboard] branch master updated: GraphiQL client-side
queries work
This is an automated email from the ASF dual-hosted git repository.
bdelacretaz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-whiteboard.git
The following commit(s) were added to refs/heads/master by this push:
new 04c602a GraphiQL client-side queries work
04c602a is described below
commit 04c602ab741d6905aec4afdd64e000a824dc066f
Author: Bertrand Delacretaz <bd...@apache.org>
AuthorDate: Thu May 28 16:11:13 2020 +0200
GraphiQL client-side queries work
---
org.apache.sling.graphql.samples.website/README.md | 57 ++++++++++++++++----
.../datafetchers/ArticlesWithTextFetcher.java | 63 ++++++++++++++++++++++
.../samples/website/datafetchers/FetcherUtil.java | 48 +++++++++++++++++
.../datafetchers/SamplesDataFetcherProvider.java | 2 +
.../website/datafetchers/SeeAlsoDataFetcher.java | 14 ++++-
.../apps/samples/servlet/GQLschema.jsp | 25 +++++++++
.../features/feature-graphql-example-website.json | 4 +-
7 files changed, 200 insertions(+), 13 deletions(-)
diff --git a/org.apache.sling.graphql.samples.website/README.md b/org.apache.sling.graphql.samples.website/README.md
index c8b4b94..a353235 100644
--- a/org.apache.sling.graphql.samples.website/README.md
+++ b/org.apache.sling.graphql.samples.website/README.md
@@ -3,7 +3,17 @@ Apache Sling GraphQL demo website
This is a work in progress demo of the Sling GraphQL Core.
-## Status
+It demonstrates both server-side GraphQL queries, used for content aggregation, and the
+more traditional client-side queries, using the same GraphQL schemas and data fetching
+Java components for both variants.
+
+Besides the page rendering code there's not much: GraphQL schema definitions and a few
+Java classes used for aggregating or enhancing content and for content queries.
+
+For now there's no pagination of query results, just arbitrary limits on the number
+of results returned.
+
+## Demo Website
A website with rich navigation is implemented with server-side GraphQL queries and client-side
Handlebars templates for HTML rendering.
@@ -12,16 +22,45 @@ http://localhost:8080/content/graphql-website-demo.html is the entry point, afte
this as described below.
The rendering is based on JSON content that's aggregated server-side using GraphQL queries
-to provide all the page content, navigation etc. in a single request.</p>
+to provide all the page content, navigation etc. in a single request.
+
+This is just an initial prototype. As a next step I'd like to render the article pages using
+server-side Handlebars templates and implement a few single-page applications for search
+and browsing. While keeping the articles rendering server-side (so that they make sense
+for Web search engines for example) and ideally using the same languages (GraphQL and
+Handlebars) either server- or client-side.
+
+## Client-side GraphQL queries
+
+Client-side queries work using an external GraphiQL client (or any suitable client) that
+talks to http://localhost:8080/graphql.json
+
+For now only simple queries are supported, like:
+
+ {
+ article(withText: "jacobi") {
+ path
+ title
+ tags
+ seeAlso {
+ title
+ path
+ }
+ }
+ }
-This is just an initial prototype. I'd like to move closer to
-[Progressive Web Apps](https://en.wikipedia.org/wiki/Progressive_web_application) techniques,
-generating a basic rendering server-side and enhancing it with CSS and JavaScript
-client-side.
+Besides fixing the `DataFetcher`s to use the correct context Resource, setting this up
+only required activating the `GraphQLServlet` (in the Feature Model that starts this demo)
+and adding the below schema file. Everything else is shared between the server-side and
+client-side query variants.
-The GraphQL schemas and `DataFetchers` that have been implemented will be usable for more
-traditional client-side GraphQL queries as well, once that's setup. As that side of things has
-less unknowns, I'm focusing on the less usual server-side GraphQL concepts for now.
+ # /apps/samples/servlet/GQLschema.jsp
+ type Query {
+ ## fetch:samples/articlesWithText
+ article (withText : String) : [Article]
+ }
+
+ <%@include file="/apps/samples/common/GQLschema.jsp" %>
## How to run this
diff --git a/org.apache.sling.graphql.samples.website/src/main/java/org/apache/sling/graphql/samples/website/datafetchers/ArticlesWithTextFetcher.java b/org.apache.sling.graphql.samples.website/src/main/java/org/apache/sling/graphql/samples/website/datafetchers/ArticlesWithTextFetcher.java
new file mode 100644
index 0000000..8005a0e
--- /dev/null
+++ b/org.apache.sling.graphql.samples.website/src/main/java/org/apache/sling/graphql/samples/website/datafetchers/ArticlesWithTextFetcher.java
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+package org.apache.sling.graphql.samples.website.datafetchers;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.graphql.samples.website.models.SlingWrappers;
+
+import graphql.schema.DataFetcher;
+import graphql.schema.DataFetchingEnvironment;
+
+class ArticlesWithTextFetcher implements DataFetcher<Object> {
+
+ public static final String NAME = "articlesWithText";
+ public static final String P_WITH_TEXT = "withText";
+
+ private final Resource resource;
+
+ ArticlesWithTextFetcher(Resource resource) {
+ this.resource = resource;
+ }
+
+ @Override
+ public Object get(DataFetchingEnvironment environment) throws Exception {
+ final String expectedText = environment.getArgument(P_WITH_TEXT);
+ final String jcrQuery = String.format(
+ "/jcr:root/content/articles//*[jcr:contains(@text, '%s') or jcr:contains(@title, '%s')]",
+ expectedText, expectedText);
+
+ final List<Map<String, Object>> result = new ArrayList<>();
+ final Iterator<Resource> it = resource.getResourceResolver().findResources(jcrQuery, "xpath");
+ // TODO should use pagination
+ int counter = 451;
+ while(it.hasNext()) {
+ if(--counter <= 0) {
+ break;
+ }
+ result.add(SlingWrappers.resourceWrapper(it.next()));
+ }
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/org.apache.sling.graphql.samples.website/src/main/java/org/apache/sling/graphql/samples/website/datafetchers/FetcherUtil.java b/org.apache.sling.graphql.samples.website/src/main/java/org/apache/sling/graphql/samples/website/datafetchers/FetcherUtil.java
new file mode 100644
index 0000000..514feba
--- /dev/null
+++ b/org.apache.sling.graphql.samples.website/src/main/java/org/apache/sling/graphql/samples/website/datafetchers/FetcherUtil.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+package org.apache.sling.graphql.samples.website.datafetchers;
+
+import java.util.Map;
+
+import org.apache.sling.api.resource.Resource;
+import graphql.schema.DataFetchingEnvironment;
+
+class FetcherUtil {
+
+ /** Return the "source" Resource to use, preferably the one provided
+ * by the DataFetchingEnvironment, otherwise the supplied base Resource.
+ */
+ static Resource getSourceResource(DataFetchingEnvironment env, Resource base) {
+ Resource result = base;
+ String path = null;
+ final Object o = env.getSource();
+ if(o instanceof Map) {
+ final Map<?, ?> m = (Map)o;
+ path = String.valueOf(m.get("path"));
+ }
+ if(path != null) {
+ final Resource r = base.getResourceResolver().getResource(base, path);
+ if(r != null) {
+ result = r;
+ }
+ }
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/org.apache.sling.graphql.samples.website/src/main/java/org/apache/sling/graphql/samples/website/datafetchers/SamplesDataFetcherProvider.java b/org.apache.sling.graphql.samples.website/src/main/java/org/apache/sling/graphql/samples/website/datafetchers/SamplesDataFetcherProvider.java
index b6b6739..850efac 100644
--- a/org.apache.sling.graphql.samples.website/src/main/java/org/apache/sling/graphql/samples/website/datafetchers/SamplesDataFetcherProvider.java
+++ b/org.apache.sling.graphql.samples.website/src/main/java/org/apache/sling/graphql/samples/website/datafetchers/SamplesDataFetcherProvider.java
@@ -46,6 +46,8 @@ public class SamplesDataFetcherProvider implements DataFetcherProvider {
return new ArticlesBySectionFetcher(r);
} else if(NavigationDataFetcher.NAME.equals(name)) {
return new NavigationDataFetcher(r);
+ } else if(ArticlesWithTextFetcher.NAME.equals(name)) {
+ return new ArticlesWithTextFetcher(r);
}
return null;
}
diff --git a/org.apache.sling.graphql.samples.website/src/main/java/org/apache/sling/graphql/samples/website/datafetchers/SeeAlsoDataFetcher.java b/org.apache.sling.graphql.samples.website/src/main/java/org/apache/sling/graphql/samples/website/datafetchers/SeeAlsoDataFetcher.java
index e863761..ecd9722 100644
--- a/org.apache.sling.graphql.samples.website/src/main/java/org/apache/sling/graphql/samples/website/datafetchers/SeeAlsoDataFetcher.java
+++ b/org.apache.sling.graphql.samples.website/src/main/java/org/apache/sling/graphql/samples/website/datafetchers/SeeAlsoDataFetcher.java
@@ -54,13 +54,23 @@ class SeeAlsoDataFetcher implements DataFetcher<Object> {
return result;
}
+ private String getSourcePath(DataFetchingEnvironment env) {
+ String result = null;
+ final Object o = env.getSource();
+ if(o instanceof Map) {
+ final Map<?, ?> m = (Map)o;
+ result = String.valueOf(m.get("path"));
+ }
+ return result;
+ }
+
@Override
- public Object get(DataFetchingEnvironment environment) throws Exception {
+ public Object get(DataFetchingEnvironment env) throws Exception {
// Our "see also" field only contains node names - this demonstrates
// using a query to get their full paths
//
- final ValueMap vm = resource.adaptTo(ValueMap.class);
+ final ValueMap vm = FetcherUtil.getSourceResource(env, resource).adaptTo(ValueMap.class);
if(vm != null) {
return Arrays
.stream(vm.get(NAME, String[].class))
diff --git a/org.apache.sling.graphql.samples.website/src/main/resources/SLING-INF/initial-content/apps/samples/servlet/GQLschema.jsp b/org.apache.sling.graphql.samples.website/src/main/resources/SLING-INF/initial-content/apps/samples/servlet/GQLschema.jsp
new file mode 100644
index 0000000..2c8e0de
--- /dev/null
+++ b/org.apache.sling.graphql.samples.website/src/main/resources/SLING-INF/initial-content/apps/samples/servlet/GQLschema.jsp
@@ -0,0 +1,25 @@
+<%--
+* 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.
+--%>
+
+type Query {
+ ## fetch:samples/articlesWithText
+ article (withText : String) : [Article]
+}
+
+<%@include file="/apps/samples/common/GQLschema.jsp" %>
\ No newline at end of file
diff --git a/org.apache.sling.graphql.samples.website/src/main/resources/features/feature-graphql-example-website.json b/org.apache.sling.graphql.samples.website/src/main/resources/features/feature-graphql-example-website.json
index de1ad43..816323a 100644
--- a/org.apache.sling.graphql.samples.website/src/main/resources/features/feature-graphql-example-website.json
+++ b/org.apache.sling.graphql.samples.website/src/main/resources/features/feature-graphql-example-website.json
@@ -10,7 +10,7 @@
"id" : "org.apache.sling:org.apache.sling.graphql.core:0.0.1-SNAPSHOT",
"configurations" : {
"org.apache.sling.graphql.core.GraphQLServlet~default" : {
- "sling.servlet.resourceTypes" : "graphql/servlet",
+ "sling.servlet.resourceTypes" : "samples/servlet",
"sling.servlet.extensions": "json",
"sling.servlet.methods": [ "GET", "POST" ]
}
@@ -41,7 +41,7 @@
"allow jcr:read on /graphql",
"end",
"set properties on /graphql",
- "set sling:resourceType{String} to graphql/servlet",
+ "set sling:resourceType{String} to samples/servlet",
"end"
]
}
\ No newline at end of file