You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by je...@apache.org on 2019/04/09 23:00:52 UTC
[geode] branch develop updated: GEODE-6608: Add Swagger UI to
Management REST API (#3431)
This is an automated email from the ASF dual-hosted git repository.
jensdeppe pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git
The following commit(s) were added to refs/heads/develop by this push:
new 232dc0f GEODE-6608: Add Swagger UI to Management REST API (#3431)
232dc0f is described below
commit 232dc0f3170c8620e54814231d23a50790634b69
Author: Jens Deppe <jd...@pivotal.io>
AuthorDate: Tue Apr 9 16:00:25 2019 -0700
GEODE-6608: Add Swagger UI to Management REST API (#3431)
Authored-by: Jens Deppe <jd...@pivotal.io>
---
.../src/test/resources/expected-pom.xml | 5 ++
.../gradle/plugins/DependencyConstraints.groovy | 1 +
geode-assembly/build.gradle | 12 +++-
...tandaloneClientManagementAPIAcceptanceTest.java | 3 +-
...aggerManagementVerificationIntegrationTest.java | 70 ++++++++++++++++++++++
.../integrationTest/resources/assembly_content.txt | 1 +
.../resources/dependency_classpath.txt | 1 +
geode-core/build.gradle | 4 ++
geode-core/src/test/resources/expected-pom.xml | 6 ++
geode-management/build.gradle | 6 +-
.../cache/configuration/BasicRegionConfig.java | 4 ++
.../geode/management/api/RestfulEndpoint.java | 1 +
geode-web-management/build.gradle | 16 +++--
.../internal/rest/ManagementLoggingFilter.java | 26 +++++---
.../controllers/RegionManagementController.java | 9 +++
.../internal/rest/swagger/SwaggerConfig.java | 63 +++++++++++++++++++
.../main/resources/swagger-management.properties | 15 +++++
.../src/main/webapp/docs/index.html | 16 +++++
.../src/test/resources/expected-pom.xml | 20 +++++++
19 files changed, 263 insertions(+), 16 deletions(-)
diff --git a/boms/geode-all-bom/src/test/resources/expected-pom.xml b/boms/geode-all-bom/src/test/resources/expected-pom.xml
index a40cd7c..35efaec 100644
--- a/boms/geode-all-bom/src/test/resources/expected-pom.xml
+++ b/boms/geode-all-bom/src/test/resources/expected-pom.xml
@@ -363,6 +363,11 @@
<version>1.7.25</version>
</dependency>
<dependency>
+ <groupId>io.swagger</groupId>
+ <artifactId>swagger-annotations</artifactId>
+ <version>1.5.20</version>
+ </dependency>
+ <dependency>
<groupId>org.springframework.hateoas</groupId>
<artifactId>spring-hateoas</artifactId>
<version>0.25.0.RELEASE</version>
diff --git a/buildSrc/src/main/groovy/org/apache/geode/gradle/plugins/DependencyConstraints.groovy b/buildSrc/src/main/groovy/org/apache/geode/gradle/plugins/DependencyConstraints.groovy
index 44d6347..07bd706 100644
--- a/buildSrc/src/main/groovy/org/apache/geode/gradle/plugins/DependencyConstraints.groovy
+++ b/buildSrc/src/main/groovy/org/apache/geode/gradle/plugins/DependencyConstraints.groovy
@@ -149,6 +149,7 @@ class DependencyConstraints implements Plugin<Project> {
api(group: 'org.postgresql', name: 'postgresql', version: '42.2.2')
api(group: 'org.skyscreamer', name: 'jsonassert', version: '1.5.0')
api(group: 'org.slf4j', name: 'slf4j-api', version: get('slf4j-api.version'))
+ api(group: 'io.swagger', name: 'swagger-annotations', version: '1.5.20')
api(group: 'org.springframework.hateoas', name: 'spring-hateoas', version: '0.25.0.RELEASE')
api(group: 'org.springframework.ldap', name: 'spring-ldap-core', version: '2.3.2.RELEASE')
api(group: 'org.springframework.shell', name: 'spring-shell', version: '1.2.0.RELEASE')
diff --git a/geode-assembly/build.gradle b/geode-assembly/build.gradle
index c9445fd..df61f63 100755
--- a/geode-assembly/build.gradle
+++ b/geode-assembly/build.gradle
@@ -202,6 +202,8 @@ dependencies {
integrationTestCompile('org.apache.httpcomponents:httpclient')
integrationTestCompile('javax.annotation:javax.annotation-api')
+ integrationTestRuntime('io.swagger:swagger-annotations')
+
distributedTestCompile(project(':geode-core'))
distributedTestCompile(project(':geode-dunit')){
@@ -220,15 +222,19 @@ dependencies {
exclude group: 'org.apache.tomcat'
}
distributedTestRuntime('org.codehaus.cargo:cargo-core-uberjar')
+ distributedTestRuntime('io.swagger:swagger-annotations')
- acceptanceTestCompile(project(':geode-core'))
+ // geodeArchives is a direct reflection of what is contained in geode-dependencies.jar. To that
+ // end only add _test_ dependencies to acceptanceTestCompile/Runtime. All other product
+ // dependencies should be a part of geodeArchives and should not need to be added as individual
+ // dependencies here.
+ acceptanceTestCompile(configurations.geodeArchives)
acceptanceTestCompile(project(':geode-dunit')) {
exclude module: 'geode-core'
}
acceptanceTestCompile(project(':geode-assembly:geode-assembly-test'))
- acceptanceTestCompile('org.apache.httpcomponents:httpclient')
-
+
// This is used by 'gradle within gradle' tests. No need to bump this version; but if you do,
// don't have it be the same version as the outer gradle version.
acceptanceTestCompile('org.gradle:gradle-tooling-api:5.1.1')
diff --git a/geode-assembly/src/acceptanceTest/java/org/apache/geode/management/internal/rest/StandaloneClientManagementAPIAcceptanceTest.java b/geode-assembly/src/acceptanceTest/java/org/apache/geode/management/internal/rest/StandaloneClientManagementAPIAcceptanceTest.java
index 92b724c..04819a9 100644
--- a/geode-assembly/src/acceptanceTest/java/org/apache/geode/management/internal/rest/StandaloneClientManagementAPIAcceptanceTest.java
+++ b/geode-assembly/src/acceptanceTest/java/org/apache/geode/management/internal/rest/StandaloneClientManagementAPIAcceptanceTest.java
@@ -179,7 +179,8 @@ public class StandaloneClientManagementAPIAcceptanceTest {
String classPath = Arrays.stream(System.getProperty("java.class.path")
.split(File.pathSeparator))
.filter(x -> x.contains(module)
- && (x.endsWith("/classes") || x.endsWith("/resources") || x.endsWith(".jar")))
+ && (x.endsWith("/classes") || x.endsWith("/classes/java/main")
+ || x.endsWith("/resources") || x.endsWith(".jar")))
.collect(Collectors.joining(File.pathSeparator));
assertThat(classPath).as("no classes found for module: " + module)
diff --git a/geode-assembly/src/integrationTest/java/org/apache/geode/management/internal/rest/SwaggerManagementVerificationIntegrationTest.java b/geode-assembly/src/integrationTest/java/org/apache/geode/management/internal/rest/SwaggerManagementVerificationIntegrationTest.java
new file mode 100644
index 0000000..9bbf04a
--- /dev/null
+++ b/geode-assembly/src/integrationTest/java/org/apache/geode/management/internal/rest/SwaggerManagementVerificationIntegrationTest.java
@@ -0,0 +1,70 @@
+/*
+ * 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.geode.management.internal.rest;
+
+
+import static org.apache.geode.test.junit.rules.HttpResponseAssert.assertResponse;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.test.junit.categories.RestAPITest;
+import org.apache.geode.test.junit.categories.SecurityTest;
+import org.apache.geode.test.junit.rules.GeodeHttpClientRule;
+import org.apache.geode.test.junit.rules.LocatorStarterRule;
+import org.apache.geode.test.junit.rules.RequiresGeodeHome;
+
+@Category({SecurityTest.class, RestAPITest.class})
+public class SwaggerManagementVerificationIntegrationTest {
+
+ @ClassRule
+ public static LocatorStarterRule locatorStarter = new LocatorStarterRule()
+ .withHttpService()
+ .withAutoStart();
+
+ @Rule
+ public GeodeHttpClientRule client = new GeodeHttpClientRule(locatorStarter::getHttpPort);
+
+ @Rule
+ public RequiresGeodeHome requiresGeodeHome = new RequiresGeodeHome();
+
+ @Test
+ public void isSwaggerRunning() throws Exception {
+ // Check the UI
+ assertResponse(client.get("/geode-management/swagger-ui.html")).hasStatusCode(200);
+
+ // Check the JSON
+ JsonNode json =
+ assertResponse(client.get("/geode-management/v2/api-docs")).hasStatusCode(200)
+ .getJsonObject();
+ assertThat(json.get("swagger").asText(), is("2.0"));
+
+ JsonNode info = json.get("info");
+ assertThat(info.get("description").asText(),
+ is("REST API and interface to manage Geode components."));
+ assertThat(info.get("title").asText(),
+ is("Apache Geode Management REST API"));
+
+ JsonNode license = info.get("license");
+ assertThat(license.get("name").asText(), is("Apache License, version 2.0"));
+ assertThat(license.get("url").asText(), is("http://www.apache.org/licenses/"));
+
+ }
+}
diff --git a/geode-assembly/src/integrationTest/resources/assembly_content.txt b/geode-assembly/src/integrationTest/resources/assembly_content.txt
index b4d93ef..217fa40 100644
--- a/geode-assembly/src/integrationTest/resources/assembly_content.txt
+++ b/geode-assembly/src/integrationTest/resources/assembly_content.txt
@@ -983,6 +983,7 @@ lib/spring-core-4.3.20.RELEASE.jar
lib/spring-expression-4.3.20.RELEASE.jar
lib/spring-shell-1.2.0.RELEASE.jar
lib/spring-web-4.3.20.RELEASE.jar
+lib/swagger-annotations-1.5.20.jar
tools/ClientProtocol/geode-protobuf-messages-definitions-0.0.0.zip
tools/Extensions/geode-web-0.0.0.war
tools/Extensions/geode-web-api-0.0.0.war
diff --git a/geode-assembly/src/integrationTest/resources/dependency_classpath.txt b/geode-assembly/src/integrationTest/resources/dependency_classpath.txt
index 93ff0e5..2f2a908 100644
--- a/geode-assembly/src/integrationTest/resources/dependency_classpath.txt
+++ b/geode-assembly/src/integrationTest/resources/dependency_classpath.txt
@@ -80,3 +80,4 @@ slf4j-api-1.7.25.jar
snappy-0.4.jar
spring-core-4.3.20.RELEASE.jar
spring-shell-1.2.0.RELEASE.jar
+swagger-annotations-1.5.20.jar
\ No newline at end of file
diff --git a/geode-core/build.gradle b/geode-core/build.gradle
index 2692bc5..dee3620 100755
--- a/geode-core/build.gradle
+++ b/geode-core/build.gradle
@@ -286,6 +286,10 @@ dependencies {
runtimeOnly('org.apache.logging.log4j:log4j-jul') {
ext.optional = true
}
+ runtimeOnly('io.swagger:swagger-annotations') {
+ ext.optional = true
+ }
+
//Jetty is used by the http service, which is used for the developer and management rest APIs
implementation('org.eclipse.jetty:jetty-webapp') {
ext.optional = true
diff --git a/geode-core/src/test/resources/expected-pom.xml b/geode-core/src/test/resources/expected-pom.xml
index 55372f4..6ed0a4f 100644
--- a/geode-core/src/test/resources/expected-pom.xml
+++ b/geode-core/src/test/resources/expected-pom.xml
@@ -304,5 +304,11 @@
<scope>runtime</scope>
<optional>true</optional>
</dependency>
+ <dependency>
+ <groupId>io.swagger</groupId>
+ <artifactId>swagger-annotations</artifactId>
+ <scope>runtime</scope>
+ <optional>true</optional>
+ </dependency>
</dependencies>
</project>
diff --git a/geode-management/build.gradle b/geode-management/build.gradle
index 1b12146..fe56720 100755
--- a/geode-management/build.gradle
+++ b/geode-management/build.gradle
@@ -28,11 +28,15 @@ dependencies {
compile('org.springframework:spring-web')
compile('javax.xml.bind:jaxb-api')
compile('javax.xml.bind:jaxb-api')
- compile('org.apache.httpcomponents:httpclient')
+ compile('org.apache.httpcomponents:httpclient')
compileOnly(project(':geode-common')) {
exclude module: 'junit'
}
+ compileOnly('io.springfox:springfox-swagger2') {
+ exclude module: 'slf4j-api'
+ exclude module: "jackson-annotations"
+ }
testCompile(project(':geode-common'))
testCompile(project(':geode-junit')) {
diff --git a/geode-management/src/main/java/org/apache/geode/cache/configuration/BasicRegionConfig.java b/geode-management/src/main/java/org/apache/geode/cache/configuration/BasicRegionConfig.java
index 3932057..e339cae 100644
--- a/geode-management/src/main/java/org/apache/geode/cache/configuration/BasicRegionConfig.java
+++ b/geode-management/src/main/java/org/apache/geode/cache/configuration/BasicRegionConfig.java
@@ -23,6 +23,7 @@ import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
import com.fasterxml.jackson.annotation.JsonIgnore;
+import io.swagger.annotations.ApiModelProperty;
import org.apache.geode.annotations.Experimental;
import org.apache.geode.management.api.RestfulEndpoint;
@@ -47,10 +48,13 @@ public class BasicRegionConfig implements CacheElement, RestfulEndpoint {
public static final String REGION_CONFIG_ENDPOINT = "/regions";
+ @ApiModelProperty(hidden = true)
@XmlElement(name = "region-attributes", namespace = "http://geode.apache.org/schema/cache")
protected RegionAttributesType regionAttributes;
+
@XmlAttribute(name = "name", required = true)
protected String name;
+
@XmlAttribute(name = "refid")
protected String type;
diff --git a/geode-management/src/main/java/org/apache/geode/management/api/RestfulEndpoint.java b/geode-management/src/main/java/org/apache/geode/management/api/RestfulEndpoint.java
index fb01e2c..eafb00c 100644
--- a/geode-management/src/main/java/org/apache/geode/management/api/RestfulEndpoint.java
+++ b/geode-management/src/main/java/org/apache/geode/management/api/RestfulEndpoint.java
@@ -25,5 +25,6 @@ public interface RestfulEndpoint {
* @return e.g. /regions
*/
@JsonIgnore
+ // @ApiModelProperty(hidden = true)
String getEndpoint();
}
diff --git a/geode-web-management/build.gradle b/geode-web-management/build.gradle
index 73433ea..1514e58 100644
--- a/geode-web-management/build.gradle
+++ b/geode-web-management/build.gradle
@@ -51,22 +51,30 @@ dependencies {
compileOnly(project(':geode-core'))
compileOnly('javax.servlet:javax.servlet-api')
+ // jackson-annotations must be accessed from the geode classloader and not the webapp
+ compileOnly('com.fasterxml.jackson.core:jackson-annotations')
compile('org.apache.commons:commons-lang3')
compile('commons-fileupload:commons-fileupload') {
exclude module: 'commons-io'
}
- compileOnly('com.fasterxml.jackson.core:jackson-annotations')
- compileOnly('com.fasterxml.jackson.core:jackson-core')
- compileOnly('com.fasterxml.jackson.core:jackson-databind')
+ compile('com.fasterxml.jackson.core:jackson-core')
+ compile('com.fasterxml.jackson.core:jackson-databind') {
+ exclude module: 'jackson-annotations'
+ }
+
compileOnly('com.fasterxml.jackson.module:jackson-module-scala_2.10')
+ compileOnly('io.swagger:swagger-annotations')
+
compile('io.springfox:springfox-swagger2') {
exclude module: 'slf4j-api'
- exclude module: "jackson-annotations"
+ exclude module: 'jackson-annotations'
+ exclude module: 'swagger-annotations'
}
compile('io.springfox:springfox-swagger-ui') {
exclude module: 'slf4j-api'
}
+
compile('org.springframework:spring-beans')
compile('org.springframework.security:spring-security-core')
compile('org.springframework.security:spring-security-web')
diff --git a/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/ManagementLoggingFilter.java b/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/ManagementLoggingFilter.java
index 90bd556..7f02b79 100644
--- a/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/ManagementLoggingFilter.java
+++ b/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/ManagementLoggingFilter.java
@@ -52,8 +52,19 @@ public class ManagementLoggingFilter extends OncePerRequestFilter {
// performs the actual request before logging
filterChain.doFilter(wrappedRequest, wrappedResponse);
- // log after the request has been made and ContentCachingRequestWrapper has cached the request
- // payload.
+ // Log after the request has been made and ContentCachingRequestWrapper has cached the request
+ // payload. We don't want to log any swagger requests though.
+ if (!(request.getRequestURI().contains("swagger")
+ || request.getRequestURI().contains("api-docs"))) {
+ logRequest(request, wrappedRequest);
+ logResponse(response, wrappedResponse);
+ }
+
+ // IMPORTANT: copy content of response back into original response
+ wrappedResponse.copyBodyToResponse();
+ }
+
+ private void logRequest(HttpServletRequest request, ContentCachingRequestWrapper wrappedRequest) {
String requestPattern = "Management Request: %s[url=%s]; user=%s; payload=%s";
String requestUrl = request.getRequestURI();
if (request.getQueryString() != null) {
@@ -63,21 +74,22 @@ public class ManagementLoggingFilter extends OncePerRequestFilter {
wrappedRequest.getCharacterEncoding());
logger.info(String.format(requestPattern, request.getMethod(), requestUrl,
request.getRemoteUser(), payload));
+ }
+ private void logResponse(HttpServletResponse response,
+ ContentCachingResponseWrapper wrappedResponse) {
// construct the response message
String responsePattern = "Management Response: Status=%s; response=%s";
- payload = getContentAsString(wrappedResponse.getContentAsByteArray(),
+ String payload = getContentAsString(wrappedResponse.getContentAsByteArray(),
wrappedResponse.getCharacterEncoding());
payload = payload.replaceAll(System.lineSeparator(), "");
logger.info(String.format(responsePattern, response.getStatus(), payload));
-
- // IMPORTANT: copy content of response back into original response
- wrappedResponse.copyBodyToResponse();
}
private String getContentAsString(byte[] buf, String encoding) {
- if (buf == null || buf.length == 0)
+ if (buf == null || buf.length == 0) {
return "";
+ }
int length = Math.min(buf.length, MAX_PAYLOAD_LENGTH);
try {
return new String(buf, 0, length, encoding);
diff --git a/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/controllers/RegionManagementController.java b/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/controllers/RegionManagementController.java
index ac510ad..3d6a006 100644
--- a/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/controllers/RegionManagementController.java
+++ b/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/controllers/RegionManagementController.java
@@ -18,6 +18,9 @@ package org.apache.geode.management.internal.rest.controllers;
import static org.apache.geode.cache.configuration.BasicRegionConfig.REGION_CONFIG_ENDPOINT;
import static org.apache.geode.management.internal.rest.controllers.AbstractManagementController.MANAGEMENT_API_VERSION;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -34,6 +37,12 @@ import org.apache.geode.management.api.ClusterManagementResult;
@RequestMapping(MANAGEMENT_API_VERSION)
public class RegionManagementController extends AbstractManagementController {
+ @ApiOperation(value = "create regions")
+ @ApiResponses({@ApiResponse(code = 200, message = "OK."),
+ @ApiResponse(code = 401, message = "Invalid Username or Password."),
+ @ApiResponse(code = 403, message = "Insufficient privileges for operation."),
+ @ApiResponse(code = 409, message = "Region already exist."),
+ @ApiResponse(code = 500, message = "GemFire throws an error or exception.")})
@PreAuthorize("@securityService.authorize('DATA', 'MANAGE')")
@RequestMapping(method = RequestMethod.POST, value = REGION_CONFIG_ENDPOINT)
public ResponseEntity<ClusterManagementResult> createRegion(
diff --git a/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/swagger/SwaggerConfig.java b/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/swagger/SwaggerConfig.java
new file mode 100644
index 0000000..2f96f61
--- /dev/null
+++ b/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/swagger/SwaggerConfig.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.geode.management.internal.rest.swagger;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.Contact;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+
+@PropertySource({"classpath:swagger-management.properties"})
+@Configuration
+@EnableSwagger2
+@SuppressWarnings("unused")
+public class SwaggerConfig {
+
+ @Bean
+ public Docket api() {
+ return new Docket(DocumentationType.SWAGGER_2)
+ .select()
+ .apis(RequestHandlerSelectors.any())
+ .paths(PathSelectors.any())
+ .build()
+ .apiInfo(apiInfo());
+ }
+
+ /**
+ * API Info as it appears on the Swagger-UI page
+ */
+ private ApiInfo apiInfo() {
+ return new ApiInfoBuilder()
+ .title("Apache Geode Management REST API")
+ .description(
+ "REST API and interface to manage Geode components.")
+ .version("1.0")
+ .termsOfServiceUrl("http://www.apache.org/licenses/")
+ .license("Apache License, version 2.0")
+ .licenseUrl("http://www.apache.org/licenses/")
+ .contact(new Contact("the Apache Geode Community",
+ "http://geode.apache.org",
+ "dev@geode.apache.org"))
+ .build();
+ }
+}
diff --git a/geode-web-management/src/main/resources/swagger-management.properties b/geode-web-management/src/main/resources/swagger-management.properties
new file mode 100644
index 0000000..bebe4a9
--- /dev/null
+++ b/geode-web-management/src/main/resources/swagger-management.properties
@@ -0,0 +1,15 @@
+#
+# 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.
+#
+springfox.documentation.swagger.v2.path=/v2/api-docs
\ No newline at end of file
diff --git a/geode-web-management/src/main/webapp/docs/index.html b/geode-web-management/src/main/webapp/docs/index.html
new file mode 100644
index 0000000..946a142
--- /dev/null
+++ b/geode-web-management/src/main/webapp/docs/index.html
@@ -0,0 +1,16 @@
+<!--
+ ~ 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.
+ -->
+
+<meta http-equiv="refresh" content="0; URL='/geode-management/swagger-ui.html'"/>
\ No newline at end of file
diff --git a/geode-web-management/src/test/resources/expected-pom.xml b/geode-web-management/src/test/resources/expected-pom.xml
index d9e364c..b4c1896 100644
--- a/geode-web-management/src/test/resources/expected-pom.xml
+++ b/geode-web-management/src/test/resources/expected-pom.xml
@@ -63,6 +63,22 @@
</exclusions>
</dependency>
<dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <scope>compile</scope>
+ <exclusions>
+ <exclusion>
+ <artifactId>jackson-annotations</artifactId>
+ <groupId>*</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<scope>compile</scope>
@@ -75,6 +91,10 @@
<artifactId>jackson-annotations</artifactId>
<groupId>*</groupId>
</exclusion>
+ <exclusion>
+ <artifactId>swagger-annotations</artifactId>
+ <groupId>*</groupId>
+ </exclusion>
</exclusions>
</dependency>
<dependency>