Skip to content

Commit

Permalink
SLING-10883 - Update the GraphQL implementation to use the Builder AP…
Browse files Browse the repository at this point in the history
…I for internal requests

* refactored code to switch to the o.a.s.api.request.builder API
  • Loading branch information
raducotescu committed Aug 29, 2022
1 parent 9989848 commit 4317933
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 51 deletions.
58 changes: 44 additions & 14 deletions pom.xml
Expand Up @@ -136,13 +136,13 @@
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.api</artifactId>
<version>2.18.4</version>
<version>2.24.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.engine</artifactId>
<version>2.6.22</version>
<version>2.7.10</version>
<scope>provided</scope>
</dependency>
<dependency>
Expand Down Expand Up @@ -181,12 +181,6 @@
<version>2.1.12</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.scripting.core</artifactId>
<version>2.0.30</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.commons.osgi</artifactId>
Expand All @@ -209,12 +203,6 @@
<artifactId>slf4j-api</artifactId>
<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>
Expand Down Expand Up @@ -315,6 +303,48 @@
<version>1.2.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.jcr.jackrabbit.usermanager</artifactId>
<version>2.2.16</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.resourceresolver</artifactId>
<version>1.8.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.servlets.resolver</artifactId>
<version>2.9.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.commons.compiler</artifactId>
<version>2.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.scripting.spi</artifactId>
<version>1.0.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.scripting.core</artifactId>
<version>2.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.util.converter</artifactId>
<version>1.0.0</version>
<scope>test</scope>
</dependency>
</dependencies>

<reporting>
Expand Down
Expand Up @@ -22,13 +22,18 @@

import java.io.IOException;

