This is an automated email from the ASF dual-hosted git repository.
radu pushed a commit to branch feature/SLING-9655
in repository
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-graphql-core.git
The following commit(s) were added to refs/heads/feature/SLING-9655 by this
push:
new ed77ae5 SLING-9655 - Caching support for the GraphQL core
ed77ae5 is described below
commit ed77ae5f8289bd3e705c81fc3748e21634540f82
Author: Radu Cotescu <[email protected]>
AuthorDate: Tue Aug 18 17:15:59 2020 +0200
SLING-9655 - Caching support for the GraphQL core
* started implementing support for persisted queries based on jcache
(WIP)
---
pom.xml | 72 +++++++++----
.../graphql/core/cache/GraphQLCacheProvider.java | 116 +++++++++++++++++++++
.../sling/graphql/core/servlet/GraphQLServlet.java | 95 +++++++++++++++--
.../sling/graphql/core/servlet/QueryParser.java | 108 +++++++++++++++++++
.../sling/graphql/core/servlet/RequestParser.java | 77 --------------
.../core/cache/GraphQLCacheProviderTest.java | 32 ++++++
.../graphql/core/it/GraphQLCoreTestSupport.java | 17 ++-
7 files changed, 404 insertions(+), 113 deletions(-)
diff --git a/pom.xml b/pom.xml
index 3c4c165..291c558 100644
--- a/pom.xml
+++ b/pom.xml
@@ -101,28 +101,35 @@
<dependencies>
<dependency>
- <groupId>javax.inject</groupId>
- <artifactId>javax.inject</artifactId>
- <scope>test</scope>
+ <groupId>org.osgi</groupId>
+ <artifactId>osgi.core</artifactId>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
- <artifactId>osgi.cmpn</artifactId>
- <scope>test</scope>
+ <artifactId>org.osgi.service.component.annotations</artifactId>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
- <artifactId>osgi.core</artifactId>
+ <artifactId>org.osgi.service.metatype.annotations</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
- <artifactId>org.osgi.service.component.annotations</artifactId>
+ <artifactId>org.osgi.annotation.versioning</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.service.metatype.annotations</artifactId>
+ <groupId>javax.cache</groupId>
+ <artifactId>cache-api</artifactId>
+ <version>1.1.1</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ <version>3.9</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -208,6 +215,13 @@
<scope>provided</scope>
</dependency>
<dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.servlet-helpers</artifactId>
+ <version>1.4.2</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
@@ -225,10 +239,14 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>org.apache.sling</groupId>
- <artifactId>org.apache.sling.servlet-helpers</artifactId>
- <version>1.4.2</version>
- <scope>provided</scope>
+ <groupId>javax.inject</groupId>
+ <artifactId>javax.inject</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>osgi.cmpn</artifactId>
+ <scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
@@ -261,16 +279,6 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>biz.aQute.bnd</groupId>
- <artifactId>biz.aQute.bndlib</artifactId>
- <version>5.0.0</version>
- <scope>compile</scope>
- </dependency>
- <dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.annotation.versioning</artifactId>
- </dependency>
- <dependency>
<groupId>org.ops4j.pax.url</groupId>
<artifactId>pax-url-wrap</artifactId>
<version>2.3.0</version>
@@ -294,6 +302,24 @@
<version>1.3_1</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>com.github.ben-manes.caffeine</groupId>
+ <artifactId>caffeine</artifactId>
+ <version>2.8.6-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.github.ben-manes.caffeine</groupId>
+ <artifactId>jcache</artifactId>
+ <version>2.8.6-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.typesafe</groupId>
+ <artifactId>config</artifactId>
+ <version>1.4.0</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<reporting>
diff --git
a/src/main/java/org/apache/sling/graphql/core/cache/GraphQLCacheProvider.java
b/src/main/java/org/apache/sling/graphql/core/cache/GraphQLCacheProvider.java
new file mode 100644
index 0000000..20afddf
--- /dev/null
+++
b/src/main/java/org/apache/sling/graphql/core/cache/GraphQLCacheProvider.java
@@ -0,0 +1,116 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.core.cache;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Hashtable;
+
+import javax.cache.Cache;
+import javax.cache.CacheManager;
+import javax.cache.configuration.MutableConfiguration;
+import javax.cache.spi.CachingProvider;
+
+import org.apache.commons.lang3.StringUtils;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(
+ immediate = true
+)
+public class GraphQLCacheProvider {
+
+ private static final Logger LOGGER =
LoggerFactory.getLogger(GraphQLCacheProvider.class);
+
+ @Reference
+ private CachingProvider cachingProvider;
+
+ private Cache<String, String> persistedQueriesCache;
+
+ private ServiceRegistration<GraphQLCacheProvider> registration;
+
+ @Nullable
+ public String getQuery(@NotNull String hash, @NotNull String resourceType,
@Nullable String selectorString) {
+ return persistedQueriesCache.get(getCacheKey(hash, resourceType,
selectorString));
+ }
+
+ public void cacheQuery(@NotNull String query, @NotNull String
resourceType, @Nullable String selectorString) {
+ String key = getCacheKey("123", resourceType, selectorString);
+ persistedQueriesCache.put(key, query);
+ }
+
+
+ @Activate
+ public void activate(BundleContext bundleContext) {
+ if (cachingProvider != null) {
+ try {
+ CacheManager cacheManager = cachingProvider.getCacheManager();
+ persistedQueriesCache = cacheManager
+
.createCache(bundleContext.getBundle().getSymbolicName() + "_persistedQueries",
new MutableConfiguration<>());
+ registration =
bundleContext.registerService(GraphQLCacheProvider.class, this, new
Hashtable<>());
+ } catch (Exception e) {
+ LOGGER.error("Unable to configure a cache for persisted
queries.", e);
+ }
+ } else {
+ LOGGER.error("Cannot activate the " +
GraphQLCacheProvider.class.getName() + " without a cachingProvider.");
+ }
+ }
+
+ @Deactivate
+ public void deactivate(BundleContext bundleContext) {
+ if (registration != null) {
+ registration.unregister();
+ }
+ cachingProvider.close();
+ }
+
+ @NotNull
+ private String getCacheKey(@NotNull String hash, @NotNull String
resourceType, @Nullable String selectorString) {
+ StringBuilder key = new StringBuilder(resourceType);
+ if (StringUtils.isNotEmpty(selectorString)) {
+ key.append("_").append(selectorString);
+ }
+ key.append("_").append(hash);
+ return key.toString();
+ }
+
+ @NotNull String getHash(@NotNull String query) throws
NoSuchAlgorithmException {
+ MessageDigest digest = MessageDigest.getInstance("SHA-256");
+ byte[] hash = digest.digest(query.getBytes(StandardCharsets.UTF_8));
+ StringBuilder buffer = new StringBuilder();
+ for (int i = 0; i < hash.length; i++) {
+ String hex = Integer.toHexString(0xff & hash[i]);
+ if (hex.length() == 1) {
+ buffer.append('0');
+ }
+ buffer.append(hex);
+ }
+ return buffer.toString();
+ }
+
+}
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 cc424b2..0daf0ef 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
@@ -21,22 +21,32 @@
package org.apache.sling.graphql.core.servlet;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import javax.servlet.Servlet;
import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
+import org.apache.sling.graphql.core.cache.GraphQLCacheProvider;
import org.apache.sling.graphql.core.engine.GraphQLResourceQuery;
+import org.apache.sling.graphql.core.engine.SlingDataFetcherSelector;
import org.apache.sling.graphql.core.json.JsonSerializer;
import org.apache.sling.graphql.core.scalars.SlingScalarsProvider;
-import org.apache.sling.graphql.core.engine.SlingDataFetcherSelector;
import org.apache.sling.graphql.core.schema.RankedSchemaProviders;
+import org.jetbrains.annotations.NotNull;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.ConfigurationPolicy;
import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.Designate;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
@@ -68,6 +78,11 @@ public class GraphQLServlet extends SlingAllMethodsServlet {
public static final String P_QUERY = "query";
+ private static final String SUFFIX_PERSISTED = "/persisted";
+ private static final Pattern PATTERN_GET_PERSISTED_QUERY =
Pattern.compile("^" + SUFFIX_PERSISTED + "/([a-f0-9]{64})$");
+
+ private Config config;
+
@ObjectClassDefinition(
name = "Apache Sling GraphQL Servlet",
description = "Servlet that implements GraphQL endpoints")
@@ -102,34 +117,94 @@ public class GraphQLServlet extends
SlingAllMethodsServlet {
@Reference
private SlingScalarsProvider scalarsProvider;
+ @Reference(
+ cardinality = ReferenceCardinality.OPTIONAL,
+ policy = ReferencePolicy.STATIC,
+ policyOption = ReferencePolicyOption.GREEDY
+ )
+ private GraphQLCacheProvider cacheProvider;
+
private final JsonSerializer jsonSerializer = new JsonSerializer();
@Override
public void doGet(SlingHttpServletRequest request,
SlingHttpServletResponse response) throws IOException {
- execute(request.getResource(), request, response);
+ String suffix = request.getRequestPathInfo().getSuffix();
+ if (suffix != null && suffix.startsWith(SUFFIX_PERSISTED)) {
+ if (cacheProvider == null) {
+
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "This servlet
does not support persisted queries.");
+ return;
+ }
+ Matcher matcher = PATTERN_GET_PERSISTED_QUERY.matcher(suffix);
+ if (matcher.matches()) {
+ String queryHash = matcher.group(1);
+ if (StringUtils.isNotEmpty(queryHash)) {
+ String query = cacheProvider.getQuery(queryHash,
request.getResource().getResourceType(),
+ request.getRequestPathInfo().getSelectorString());
+ if (query != null) {
+ execute(query, request, response);
+ } else {
+ response.sendError(HttpServletResponse.SC_NOT_FOUND,
"Cannot find persisted query " + queryHash);
+ }
+ return;
+ }
+ } else {
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
+ } else {
+ execute(request.getResource(), request, response);
+ }
}
@Override
public void doPost(SlingHttpServletRequest request,
SlingHttpServletResponse response) throws IOException {
- execute(request.getResource(), request, response);
+ String suffix = request.getRequestPathInfo().getSuffix();
+ if (suffix != null && suffix.equals(SUFFIX_PERSISTED)) {
+ if (cacheProvider == null) {
+
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "This servlet
does not support persisted queries.");
+ return;
+ }
+ String query = IOUtils.toString(request.getInputStream(),
StandardCharsets.UTF_8);
+ cacheProvider.cacheQuery(query,
request.getResource().getResourceType(),
request.getRequestPathInfo().getSelectorString());
+ response.setStatus(HttpServletResponse.SC_CREATED);
+ } else {
+ execute(request.getResource(), request, response);
+ }
}
private void execute(Resource resource, SlingHttpServletRequest request,
SlingHttpServletResponse response) throws IOException {
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
-
- final RequestParser parser = new RequestParser(request);
- final String query = parser.getQuery();
- if (query == null || query.trim().length() == 0) {
+ final QueryParser.Result result = QueryParser.fromRequest(request);
+ if (result == null) {
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST);
+ return;
+ }
+ final String query = result.getQuery();
+ if (query.trim().length() == 0) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Missing
request parameter:" + P_QUERY);
return;
}
try {
final GraphQLResourceQuery q = new GraphQLResourceQuery();
- final ExecutionResult result = q.executeQuery(schemaProviders,
dataFetcherSelector, scalarsProvider,
- resource, request.getRequestPathInfo().getSelectors(), query,
parser.getVariables());
- jsonSerializer.sendJSON(response.getWriter(), result);
+ final ExecutionResult executionResult =
q.executeQuery(schemaProviders, dataFetcherSelector, scalarsProvider,
+ resource, request.getRequestPathInfo().getSelectors(), query,
result.getVariables());
+ jsonSerializer.sendJSON(response.getWriter(), executionResult);
+ } catch(Exception ex) {
+ throw new IOException(ex);
+ }
+ }
+
+ private void execute(@NotNull String persistedQuery,
SlingHttpServletRequest request, SlingHttpServletResponse response) throws
IOException {
+ response.setContentType("application/json");
+ response.setCharacterEncoding("UTF-8");
+ try {
+ final QueryParser.Result result =
QueryParser.fromJSON(persistedQuery);
+ final GraphQLResourceQuery q = new GraphQLResourceQuery();
+ final ExecutionResult executionResult =
q.executeQuery(schemaProviders, dataFetcherSelector, scalarsProvider,
+ request.getResource(),
request.getRequestPathInfo().getSelectors(), result.getQuery(),
result.getVariables());
+ jsonSerializer.sendJSON(response.getWriter(), executionResult);
} catch(Exception ex) {
throw new IOException(ex);
}
diff --git
a/src/main/java/org/apache/sling/graphql/core/servlet/QueryParser.java
b/src/main/java/org/apache/sling/graphql/core/servlet/QueryParser.java
new file mode 100644
index 0000000..d6b868e
--- /dev/null
+++ b/src/main/java/org/apache/sling/graphql/core/servlet/QueryParser.java
@@ -0,0 +1,108 @@
+/*
+ * 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.core.servlet;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.input.ReaderInputStream;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.graphql.core.json.JsonSerializer;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class QueryParser {
+
+ private QueryParser() {}
+
+ static class Result {
+
+ private final String query;
+ private final Map<String, Object> variables;
+
+ Result(String query, Map<String, Object> variables) {
+ this.query = query;
+ this.variables = variables;
+ }
+
+ @NotNull
+ public String getQuery() {
+ return query;
+ }
+
+ @NotNull
+ public Map<String, Object> getVariables() {
+ return variables;
+ }
+ }
+
+ private static final String MIME_TYPE_JSON = "application/json";
+ private static final JsonSerializer jsonSerializer = new JsonSerializer();
+ private static final String JSON_KEY_QUERY = "query";
+ private static final String JSON_KEY_VARIABLES = "variables";
+
+ @Nullable
+ public static Result fromRequest(@NotNull SlingHttpServletRequest request)
throws IOException {
+ String query = null;
+ Map<String, Object> variables = null;
+ if (request.getMethod().equalsIgnoreCase("POST") &&
MIME_TYPE_JSON.equals(request.getContentType())) {
+ Map<String, Object> requestJson = getInputJson(request);
+ query = (String) requestJson.get(JSON_KEY_QUERY);
+ if (query != null) {
+ query = query.replace("\\n", "\n");
+ }
+ variables = (Map<String, Object>)
requestJson.get(JSON_KEY_VARIABLES);
+ }
+
+ if (query == null) {
+ query = request.getParameter(JSON_KEY_QUERY);
+ }
+
+ if (variables == null) {
+ variables = Collections.emptyMap();
+ }
+ if (query != null) {
+ return new Result(query, variables);
+ }
+ return null;
+ }
+
+ public static Result fromJSON(String json) throws IOException {
+ Map<String, Object> jsonMap =
jsonSerializer.JSONtoMaps(IOUtils.toInputStream(json, StandardCharsets.UTF_8));
+ String query = (String) jsonMap.get(JSON_KEY_QUERY);
+ if (query != null) {
+ Map<String, Object> variables = (Map<String, Object>)
jsonMap.get(JSON_KEY_VARIABLES);
+ if (variables == null) {
+ variables = Collections.emptyMap();
+ }
+ return new Result(query, variables);
+ }
+ throw new IOException("The provided JSON structure does not contain a
query.");
+
+ }
+
+ private static Map<String, Object> getInputJson(SlingHttpServletRequest
req) throws IOException {
+ return jsonSerializer.JSONtoMaps(new
ReaderInputStream(req.getReader()));
+ }
+
+}
diff --git
a/src/main/java/org/apache/sling/graphql/core/servlet/RequestParser.java
b/src/main/java/org/apache/sling/graphql/core/servlet/RequestParser.java
deleted file mode 100644
index 724ceaf..0000000
--- a/src/main/java/org/apache/sling/graphql/core/servlet/RequestParser.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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.core.servlet;
-
-import org.apache.commons.io.input.ReaderInputStream;
-import org.apache.sling.api.SlingHttpServletRequest;
-import org.apache.sling.graphql.core.json.JsonSerializer;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Map;
-
-public class RequestParser {
-
- private static final String MIME_TYPE_JSON = "application/json";
-
- private String query;
-
- private Map<String, Object> variables;
- private final JsonSerializer jsonSerializer = new JsonSerializer();
-
- RequestParser(SlingHttpServletRequest request) throws IOException {
- parse(request);
- }
-
- private Map<String, Object> getInputJson(SlingHttpServletRequest req)
throws IOException {
- return jsonSerializer.JSONtoMaps(new
ReaderInputStream(req.getReader()));
- }
-
- @SuppressWarnings("unchecked")
- private void parse(SlingHttpServletRequest request) throws IOException {
- if (request.getMethod().equalsIgnoreCase("POST")) {
- if (MIME_TYPE_JSON.equals(request.getContentType())) {
- Map<String, Object> requestJson = getInputJson(request);
- query = (String) requestJson.get("query");
- if (query != null) {
- query = query.replace("\\n", "\n");
- }
- variables = (Map<String, Object>) requestJson.get("variables");
- }
- }
-
- if (query == null) {
- query = request.getParameter("query");
- }
-
- if (variables == null) {
- variables = Collections.emptyMap();
- }
- }
-
- public String getQuery() {
- return query;
- }
-
- public Map<String, Object> getVariables() {
- return variables;
- }
-
-}
diff --git
a/src/test/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderTest.java
b/src/test/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderTest.java
new file mode 100644
index 0000000..66184b6
--- /dev/null
+++
b/src/test/java/org/apache/sling/graphql/core/cache/GraphQLCacheProviderTest.java
@@ -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.
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+package org.apache.sling.graphql.core.cache;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class GraphQLCacheProviderTest {
+
+ @Test
+ public void getHash() throws Exception {
+ GraphQLCacheProvider provider = new GraphQLCacheProvider();
+
assertEquals("b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9",
provider.getHash("hello world"));
+ }
+}
diff --git
a/src/test/java/org/apache/sling/graphql/core/it/GraphQLCoreTestSupport.java
b/src/test/java/org/apache/sling/graphql/core/it/GraphQLCoreTestSupport.java
index 078c5c6..49a6f87 100644
--- a/src/test/java/org/apache/sling/graphql/core/it/GraphQLCoreTestSupport.java
+++ b/src/test/java/org/apache/sling/graphql/core/it/GraphQLCoreTestSupport.java
@@ -23,6 +23,7 @@ import javax.inject.Inject;
import com.cedarsoftware.util.io.JsonWriter;
import org.apache.commons.io.output.WriterOutputStream;
+import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.graphql.core.json.JsonSerializer;
@@ -35,6 +36,7 @@ import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.ProbeBuilder;
import org.ops4j.pax.exam.TestProbeBuilder;
import org.ops4j.pax.exam.options.ModifiableCompositeOption;
+import org.ops4j.pax.exam.options.extra.VMOption;
import org.ops4j.pax.tinybundles.core.TinyBundle;
import org.osgi.framework.Constants;
import org.apache.sling.engine.SlingRequestProcessor;
@@ -47,6 +49,7 @@ import static
org.apache.sling.testing.paxexam.SlingOptions.slingScriptingJsp;
import static org.ops4j.pax.exam.CoreOptions.composite;
import static org.ops4j.pax.exam.CoreOptions.junitBundles;
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.vmOptions;
import static org.ops4j.pax.exam.CoreOptions.when;
import static org.ops4j.pax.exam.CoreOptions.vmOption;
import static org.ops4j.pax.exam.CoreOptions.streamBundle;
@@ -74,10 +77,14 @@ public abstract class GraphQLCoreTestSupport extends
TestSupport {
public ModifiableCompositeOption baseConfiguration() {
final String vmOpt = System.getProperty("pax.vm.options");
+ VMOption vmOption = null;
+ if (StringUtils.isNotEmpty(vmOpt)) {
+ vmOption = new VMOption(vmOpt);
+ }
return composite(
- when(vmOpt != null).useOptions(
- vmOption(vmOpt)
+ when(vmOption != null).useOptions(
+ vmOption
),
super.baseConfiguration(),
slingQuickstart(),
@@ -89,6 +96,10 @@ public abstract class GraphQLCoreTestSupport extends
TestSupport {
.asOption(),
mavenBundle().groupId("org.apache.sling").artifactId("org.apache.sling.servlet-helpers").versionAsInProject(),
mavenBundle().groupId("com.cedarsoftware").artifactId("json-io").versionAsInProject(),
+
mavenBundle().groupId("javax.cache").artifactId("cache-api").versionAsInProject(),
+
mavenBundle().groupId("com.typesafe").artifactId("config").versionAsInProject(),
+
mavenBundle().groupId("com.github.ben-manes.caffeine").artifactId("caffeine").versionAsInProject(),
+
mavenBundle().groupId("com.github.ben-manes.caffeine").artifactId("jcache").versionAsInProject(),
slingResourcePresence(),
jsonPath(),
junitBundles()
@@ -229,4 +240,4 @@ public abstract class GraphQLCoreTestSupport extends
TestSupport {
bundle.set(Constants.EXPORT_PACKAGE, exports.toString());
return streamBundle(bundle.build()).start();
}
-}
\ No newline at end of file
+}