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/12 15:07:59 UTC
[sling-org-apache-sling-graphql-core] branch master updated: Take
request selectors into account for schema generation
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-org-apache-sling-graphql-core.git
The following commit(s) were added to refs/heads/master by this push:
new d3b8c21 Take request selectors into account for schema generation
d3b8c21 is described below
commit d3b8c21e571fb453e8ef301f438ab8674932d92f
Author: Bertrand Delacretaz <bd...@apache.org>
AuthorDate: Tue May 12 17:07:43 2020 +0200
Take request selectors into account for schema generation
---
.../graphql/core/engine/GraphQLResourceQuery.java | 12 ++++---
.../sling/graphql/core/json/JsonSerializer.java | 15 ++++++++-
.../graphql/core/schema/DefaultSchemaProvider.java | 11 ++++++-
.../core/scripting/GraphQLScriptEngine.java | 2 +-
.../sling/graphql/core/servlet/GraphQLServlet.java | 3 +-
.../core/engine/GraphQLResourceQueryTest.java | 24 +++++++++++---
.../core/it/GraphQLScriptingTestSupport.java | 17 ----------
.../sling/graphql/core/it/GraphQLServletIT.java | 18 ++++++----
.../graphql/core/it/PipeDataFetcherProvider.java | 20 +++++-------
.../graphql/core/mocks/MockSchemaProvider.java | 38 +++++++++++++++-------
.../apps/graphql/test/two/testing.GQLschema.jsp | 35 ++++++++++++++++++++
src/test/resources/test-schema-selected-foryou.txt | 32 ++++++++++++++++++
12 files changed, 169 insertions(+), 58 deletions(-)
diff --git a/src/main/java/org/apache/sling/graphql/core/engine/GraphQLResourceQuery.java b/src/main/java/org/apache/sling/graphql/core/engine/GraphQLResourceQuery.java
index 6c43d22..81daff4 100644
--- a/src/main/java/org/apache/sling/graphql/core/engine/GraphQLResourceQuery.java
+++ b/src/main/java/org/apache/sling/graphql/core/engine/GraphQLResourceQuery.java
@@ -52,12 +52,14 @@ public class GraphQLResourceQuery {
private final Logger log = LoggerFactory.getLogger(getClass());
public ExecutionResult executeQuery(SchemaProvider schemaProvider, DataFetcherSelector fetchers,
- Resource r, String query) throws ScriptException {
- return executeQuery(schemaProvider, fetchers, r, query, Collections.emptyMap());
+ Resource r, String [] requestSelectors, String query) throws ScriptException {
+ return executeQuery(schemaProvider, fetchers, r, requestSelectors, query, Collections.emptyMap());
}
public ExecutionResult executeQuery(SchemaProvider schemaProvider, DataFetcherSelector fetchersSelector,
- Resource r, String query, Map<String, Object> variables) throws ScriptException {
+ Resource r,
+ String [] requestSelectors,
+ String query, Map<String, Object> variables) throws ScriptException {
if(r == null) {
throw new ScriptException("Resource is null");
}
@@ -73,7 +75,7 @@ public class GraphQLResourceQuery {
String schemaDef = null;
try {
- schemaDef = schemaProvider.getSchema(r, null);
+ schemaDef = schemaProvider.getSchema(r, requestSelectors);
} catch(Exception e) {
final ScriptException up = new ScriptException("Schema provider failed");
up.initCause(e);
@@ -146,7 +148,7 @@ public class GraphQLResourceQuery {
log.warn("No data fetcher registered for {}", def.toString());
}
} catch (IllegalArgumentException iae) {
- log.warn("Invalid fetcher definition", iae);
+ throw new IOException("Invalid fetcher definition", iae);
}
}
}
diff --git a/src/main/java/org/apache/sling/graphql/core/json/JsonSerializer.java b/src/main/java/org/apache/sling/graphql/core/json/JsonSerializer.java
index ca618d3..8c57816 100644
--- a/src/main/java/org/apache/sling/graphql/core/json/JsonSerializer.java
+++ b/src/main/java/org/apache/sling/graphql/core/json/JsonSerializer.java
@@ -22,6 +22,8 @@ package org.apache.sling.graphql.core.json;
import java.io.IOException;
import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
import com.cedarsoftware.util.io.JsonWriter;
@@ -31,13 +33,24 @@ import graphql.ExecutionResult;
public class JsonSerializer {
+ public static final Map<String, Object> WRITER_OPTIONS = new HashMap<String, Object>() {
+ private static final long serialVersionUID = 1L;
+ {
+ put(JsonWriter.TYPE, false);
+ }
+ };
+
public void sendJSON(PrintWriter out, ExecutionResult result) throws IOException {
final Object data = result.toSpecification();
if (data == null) {
throw new IOException("No data");
}
- try(JsonWriter w = new JsonWriter(new WriterOutputStream(out))) {
+ try(JsonWriter w = new JsonWriter(new WriterOutputStream(out), WRITER_OPTIONS)) {
w.write(data);
}
}
+
+ public String toJSON(Object data) {
+ return JsonWriter.objectToJson(data, JsonSerializer.WRITER_OPTIONS);
+ }
}
diff --git a/src/main/java/org/apache/sling/graphql/core/schema/DefaultSchemaProvider.java b/src/main/java/org/apache/sling/graphql/core/schema/DefaultSchemaProvider.java
index bc323ac..05017d2 100644
--- a/src/main/java/org/apache/sling/graphql/core/schema/DefaultSchemaProvider.java
+++ b/src/main/java/org/apache/sling/graphql/core/schema/DefaultSchemaProvider.java
@@ -59,7 +59,16 @@ public class DefaultSchemaProvider implements SchemaProvider {
public String getSchema(Resource r, String [] selectors) throws SchemaProviderException {
final ResourceResolver resourceResolver = r.getResourceResolver();
final MockSlingHttpServletRequest request = new MockSlingHttpServletRequest(resourceResolver);
- final String path = r.getPath() + SCHEMA_EXTENSION;
+
+ final StringBuilder sb = new StringBuilder();
+ sb.append(r.getPath());
+ if(selectors != null) {
+ for(String s : selectors) {
+ sb.append(".").append(s);
+ }
+ }
+ sb.append(SCHEMA_EXTENSION);
+ final String path = sb.toString();
request.setPathInfo(path);
final MockSlingHttpServletResponse response = new MockSlingHttpServletResponse();
final int status = response.getStatus();
diff --git a/src/main/java/org/apache/sling/graphql/core/scripting/GraphQLScriptEngine.java b/src/main/java/org/apache/sling/graphql/core/scripting/GraphQLScriptEngine.java
index ed8f33f..60a2126 100644
--- a/src/main/java/org/apache/sling/graphql/core/scripting/GraphQLScriptEngine.java
+++ b/src/main/java/org/apache/sling/graphql/core/scripting/GraphQLScriptEngine.java
@@ -61,7 +61,7 @@ public class GraphQLScriptEngine extends AbstractScriptEngine {
final Resource resource = (Resource) context.getBindings(ScriptContext.ENGINE_SCOPE)
.get(SlingBindings.RESOURCE);
final ExecutionResult result = q.executeQuery(factory.getSchemaProvider(), factory.getdataFetcherSelector(),
- resource, IOUtils.toString(reader));
+ resource, null, IOUtils.toString(reader));
final PrintWriter out = (PrintWriter) context.getBindings(ScriptContext.ENGINE_SCOPE).get(SlingBindings.OUT);
jsonSerializer.sendJSON(out, result);
} catch(Exception e) {
diff --git a/src/main/java/org/apache/sling/graphql/core/servlet/GraphQLServlet.java b/src/main/java/org/apache/sling/graphql/core/servlet/GraphQLServlet.java
index ebb99cc..8a8499e 100644
--- a/src/main/java/org/apache/sling/graphql/core/servlet/GraphQLServlet.java
+++ b/src/main/java/org/apache/sling/graphql/core/servlet/GraphQLServlet.java
@@ -128,7 +128,8 @@ public class GraphQLServlet extends SlingAllMethodsServlet {
try {
final GraphQLResourceQuery q = new GraphQLResourceQuery();
- final ExecutionResult result = q.executeQuery(schemaProvider, dataFetcherSelector, resource, query, parser.getVariables());
+ final ExecutionResult result = q.executeQuery(schemaProvider, dataFetcherSelector,
+ resource, request.getRequestPathInfo().getSelectors(), query, parser.getVariables());
jsonSerializer.sendJSON(response.getWriter(), result);
} catch(Exception ex) {
throw new IOException(ex);
diff --git a/src/test/java/org/apache/sling/graphql/core/engine/GraphQLResourceQueryTest.java b/src/test/java/org/apache/sling/graphql/core/engine/GraphQLResourceQueryTest.java
index 916bedd..3c5a0dd 100644
--- a/src/test/java/org/apache/sling/graphql/core/engine/GraphQLResourceQueryTest.java
+++ b/src/test/java/org/apache/sling/graphql/core/engine/GraphQLResourceQueryTest.java
@@ -37,6 +37,7 @@ import org.apache.sling.graphql.api.SchemaProvider;
import org.apache.sling.graphql.api.graphqljava.DataFetcherProvider;
import org.apache.sling.graphql.core.schema.DataFetcherSelector;
import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
+import org.apache.sling.graphql.core.json.JsonSerializer;
import org.apache.sling.graphql.core.mocks.DigestDataFetcher;
import org.apache.sling.graphql.core.mocks.DigestDataFetcherProvider;
import org.apache.sling.graphql.core.mocks.EchoDataFetcherProvider;
@@ -50,7 +51,7 @@ import org.mockito.Mockito;
import graphql.ExecutionResult;
public class GraphQLResourceQueryTest {
- private final SchemaProvider schemaProvider = new MockSchemaProvider();
+ private SchemaProvider schemaProvider = new MockSchemaProvider("test-schema");
private DataFetcherSelector dataFetchersSelector;
private Resource resource;
@@ -79,15 +80,20 @@ public class GraphQLResourceQueryTest {
registerDataFetcherProvider("test", new FailingDataFetcherProvider("echo"));
registerDataFetcherProvider("failure", new FailingDataFetcherProvider("fail"));
registerDataFetcherProvider("test", new EchoDataFetcherProvider("static", staticData));
+ registerDataFetcherProvider("test", new EchoDataFetcherProvider("fortyTwo", 42));
registerDataFetcherProvider("test", new DigestDataFetcherProvider());
dataFetchersSelector = new DataFetcherSelector(context.bundleContext());
}
private String queryJSON(String stmt) throws Exception {
- final ExecutionResult result = new GraphQLResourceQuery().executeQuery(schemaProvider, dataFetchersSelector, resource, stmt);
+ return queryJSON(stmt, null);
+ }
+
+ private String queryJSON(String stmt, String [] selectors) throws Exception {
+ final ExecutionResult result = new GraphQLResourceQuery().executeQuery(schemaProvider, dataFetchersSelector, resource, selectors, stmt);
assertTrue("Expecting no errors: " + result.getErrors(), result.getErrors().isEmpty());
- return JsonWriter.objectToJson(result);
+ return new JsonSerializer().toJSON(result);
}
@Test
@@ -131,9 +137,19 @@ public class GraphQLResourceQueryTest {
public void dataFetcherFailureTest() throws Exception {
try {
final String stmt = "{ currentResource { failure } }";
- new GraphQLResourceQuery().executeQuery(schemaProvider, dataFetchersSelector, resource, stmt);
+ new GraphQLResourceQuery().executeQuery(schemaProvider, dataFetchersSelector, resource, null, stmt);
} catch(RuntimeException rex) {
assertThat(rex.getMessage(), equalTo("FailureDataFetcher"));
}
}
+
+ @Test
+ public void schemaSelectorsTest() throws Exception {
+ final String [] selectors = { "selected", "foryou" };
+ final String json = queryJSON("{ currentResource { path fortyTwo } }", selectors);
+
+ assertThat(json, hasJsonPath("$.data.currentResource"));
+ assertThat(json, hasJsonPath("$.data.currentResource.path", equalTo(42)));
+ assertThat(json, hasJsonPath("$.data.currentResource.fortyTwo", equalTo(42)));
+ }
}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/graphql/core/it/GraphQLScriptingTestSupport.java b/src/test/java/org/apache/sling/graphql/core/it/GraphQLScriptingTestSupport.java
index dadcbba..9fc889b 100644
--- a/src/test/java/org/apache/sling/graphql/core/it/GraphQLScriptingTestSupport.java
+++ b/src/test/java/org/apache/sling/graphql/core/it/GraphQLScriptingTestSupport.java
@@ -70,23 +70,6 @@ public abstract class GraphQLScriptingTestSupport extends TestSupport {
@Inject
protected SlingRequestProcessor requestProcessor;
- protected ServiceRegistration<DataFetcherProvider> dataFetcherFactoryRegistration;
-
- @Inject
- private BundleContext bundleContext;
-
- @Before
- public void registerFetchers() {
- PipeDataFetcherProvider pipeDataFetcherFactory = new PipeDataFetcherProvider();
- dataFetcherFactoryRegistration =
- bundleContext.registerService(DataFetcherProvider.class, pipeDataFetcherFactory, null);
- }
-
- @After
- public void unregisterFetchers() {
- dataFetcherFactoryRegistration.unregister();
- }
-
public ModifiableCompositeOption baseConfiguration() {
final String vmOpt = System.getProperty("pax.vm.options");
diff --git a/src/test/java/org/apache/sling/graphql/core/it/GraphQLServletIT.java b/src/test/java/org/apache/sling/graphql/core/it/GraphQLServletIT.java
index 08c27c2..d325c9c 100644
--- a/src/test/java/org/apache/sling/graphql/core/it/GraphQLServletIT.java
+++ b/src/test/java/org/apache/sling/graphql/core/it/GraphQLServletIT.java
@@ -64,7 +64,7 @@ public class GraphQLServletIT extends GraphQLScriptingTestSupport {
.asOption(),
factoryConfiguration(GRAPHQL_SERVLET_CONFIG_PID)
.put("sling.servlet.resourceTypes", "graphql/test/two")
- .put("sling.servlet.selectors", "testing")
+ .put("sling.servlet.selectors", new String[] { "testing", "another" })
.put("sling.servlet.extensions", "otherExt")
.asOption(),
};
@@ -87,12 +87,18 @@ public class GraphQLServletIT extends GraphQLScriptingTestSupport {
}
@Test
- public void testOtherExt() throws Exception {
- final String json = getContent("/graphql/two.testing.otherExt", "query", "{ currentResource { path name } }");
- assertThat(json, hasJsonPath("$.data.currentResource.path", equalTo("/content/graphql/two")));
- assertThat(json, hasJsonPath("$.data.currentResource.name", equalTo("two")));
- assertThat(json, hasNoJsonPath("$.data.currentResource.resourceType"));
+ public void testOtherExtAndTestingSelector() throws Exception {
executeRequest("GET", "/graphql/two.otherExt", null, 404);
+ final String json = getContent("/graphql/two.testing.otherExt", "query", "{ withTestingSelector { farenheit } }");
+ assertThat(json, hasJsonPath("$.data.withTestingSelector.farenheit", equalTo(451)));
+ }
+
+ @Test
+ public void testOtherExtAndOtherSelector() throws Exception {
+ final String json = getContent("/graphql/two.another.otherExt", "query", "{ currentResource { resourceType name } }");
+ assertThat(json, hasJsonPath("$.data.currentResource.resourceType", equalTo("graphql/test/two")));
+ assertThat(json, hasJsonPath("$.data.currentResource.name", equalTo("two")));
+ assertThat(json, hasNoJsonPath("$.data.currentResource.path"));
}
@Test
diff --git a/src/test/java/org/apache/sling/graphql/core/it/PipeDataFetcherProvider.java b/src/test/java/org/apache/sling/graphql/core/it/PipeDataFetcherProvider.java
index a0d0a24..a134918 100644
--- a/src/test/java/org/apache/sling/graphql/core/it/PipeDataFetcherProvider.java
+++ b/src/test/java/org/apache/sling/graphql/core/it/PipeDataFetcherProvider.java
@@ -30,21 +30,15 @@ public class PipeDataFetcherProvider implements DataFetcherProvider {
static class PipeDataFetcher implements DataFetcher<Object> {
- private final Resource r;
- private final String options;
+ private final Object value;
- PipeDataFetcher(Resource r, String name, String options, String source) {
- this.r = r;
- this.options = options;
+ PipeDataFetcher(Object value) {
+ this.value = value;
}
@Override
public Object get(DataFetchingEnvironment environment) throws Exception {
- if (!options.isEmpty() && !options.equals("$")) {
- throw new IllegalArgumentException("Invalid fetcher options: " + options);
- }
-
- return r;
+ return value;
}
}
@@ -52,7 +46,11 @@ public class PipeDataFetcherProvider implements DataFetcherProvider {
@Override
public DataFetcher<Object> createDataFetcher(Resource r, String name, String options, String source) {
if("pipe".equals(name)) {
- return new PipeDataFetcher(r, name, options, source);
+ if("farenheit".equals(options)) {
+ return new PipeDataFetcher(451);
+ } else {
+ return new PipeDataFetcher(r);
+ }
} else {
return null;
}
diff --git a/src/test/java/org/apache/sling/graphql/core/mocks/MockSchemaProvider.java b/src/test/java/org/apache/sling/graphql/core/mocks/MockSchemaProvider.java
index d58a668..10f3a66 100644
--- a/src/test/java/org/apache/sling/graphql/core/mocks/MockSchemaProvider.java
+++ b/src/test/java/org/apache/sling/graphql/core/mocks/MockSchemaProvider.java
@@ -18,6 +18,8 @@
*/
package org.apache.sling.graphql.core.mocks;
+import static org.junit.Assert.fail;
+
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
@@ -28,22 +30,36 @@ import org.apache.sling.graphql.api.SchemaProvider;
public class MockSchemaProvider implements SchemaProvider {
- private static final String MOCK_SCHEMA_PATH = "/test-schema.txt";
- private static final String MOCK_SCHEMA;
+ private final String basename;
- static {
- try (InputStream is = MockSchemaProvider.class.getResourceAsStream(MOCK_SCHEMA_PATH)) {
- final StringWriter w = new StringWriter();
- IOUtils.copy(is, w);
- MOCK_SCHEMA = w.toString();
- } catch(IOException ioe) {
- throw new RuntimeException("Error reading " + MOCK_SCHEMA_PATH, ioe);
- }
+ public MockSchemaProvider(String basename) {
+ this.basename = basename;
}
@Override
public String getSchema(Resource r, String[] selectors) {
- return MOCK_SCHEMA;
+
+ final StringBuilder sb = new StringBuilder();
+ sb.append("/").append(basename);
+ if(selectors != null) {
+ for(String s : selectors) {
+ sb.append("-").append(s);
+ }
+ }
+ sb.append(".txt");
+
+ final String path = sb.toString();
+
+ try (InputStream is = MockSchemaProvider.class.getResourceAsStream(path)) {
+ if(is == null) {
+ fail("Test schema not found: " + path);
+ }
+ final StringWriter w = new StringWriter();
+ IOUtils.copy(is, w);
+ return w.toString();
+ } catch(IOException ioe) {
+ throw new RuntimeException("Error reading " + path, ioe);
+ }
}
}
diff --git a/src/test/resources/initial-content/apps/graphql/test/two/testing.GQLschema.jsp b/src/test/resources/initial-content/apps/graphql/test/two/testing.GQLschema.jsp
new file mode 100644
index 0000000..61633a0
--- /dev/null
+++ b/src/test/resources/initial-content/apps/graphql/test/two/testing.GQLschema.jsp
@@ -0,0 +1,35 @@
+<%--
+* 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.
+--%>
+
+<%--
+Generating the schemas in JSP might not be the best way
+but it works for these initial tests - we might create
+a "passthrough" script engine, or one that extracts the
+additional DataFetcher information that we need.
+--%>
+
+type Query {
+ ## fetch:test/pipe
+ withTestingSelector : TestData
+}
+
+type TestData {
+ ## fetch:test/pipe/farenheit
+ farenheit: Int
+}
\ No newline at end of file
diff --git a/src/test/resources/test-schema-selected-foryou.txt b/src/test/resources/test-schema-selected-foryou.txt
new file mode 100644
index 0000000..0f00020
--- /dev/null
+++ b/src/test/resources/test-schema-selected-foryou.txt
@@ -0,0 +1,32 @@
+# * 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.
+
+# GraphQL Schema used for our tests
+# annotated with our fetch: definitions
+
+type Query {
+ ## fetch:echoNS/echo
+ currentResource : SlingResource
+}
+
+type SlingResource {
+ ## fetch:test/fortyTwo
+ fortyTwo: Int
+
+ ## fetch:test/fortyTwo
+ path: Int
+}
\ No newline at end of file