import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.request.builder.Builders;
import org.apache.sling.api.request.builder.SlingHttpServletRequestBuilder;
import org.apache.sling.api.request.builder.SlingHttpServletResponseResult;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.servlets.ServletResolver;
import org.apache.sling.graphql.api.SchemaProvider;
import org.apache.sling.servlethelpers.internalrequests.InternalRequest;
import org.apache.sling.servlethelpers.internalrequests.ServletInternalRequest;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
Expand All @@ -53,16 +58,20 @@ public class DefaultSchemaProvider implements SchemaProvider {

@Override
public String getSchema(Resource r, String [] selectors) throws IOException {
final InternalRequest req =
new ServletInternalRequest(servletResolver, r)
.withSelectors(selectors)
.withExtension(SCHEMA_EXTENSION)
;

final SlingHttpServletRequest req =
Builders.newRequestBuilder(r).withSelectors(selectors).withExtension(SCHEMA_EXTENSION).build();
final SlingHttpServletResponseResult response = Builders.newResponseBuilder().build();
try {
Servlet servlet = servletResolver.resolveServlet(req);
if (servlet != null) {
servlet.service(req, response);
}
} catch (ServletException e) {
LOGGER.error("Unable to retrieve a GraphQL Schema for {}.", r.getPath());
}
LOGGER.debug("Getting GraphQL Schema for {}: {}", r.getPath(), req);

if(req.execute().getStatus() == HttpServletResponse.SC_OK) {
return req.getResponseAsString();
if(response.getStatus() == HttpServletResponse.SC_OK) {
return response.getOutputAsString();
} else {
return DEFAULT_SCHEMA;
}
Expand Down
Expand Up @@ -23,24 +23,33 @@
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;

import javax.inject.Inject;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.johnzon.mapper.Mapper;
import org.apache.johnzon.mapper.MapperBuilder;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.request.builder.Builders;
import org.apache.sling.api.request.builder.SlingHttpServletResponseResult;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.resource.ResourceWrapper;
import org.apache.sling.engine.SlingRequestProcessor;
import org.apache.sling.graphql.core.mocks.QueryDataFetcherComponent;
import org.apache.sling.graphql.core.mocks.TestDataFetcherComponent;
import org.apache.sling.servlethelpers.MockSlingHttpServletResponse;
import org.apache.sling.servlethelpers.internalrequests.SlingInternalRequest;
import org.apache.sling.testing.paxexam.SlingOptions;
import org.apache.sling.testing.paxexam.SlingVersionResolver;
import org.apache.sling.testing.paxexam.TestSupport;
import org.jetbrains.annotations.NotNull;
import org.junit.Before;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.ProbeBuilder;
Expand All @@ -49,6 +58,8 @@
import org.ops4j.pax.exam.options.extra.VMOption;
import org.ops4j.pax.tinybundles.core.TinyBundle;
import org.osgi.framework.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.apache.sling.testing.paxexam.SlingOptions.slingCommonsMetrics;
import static org.apache.sling.testing.paxexam.SlingOptions.slingQuickstartOakTar;
Expand All @@ -65,6 +76,8 @@

public abstract class GraphQLCoreTestSupport extends TestSupport {

private static final Logger LOGGER = LoggerFactory.getLogger(GraphQLCoreTestSupport.class);

private final static int STARTUP_WAIT_SECONDS = 30;

@Inject
Expand All @@ -86,6 +99,15 @@ public ModifiableCompositeOption baseConfiguration() {
jacocoCommand = new VMOption(jacocoOpt);
}

SlingOptions.versionResolver.setVersionFromProject(SlingVersionResolver.SLING_GROUP_ID, "org.apache.sling.api");
SlingOptions.versionResolver.setVersionFromProject(SlingVersionResolver.SLING_GROUP_ID, "org.apache.sling.servlets.resolver");
SlingOptions.versionResolver.setVersionFromProject(SlingVersionResolver.SLING_GROUP_ID, "org.apache.sling.engine");
SlingOptions.versionResolver.setVersionFromProject(SlingVersionResolver.SLING_GROUP_ID, "org.apache.sling.resourceresolver");
SlingOptions.versionResolver.setVersionFromProject(SlingVersionResolver.SLING_GROUP_ID, "org.apache.sling.scripting.api");
SlingOptions.versionResolver.setVersionFromProject(SlingVersionResolver.SLING_GROUP_ID, "org.apache.sling.scripting.core");
SlingOptions.versionResolver.setVersionFromProject(SlingVersionResolver.SLING_GROUP_ID, "org.apache.sling.commons.compiler");
SlingOptions.versionResolver.setVersionFromProject(SlingVersionResolver.SLING_GROUP_ID, "org.apache.sling.jcr.jackrabbit.usermanager");

return composite(
when(vmOption != null).useOptions(vmOption),
when(jacocoCommand != null).useOptions(jacocoCommand),
Expand All @@ -98,6 +120,8 @@ public ModifiableCompositeOption baseConfiguration() {
.asOption(),
mavenBundle().groupId("org.apache.sling").artifactId("org.apache.sling.servlet-helpers").versionAsInProject(),
mavenBundle().groupId("org.apache.sling").artifactId("org.apache.sling.commons.johnzon").versionAsInProject(),
mavenBundle().groupId("org.osgi").artifactId("org.osgi.util.converter").versionAsInProject(), // required for the newer Sling API
mavenBundle().groupId(SlingVersionResolver.SLING_GROUP_ID).artifactId("org.apache.sling.scripting.spi").versionAsInProject(),
mavenBundle().groupId("org.apache.johnzon").artifactId("johnzon-mapper").versionAsInProject(),
slingResourcePresence(),
slingCommonsMetrics(),
Expand Down Expand Up @@ -168,26 +192,65 @@ public void waitForSling() throws Exception {
fail("Did not get a " + expectedStatus + " status at " + path + " got " + statuses);
}

protected MockSlingHttpServletResponse executeRequest(final String method,
final String path, Map<String, Object> params, String contentType,
Reader body, final int expectedStatus) throws Exception {
protected SlingHttpServletResponseResult executeRequest(final String method,
final String path, Map<String, String[]> params, String contentType,
Reader body, final int expectedStatus) throws Exception {

// Admin resolver is fine for testing
@SuppressWarnings("deprecation")
final ResourceResolver resourceResolver = resourceResolverFactory.getAdministrativeResourceResolver(null);

final int [] statusParam = expectedStatus == -1 ? null : new int[] { expectedStatus };

return (MockSlingHttpServletResponse)
new SlingInternalRequest(resourceResolver, requestProcessor, path)
.withRequestMethod(method)
.withParameters(params)
.withContentType(contentType)
.withBody(body)
.execute()
.checkStatus(statusParam)
.getResponse()
;
Resource resource = resourceResolver.resolve(path);
String selectorsExtensionSuffix = resource.getResourceMetadata().getResolutionPathInfo();
String[] selectors = new String[0];
String extension = null;
String suffix = null;
int firstSlash = selectorsExtensionSuffix.indexOf('/');
if (firstSlash != -1) {
suffix = selectorsExtensionSuffix.substring(firstSlash);
selectorsExtensionSuffix = selectorsExtensionSuffix.substring(0, selectorsExtensionSuffix.length() - suffix.length());
}
if (selectorsExtensionSuffix.startsWith(".")) {
selectorsExtensionSuffix = selectorsExtensionSuffix.substring(1);
}
if (selectorsExtensionSuffix.length() > 0) {
String[] parts = selectorsExtensionSuffix.split("\\.");
if (parts.length > 1) {
selectors = Arrays.copyOfRange(parts, 0, parts.length - 1);
}
extension = parts[parts.length - 1];
}
String resolvedPath = resource.getPath();
if (selectors.length > 0) {
resolvedPath += "." + String.join(".", selectors);
}
if (extension != null) {
resolvedPath += "." + extension;
}
if (suffix != null) {
resolvedPath += suffix;
}
if (!path.equals(resolvedPath) && suffix != null) {
resource = new ResourceWrapper(resource) {
@Override
public @NotNull String getPath() {
return path;
}
};
}
final SlingHttpServletRequest request = Builders.newRequestBuilder(Objects.requireNonNull(resource))
.withRequestMethod(method)
.withParameters(params)
.withContentType(contentType)
.withBody(body == null ? null : IOUtils.toString(body))
.withSelectors(resource instanceof ResourceWrapper ? null : selectors)
.withExtension(resource instanceof ResourceWrapper ? null : extension)
.withSuffix(resource instanceof ResourceWrapper ? null : suffix)
.build();
final SlingHttpServletResponseResult response = Builders.newResponseBuilder().build();
requestProcessor.processRequest(request, response, resourceResolver);
return response;
}

protected String getContent(String path) throws Exception {
Expand All @@ -211,7 +274,7 @@ protected String getContentWithPost(String path, String query, Map<String, Objec
return executeRequest("POST", path, null, "application/json", new StringReader(toJSON(body)), 200).getOutputAsString();
}

protected MockSlingHttpServletResponse persistQuery(String path, String query, Map<String, Object> variables) throws Exception {
protected SlingHttpServletResponseResult persistQuery(String path, String query, Map<String, Object> variables) throws Exception {
Map<String, Object> body = new HashMap<>();
if (query != null) {
String queryEncoded = query.replace("\n", "\\n");
Expand All @@ -229,10 +292,10 @@ protected String toJSON(Object source) {
return mapper.toStructure(source).toString();
}

protected Map<String, Object> toMap(String ...keyValuePairs) {
final Map<String, Object> result = new HashMap<>();
protected Map<String, String[]> toMap(String ...keyValuePairs) {
final Map<String, String[]> result = new HashMap<>();
for(int i=0 ; i < keyValuePairs.length; i+=2) {
result.put(keyValuePairs[i], keyValuePairs[i+1]);
result.put(keyValuePairs[i], new String[] {keyValuePairs[i+1]});
}
return result;
}
Expand Down
Expand Up @@ -45,10 +45,10 @@
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.sling.api.request.builder.SlingHttpServletResponseResult;
import org.apache.sling.graphql.api.SchemaProvider;
import org.apache.sling.graphql.core.mocks.ReplacingSchemaProvider;
import org.apache.sling.resource.presence.ResourcePresence;
import org.apache.sling.servlethelpers.MockSlingHttpServletResponse;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Configuration;
Expand All @@ -61,8 +61,8 @@

import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath;
import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasNoJsonPath;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
Expand Down Expand Up @@ -126,7 +126,7 @@ public void testGqlExtWithPost() throws Exception {
@Test
public void testPersistedQueriesBasic() throws Exception {
String queryHash = "a16982712f6ecdeba5d950d42e3c13df0fc26d008c497f6bf012701b57e02a51";
MockSlingHttpServletResponse response = persistQuery("/graphql/two.gql", "{ currentResource { resourceType name } }", null);
SlingHttpServletResponseResult response = persistQuery("/graphql/two.gql", "{ currentResource { resourceType name } }", null);
assertEquals("Expected to have stored a persisted query.", 201, response.getStatus());
assertEquals("The value of the Location header does not look correct.",
"http://localhost/graphql/two.gql/persisted/" + queryHash + ".gql",
Expand Down Expand Up @@ -227,7 +227,7 @@ public void testOtherExtAndOtherSelector() throws Exception {

@Test
public void testMissingQuery() throws Exception {
MockSlingHttpServletResponse response = executeRequest("GET", "/graphql/two.gql", null, null, null, -1);
SlingHttpServletResponseResult response = executeRequest("GET", "/graphql/two.gql", null, null, null, -1);
assertEquals(400, response.getStatus());
}

Expand Down
Expand Up @@ -20,8 +20,8 @@

import javax.inject.Inject;

import org.apache.sling.api.request.builder.SlingHttpServletResponseResult;
import org.apache.sling.resource.presence.ResourcePresence;
import org.apache.sling.servlethelpers.MockSlingHttpServletResponse;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Configuration;
Expand Down Expand Up @@ -55,7 +55,7 @@ public Option[] configuration() {
@Test
public void testServletDisabledByDefault() throws Exception {
final String path = "/graphql/one";
MockSlingHttpServletResponse response = executeRequest("GET", path + ".json", null, null, null, -1);
SlingHttpServletResponseResult response = executeRequest("GET", path + ".json", null, null, null, -1);
assertEquals(200, response.getStatus());

response = executeRequest("GET", path + ".gql", null, null, null, -1);
Expand Down

0 comments on commit 4317933

Please sign in to comment.