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 092f598  GEODE-6384: Create consistent API to retrieve instances of 
ClusterManagementService (#3191)
092f598 is described below

commit 092f5981c79b10ca5c6da642d1df8348f235f41c
Author: Jens Deppe <jde...@pivotal.io>
AuthorDate: Fri Feb 22 05:17:36 2019 -0800

    GEODE-6384: Create consistent API to retrieve instances of 
ClusterManagementService (#3191)
    
    
    - The overall intent of this commit is to provide a consistent means for
      retrieving a ClusterMangementService instance regardless of the
      context you are developing in. Currently, the relevant contexts are:
      1) a Java application that has no access (or need to access) core
      Geode code. 2) a typical Geode client application and 3) server or
      locator-side code.
    - Introduces a service provider interface
      (ClusterManagementServiceProviderFactory) whose implementations are
      context dependent. This commit introduces two implementations, namely:
      BasicClusterManagementProviderFactory and
      SmartClusterManagementServiceProviderFactory). The latter is
      incomplete but will be fully supported in the near future.
    - The entry point to creating a ClusterManagementService is in
      ClusterManagementServiceProvider - more documentation can be found
      there.
---
 geode-assembly/build.gradle                        |   1 +
 .../geode/test/junit/rules/HttpResponseAssert.java |   2 +-
 ...ClusterManagementLocatorReconnectDunitTest.java |   2 +-
 .../internal/rest/RegionManagementDunitTest.java   |  40 ++++-
 .../internal/DisabledClusterConfigTest.java        |   2 +-
 .../integrationTest/resources/assembly_content.txt |  17 ++
 ...ClusterManagementServiceRetrievalDUnitTest.java |  53 ++++++
 .../internal/api/RegionAPIDUnitTest.java           |   1 +
 .../commands/DescribeMembersCommandDUnitTest.java  |  42 ++++-
 .../distributed/internal/InternalLocator.java      |   2 +-
 .../internal/cache/ClusterConfigurationLoader.java |   1 -
 ...odeClusterManagementServiceProviderFactory.java | 124 ++++++++++++++
 .../api/LocatorClusterManagementService.java       |   2 +
 .../cli/commands/DescribeMemberCommand.java        |   5 -
 .../internal/cli/domain/MemberInformation.java     |  27 ++--
 .../functions/GetMemberInformationFunction.java    |  21 ++-
 .../internal/cli/util/MemberInformation.java       | 180 ---------------------
 ...ent.spi.ClusterManagementServiceProviderFactory |  16 ++
 .../sanctioned-geode-core-serializables.txt        |   5 +-
 .../internal/api/ClusterManagementResultTest.java  |   2 +
 .../api/LocatorClusterManagementServiceTest.java   |   1 +
 .../geode/test/dunit/rules/ClusterStartupRule.java |  23 ++-
 geode-management/build.gradle                      |   1 +
 .../geode/cache/configuration/RegionConfig.java    |   8 +-
 .../api/ClusterManagementResult.java               |   2 +-
 .../api/ClusterManagementService.java              |  38 ++++-
 .../api/Status.java => api/RestfulEndpoint.java}   |  29 +---
 .../management/{internal => }/api/Status.java      |   2 +-
 .../client/ClusterManagementServiceProvider.java   | 119 ++++++++++++++
 .../client/RestTemplateResponseErrorHandler.java   |  25 +--
 .../internal/ClusterManagementClient.java          | 105 ++++++++++++
 .../ClusterManagementServiceProviderFactory.java   |  60 +++++++
 ...JavaClientClusterManagementProviderFactory.java |  54 +++++++
 ...ent.spi.ClusterManagementServiceProviderFactory |  17 ++
 .../src/test/resources/expected-pom.xml            |   5 +
 geode-web-management/build.gradle                  |   4 +
 ...xtLoader.java => BaseLocatorContextLoader.java} |  17 +-
 .../LocatorWithSecurityManagerContextLoader.java   |  31 ++--
 .../internal/rest/PlainLocatorContextLoader.java   |  36 ++---
 .../rest/StandardRequestPostProcessor.java         |   2 +-
 .../client/ClusterManagementClientDUnitTest.java   |  87 ++++++++++
 .../rest/RegionManagementIntegrationTest.java      |   3 +-
 .../controllers/ManagementControllerAdvice.java    |   4 +-
 .../controllers/RegionManagementController.java    |   2 +-
 .../rest/security/RestSecurityConfiguration.java   |   2 +-
 45 files changed, 900 insertions(+), 322 deletions(-)

diff --git a/geode-assembly/build.gradle b/geode-assembly/build.gradle
index 1a1da28..c5d8510 100755
--- a/geode-assembly/build.gradle
+++ b/geode-assembly/build.gradle
@@ -189,6 +189,7 @@ dependencies {
   distributedTestCompile(project(':extensions:session-testing-war'))
   distributedTestCompile(project(':geode-assembly:geode-assembly-test'))
   distributedTestCompile('org.apache.httpcomponents:httpclient')
+  distributedTestCompile('org.springframework:spring-web')
 
   
distributedTestRuntime(project(':extensions:geode-modules-session-internal')) {
     exclude group: 'org.apache.tomcat'
diff --git 
a/geode-assembly/geode-assembly-test/src/main/java/org/apache/geode/test/junit/rules/HttpResponseAssert.java
 
b/geode-assembly/geode-assembly-test/src/main/java/org/apache/geode/test/junit/rules/HttpResponseAssert.java
index 63e0c61..5ff00de 100644
--- 
a/geode-assembly/geode-assembly-test/src/main/java/org/apache/geode/test/junit/rules/HttpResponseAssert.java
+++ 
b/geode-assembly/geode-assembly-test/src/main/java/org/apache/geode/test/junit/rules/HttpResponseAssert.java
@@ -33,7 +33,7 @@ import org.assertj.core.api.AbstractCharSequenceAssert;
 import org.assertj.core.api.ListAssert;
 
 import org.apache.geode.internal.logging.LogService;
-import org.apache.geode.management.internal.api.ClusterManagementResult;
+import org.apache.geode.management.api.ClusterManagementResult;
 
 public class HttpResponseAssert extends AbstractAssert<HttpResponseAssert, 
HttpResponse> {
   private static final Logger logger = LogService.getLogger();
diff --git 
a/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/ClusterManagementLocatorReconnectDunitTest.java
 
b/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/ClusterManagementLocatorReconnectDunitTest.java
index 846c162..7d70f08 100644
--- 
a/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/ClusterManagementLocatorReconnectDunitTest.java
+++ 
b/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/ClusterManagementLocatorReconnectDunitTest.java
@@ -28,7 +28,7 @@ import org.apache.geode.cache.Region;
 import org.apache.geode.cache.configuration.CacheConfig;
 import org.apache.geode.cache.configuration.CacheElement;
 import org.apache.geode.cache.configuration.RegionConfig;
-import org.apache.geode.management.internal.api.ClusterManagementResult;
+import org.apache.geode.management.api.ClusterManagementResult;
 import org.apache.geode.test.dunit.IgnoredException;
 import org.apache.geode.test.dunit.rules.ClusterStartupRule;
 import org.apache.geode.test.dunit.rules.MemberVM;
diff --git 
a/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/RegionManagementDunitTest.java
 
b/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/RegionManagementDunitTest.java
index 679eaea..db5263a 100644
--- 
a/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/RegionManagementDunitTest.java
+++ 
b/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/RegionManagementDunitTest.java
@@ -21,13 +21,15 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
 import org.junit.Test;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.client.RestTemplate;
 
 import org.apache.geode.cache.Cache;
 import org.apache.geode.cache.Region;
 import org.apache.geode.cache.configuration.CacheConfig;
 import org.apache.geode.cache.configuration.CacheElement;
 import org.apache.geode.cache.configuration.RegionConfig;
-import org.apache.geode.management.internal.api.ClusterManagementResult;
+import org.apache.geode.management.api.ClusterManagementResult;
 import org.apache.geode.test.dunit.IgnoredException;
 import org.apache.geode.test.dunit.rules.ClusterStartupRule;
 import org.apache.geode.test.dunit.rules.MemberVM;
@@ -78,6 +80,42 @@ public class RegionManagementDunitTest {
   }
 
   @Test
+  public void createsRegionUsingClusterManagementClient() throws Exception {
+    RegionConfig regionConfig = new RegionConfig();
+    regionConfig.setName("customers2");
+    regionConfig.setType("REPLICATE");
+    ObjectMapper mapper = new ObjectMapper();
+    String json = mapper.writeValueAsString(regionConfig);
+
+    String url = 
String.format("http://localhost:%d/geode-management/v2/regions";,
+        locator.getHttpPort());
+    RestTemplate template = new RestTemplate();
+
+    ResponseEntity<ClusterManagementResult> result =
+        template.postForEntity(url, regionConfig, 
ClusterManagementResult.class);
+
+    result.getBody();
+
+    // ClusterManagementResult result =
+    // restClient.doPostAndAssert("/regions", json)
+    // .hasStatusCode(201)
+    // .getClusterManagementResult();
+    //
+    // assertThat(result.isSuccessfullyAppliedOnMembers()).isTrue();
+    // assertThat(result.isSuccessfullyPersisted()).isTrue();
+    // 
assertThat(result.getMemberStatuses()).containsKeys("server-1").hasSize(1);
+    //
+    // // make sure region is created
+    // server.invoke(() -> verifyRegionCreated("customers", "REPLICATE"));
+    //
+    // // make sure region is persisted
+    // locator.invoke(() -> verifyRegionPersisted("customers", "REPLICATE"));
+    //
+    // // verify that additional server can be started with the cluster 
configuration
+    // cluster.startServerVM(2, locator.getPort());
+  }
+
+  @Test
   public void createsAPartitionedRegionByDefault() throws Exception {
     String json = "{\"name\": \"orders\"}";
 
diff --git 
a/geode-assembly/src/integrationTest/java/org/apache/geode/management/internal/DisabledClusterConfigTest.java
 
b/geode-assembly/src/integrationTest/java/org/apache/geode/management/internal/DisabledClusterConfigTest.java
index f596830..d7af562 100644
--- 
a/geode-assembly/src/integrationTest/java/org/apache/geode/management/internal/DisabledClusterConfigTest.java
+++ 
b/geode-assembly/src/integrationTest/java/org/apache/geode/management/internal/DisabledClusterConfigTest.java
@@ -22,7 +22,7 @@ import org.junit.Rule;
 import org.junit.Test;
 
 import org.apache.geode.distributed.ConfigurationProperties;
-import org.apache.geode.management.internal.api.ClusterManagementResult;
+import org.apache.geode.management.api.ClusterManagementResult;
 import org.apache.geode.test.junit.rules.GeodeDevRestClient;
 import org.apache.geode.test.junit.rules.LocatorStarterRule;
 import org.apache.geode.test.junit.rules.RequiresGeodeHome;
diff --git a/geode-assembly/src/integrationTest/resources/assembly_content.txt 
b/geode-assembly/src/integrationTest/resources/assembly_content.txt
index ab83cdd..c2569de 100644
--- a/geode-assembly/src/integrationTest/resources/assembly_content.txt
+++ b/geode-assembly/src/integrationTest/resources/assembly_content.txt
@@ -676,6 +676,13 @@ 
javadoc/org/apache/geode/management/PersistentMemberDetails.html
 javadoc/org/apache/geode/management/RegionAttributesData.html
 javadoc/org/apache/geode/management/RegionMXBean.html
 javadoc/org/apache/geode/management/ServerLoadData.html
+javadoc/org/apache/geode/management/api/ClusterManagementResult.html
+javadoc/org/apache/geode/management/api/ClusterManagementService.html
+javadoc/org/apache/geode/management/api/RestfulEndpoint.html
+javadoc/org/apache/geode/management/api/Status.html
+javadoc/org/apache/geode/management/api/package-frame.html
+javadoc/org/apache/geode/management/api/package-summary.html
+javadoc/org/apache/geode/management/api/package-tree.html
 javadoc/org/apache/geode/management/cli/CliFunction.html
 javadoc/org/apache/geode/management/cli/CliMetaData.AvailabilityMetadata.html
 javadoc/org/apache/geode/management/cli/CliMetaData.html
@@ -693,6 +700,11 @@ 
javadoc/org/apache/geode/management/cli/UpdateAllConfigurationGroupsMarker.html
 javadoc/org/apache/geode/management/cli/package-frame.html
 javadoc/org/apache/geode/management/cli/package-summary.html
 javadoc/org/apache/geode/management/cli/package-tree.html
+javadoc/org/apache/geode/management/client/ClusterManagementServiceProvider.html
+javadoc/org/apache/geode/management/client/RestTemplateResponseErrorHandler.html
+javadoc/org/apache/geode/management/client/package-frame.html
+javadoc/org/apache/geode/management/client/package-summary.html
+javadoc/org/apache/geode/management/client/package-tree.html
 javadoc/org/apache/geode/management/membership/ClientMembership.html
 javadoc/org/apache/geode/management/membership/ClientMembershipEvent.html
 javadoc/org/apache/geode/management/membership/ClientMembershipListener.html
@@ -707,6 +719,11 @@ 
javadoc/org/apache/geode/management/membership/package-tree.html
 javadoc/org/apache/geode/management/package-frame.html
 javadoc/org/apache/geode/management/package-summary.html
 javadoc/org/apache/geode/management/package-tree.html
+javadoc/org/apache/geode/management/spi/ClusterManagementServiceProviderFactory.html
+javadoc/org/apache/geode/management/spi/JavaClientClusterManagementProviderFactory.html
+javadoc/org/apache/geode/management/spi/package-frame.html
+javadoc/org/apache/geode/management/spi/package-summary.html
+javadoc/org/apache/geode/management/spi/package-tree.html
 javadoc/org/apache/geode/memcached/GemFireMemcachedServer.Protocol.html
 javadoc/org/apache/geode/memcached/GemFireMemcachedServer.html
 javadoc/org/apache/geode/memcached/package-frame.html
diff --git 
a/geode-core/src/distributedTest/java/org/apache/geode/management/api/ClusterManagementServiceRetrievalDUnitTest.java
 
b/geode-core/src/distributedTest/java/org/apache/geode/management/api/ClusterManagementServiceRetrievalDUnitTest.java
new file mode 100644
index 0000000..708da0c
--- /dev/null
+++ 
b/geode-core/src/distributedTest/java/org/apache/geode/management/api/ClusterManagementServiceRetrievalDUnitTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.api;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.springframework.web.util.AbstractUriTemplateHandler;
+
+import org.apache.geode.management.client.ClusterManagementServiceProvider;
+import org.apache.geode.management.internal.ClusterManagementClient;
+import org.apache.geode.test.dunit.rules.ClusterStartupRule;
+import org.apache.geode.test.dunit.rules.MemberVM;
+
+public class ClusterManagementServiceRetrievalDUnitTest {
+
+  private static MemberVM locator;
+  private static MemberVM server1;
+
+  @ClassRule
+  public static ClusterStartupRule cluster = new ClusterStartupRule();
+
+  @Test
+  public void retrieveClusterManagementServiceFromServer() {
+    locator = cluster.startLocatorVM(0,
+        x -> x.withHttpService());
+    server1 = cluster.startServerVM(1, locator.getPort());
+
+    final String url = String.format("http://localhost:%d";, 
locator.getHttpPort());
+    server1.invoke(() -> {
+      ClusterManagementClient cms =
+          (ClusterManagementClient) 
ClusterManagementServiceProvider.getService();
+      assertThat(
+          ((AbstractUriTemplateHandler) 
cms.getRestTemplate().getUriTemplateHandler()).getBaseUrl())
+              .isEqualTo(url);
+    });
+  }
+
+}
diff --git 
a/geode-core/src/distributedTest/java/org/apache/geode/management/internal/api/RegionAPIDUnitTest.java
 
b/geode-core/src/distributedTest/java/org/apache/geode/management/internal/api/RegionAPIDUnitTest.java
index 0c2fec2..8633015 100644
--- 
a/geode-core/src/distributedTest/java/org/apache/geode/management/internal/api/RegionAPIDUnitTest.java
+++ 
b/geode-core/src/distributedTest/java/org/apache/geode/management/internal/api/RegionAPIDUnitTest.java
@@ -29,6 +29,7 @@ import org.apache.geode.cache.RegionShortcut;
 import org.apache.geode.cache.configuration.CacheConfig;
 import org.apache.geode.cache.configuration.CacheElement;
 import org.apache.geode.cache.configuration.RegionConfig;
+import org.apache.geode.management.api.ClusterManagementResult;
 import org.apache.geode.test.dunit.rules.ClusterStartupRule;
 import org.apache.geode.test.dunit.rules.MemberVM;
 import org.apache.geode.test.junit.categories.RegionsTest;
diff --git 
a/geode-core/src/distributedTest/java/org/apache/geode/management/internal/cli/commands/DescribeMembersCommandDUnitTest.java
 
b/geode-core/src/distributedTest/java/org/apache/geode/management/internal/cli/commands/DescribeMembersCommandDUnitTest.java
index 942fd49..b6c61fb 100644
--- 
a/geode-core/src/distributedTest/java/org/apache/geode/management/internal/cli/commands/DescribeMembersCommandDUnitTest.java
+++ 
b/geode-core/src/distributedTest/java/org/apache/geode/management/internal/cli/commands/DescribeMembersCommandDUnitTest.java
@@ -15,6 +15,9 @@
 package org.apache.geode.management.internal.cli.commands;
 
 import static 
org.apache.geode.management.internal.cli.i18n.CliStrings.DESCRIBE_MEMBER;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Map;
 
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
@@ -22,6 +25,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
+import org.apache.geode.management.internal.cli.result.CommandResult;
 import org.apache.geode.test.dunit.rules.ClusterStartupRule;
 import org.apache.geode.test.dunit.rules.MemberVM;
 import org.apache.geode.test.junit.categories.JMXTest;
@@ -58,14 +62,44 @@ public class DescribeMembersCommandDUnitTest {
   @Test
   public void describeLocator() throws Exception {
     gfsh.connectAndVerify(locator);
-    gfsh.executeAndAssertThat(DESCRIBE_MEMBER + " 
--name=locator-0").statusIsSuccess()
-        .containsOutput("locator-0").doesNotContainOutput("server-1");
+    CommandResult result = gfsh.executeAndAssertThat(DESCRIBE_MEMBER + " 
--name=locator-0")
+        .statusIsSuccess()
+        .getCommandResult();
+
+    Map<String, String> memberInfo = result.getMapFromSection("0");
+    assertThat(memberInfo.get("Name")).isEqualTo("locator-0");
+    assertThat(memberInfo.get("Id")).contains("locator-0");
+    assertThat(memberInfo.get("Host")).as("Host").isNotBlank();
+    assertThat(memberInfo.get("PID")).as("PID").isNotBlank();
+    assertThat(memberInfo.get("Used Heap")).as("Used Heap").isNotBlank();
+    assertThat(memberInfo.get("Max Heap")).as("Max Heap").isNotBlank();
+    assertThat(memberInfo.get("Working Dir")).as("Working Dir").isNotBlank();
+    assertThat(memberInfo.get("Log file")).as("Log File").isNotBlank();
+    assertThat(memberInfo.get("Locators")).as("Locators").isNotBlank();
   }
 
   @Test
   public void describeServer() throws Exception {
     gfsh.connectAndVerify(locator);
-    gfsh.executeAndAssertThat(DESCRIBE_MEMBER + " 
--name=server-1").statusIsSuccess()
-        .doesNotContainOutput("locator-0").containsOutput("server-1");
+    CommandResult result = gfsh.executeAndAssertThat(DESCRIBE_MEMBER + " 
--name=server-1")
+        .statusIsSuccess()
+        .getCommandResult();
+
+    Map<String, String> memberInfo = result.getMapFromSection("0");
+    assertThat(memberInfo.get("Name")).isEqualTo("server-1");
+    assertThat(memberInfo.get("Id")).contains("server-1");
+    assertThat(memberInfo.get("Host")).as("Host").isNotBlank();
+    assertThat(memberInfo.get("PID")).as("PID").isNotBlank();
+    assertThat(memberInfo.get("Used Heap")).as("Used Heap").isNotBlank();
+    assertThat(memberInfo.get("Max Heap")).as("Max Heap").isNotBlank();
+    assertThat(memberInfo.get("Working Dir")).as("Working Dir").isNotBlank();
+    assertThat(memberInfo.get("Log file")).as("Log File").isNotBlank();
+    assertThat(memberInfo.get("Locators")).as("Locators").isNotBlank();
+
+    Map<String, String> cacheServerInfo = result.getMapFromSection("1");
+    assertThat(cacheServerInfo.get("Server Bind")).as("Server Bind").isBlank();
+    assertThat(cacheServerInfo.get("Server Port")).as("Server 
Port").isNotBlank();
+    assertThat(cacheServerInfo.get("Running")).as("Running").isEqualTo("true");
+    assertThat(cacheServerInfo.get("Client Connections")).as("Client 
Connections").isEqualTo("0");
   }
 }
diff --git 
a/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalLocator.java
 
b/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalLocator.java
index 03cf0e6..28bd0bd 100644
--- 
a/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalLocator.java
+++ 
b/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalLocator.java
@@ -83,10 +83,10 @@ import org.apache.geode.internal.logging.NullLoggingSession;
 import org.apache.geode.internal.net.SocketCreator;
 import org.apache.geode.internal.net.SocketCreatorFactory;
 import org.apache.geode.internal.statistics.StatisticsConfig;
+import org.apache.geode.management.api.ClusterManagementService;
 import org.apache.geode.management.internal.AgentUtil;
 import org.apache.geode.management.internal.JmxManagerLocator;
 import org.apache.geode.management.internal.JmxManagerLocatorRequest;
-import org.apache.geode.management.internal.api.ClusterManagementService;
 import 
org.apache.geode.management.internal.api.LocatorClusterManagementService;
 import 
org.apache.geode.management.internal.configuration.domain.SharedConfigurationStatus;
 import 
org.apache.geode.management.internal.configuration.handlers.SharedConfigurationStatusRequestHandler;
diff --git 
a/geode-core/src/main/java/org/apache/geode/internal/cache/ClusterConfigurationLoader.java
 
b/geode-core/src/main/java/org/apache/geode/internal/cache/ClusterConfigurationLoader.java
index 7780600..3e15b00 100644
--- 
a/geode-core/src/main/java/org/apache/geode/internal/cache/ClusterConfigurationLoader.java
+++ 
b/geode-core/src/main/java/org/apache/geode/internal/cache/ClusterConfigurationLoader.java
@@ -272,7 +272,6 @@ public class ClusterConfigurationLoader {
       throws ClusterConfigurationNotAvailableException, UnknownHostException {
 
     Set<String> groups = getGroups(groupList);
-    GetClusterConfigurationFunction function = new 
GetClusterConfigurationFunction();
 
     ConfigurationResponse response = null;
 
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/api/GeodeClusterManagementServiceProviderFactory.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/api/GeodeClusterManagementServiceProviderFactory.java
new file mode 100644
index 0000000..ce8d9c7
--- /dev/null
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/api/GeodeClusterManagementServiceProviderFactory.java
@@ -0,0 +1,124 @@
+/*
+ * 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.api;
+
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.logging.log4j.Logger;
+
+import org.apache.geode.annotations.Immutable;
+import org.apache.geode.cache.Cache;
+import org.apache.geode.cache.CacheFactory;
+import org.apache.geode.cache.client.ClientCache;
+import org.apache.geode.cache.client.ClientCacheFactory;
+import org.apache.geode.cache.execute.FunctionException;
+import org.apache.geode.cache.execute.FunctionService;
+import org.apache.geode.cache.execute.ResultCollector;
+import org.apache.geode.distributed.internal.InternalLocator;
+import 
org.apache.geode.distributed.internal.membership.InternalDistributedMember;
+import org.apache.geode.internal.cache.GemFireCacheImpl;
+import org.apache.geode.internal.logging.LogService;
+import org.apache.geode.management.api.ClusterManagementService;
+import org.apache.geode.management.client.ClusterManagementServiceProvider;
+import org.apache.geode.management.internal.ClusterManagementClient;
+import org.apache.geode.management.internal.cli.domain.MemberInformation;
+import 
org.apache.geode.management.internal.cli.functions.GetMemberInformationFunction;
+import org.apache.geode.management.spi.ClusterManagementServiceProviderFactory;
+import 
org.apache.geode.management.spi.JavaClientClusterManagementProviderFactory;
+
+/**
+ * An implementation of {@link ClusterManagementServiceProviderFactory} which 
can be used in any
+ * context where Geode is running (client, server or locator). It will attempt 
to determine the
+ * address of the {@code ClusterManagementService} when using the {@code 
create()} call. Otherwise
+ * an explicit can also be used.
+ */
+public class GeodeClusterManagementServiceProviderFactory extends
+    JavaClientClusterManagementProviderFactory {
+
+  @Immutable
+  private static final GetMemberInformationFunction 
MEMBER_INFORMATION_FUNCTION =
+      new GetMemberInformationFunction();
+
+  private static final Logger logger = LogService.getLogger();
+
+  @Override
+  public String getContext() {
+    return ClusterManagementServiceProvider.GEODE_CONTEXT;
+  }
+
+  @Override
+  public ClusterManagementService create() throws IllegalStateException {
+    if (InternalLocator.getLocator() != null) {
+      return InternalLocator.getLocator().getClusterManagementService();
+    }
+
+    Cache cache = CacheFactory.getAnyInstance();
+    if (cache != null && cache.isServer()) {
+      GemFireCacheImpl cacheImpl = (GemFireCacheImpl) cache;
+
+      Set<InternalDistributedMember> locatorsWithClusterConfig =
+          
cacheImpl.getDistributionManager().getAllHostedLocatorsWithSharedConfiguration()
+              .keySet();
+      String serviceAddress = getHttpServiceAddress(locatorsWithClusterConfig);
+
+      return new ClusterManagementClient(serviceAddress);
+    }
+
+    ClientCache clientCache = ClientCacheFactory.getAnyInstance();
+    if (clientCache != null) {
+      throw new IllegalStateException(
+          "Under construction. To retrieve an instance of 
ClusterManagementService from a Geode client, please use either 
create(clusterUrl) or create(requestFactory) methods");
+    }
+    // } catch( CacheClosedException e) {
+    throw new IllegalStateException("ClusterManagementService.create() " +
+        "must be executed on one of locator, server or client cache VMs");
+  }
+
+  private String getHttpServiceAddress(Set<InternalDistributedMember> 
locators) {
+    for (InternalDistributedMember locator : locators) {
+
+      try {
+        ResultCollector resultCollector =
+            
FunctionService.onMember(locator).execute(MEMBER_INFORMATION_FUNCTION);
+        List<MemberInformation> memberInformation =
+            (List<MemberInformation>) resultCollector.getResult();
+        // Is this even possible?
+        if (memberInformation.isEmpty()) {
+          continue;
+        }
+
+        // What address to use
+        String host;
+        if 
(StringUtils.isNotBlank(memberInformation.get(0).getHttpServiceBindAddress())) {
+          host = memberInformation.get(0).getHttpServiceBindAddress();
+        } else if 
(StringUtils.isNotBlank(memberInformation.get(0).getServerBindAddress())) {
+          host = memberInformation.get(0).getServerBindAddress();
+        } else {
+          host = memberInformation.get(0).getHost();
+        }
+
+        return String.format("http://%s:%d";, host, 
memberInformation.get(0).getHttpServicePort());
+      } catch (FunctionException e) {
+        logger.warn("Unable to execute GetMemberInformationFunction on " + 
locator.getId());
+        throw new IllegalStateException(e);
+      }
+    }
+
+    throw new IllegalStateException("Unable to determine 
ClusterManagementService endpoint");
+  }
+}
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/api/LocatorClusterManagementService.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/api/LocatorClusterManagementService.java
index 69aa45e..c439f7c 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/api/LocatorClusterManagementService.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/api/LocatorClusterManagementService.java
@@ -35,6 +35,8 @@ import 
org.apache.geode.distributed.ConfigurationPersistenceService;
 import org.apache.geode.distributed.DistributedMember;
 import org.apache.geode.distributed.internal.DistributionManager;
 import org.apache.geode.internal.logging.LogService;
+import org.apache.geode.management.api.ClusterManagementResult;
+import org.apache.geode.management.api.ClusterManagementService;
 import org.apache.geode.management.internal.cli.CliUtil;
 import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
 import org.apache.geode.management.internal.cli.functions.UpdateCacheFunction;
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DescribeMemberCommand.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DescribeMemberCommand.java
index b874f5a..753e159 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DescribeMemberCommand.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DescribeMemberCommand.java
@@ -65,11 +65,6 @@ public class DescribeMemberCommand extends 
InternalGfshCommand {
         CompositeResultData crd = ResultBuilder.createCompositeResultData();
 
         MemberInformation memberInformation = (MemberInformation) obj;
-        memberInformation.setName(memberToBeDescribed.getName());
-        memberInformation.setId(memberToBeDescribed.getId());
-        memberInformation.setHost(memberToBeDescribed.getHost());
-        memberInformation.setProcessId("" + 
memberToBeDescribed.getProcessId());
-
         CompositeResultData.SectionResultData section = crd.addSection();
         section.addData("Name", memberInformation.getName());
         section.addData("Id", memberInformation.getId());
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/MemberInformation.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/MemberInformation.java
index a5e1325..357b976 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/MemberInformation.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/MemberInformation.java
@@ -41,8 +41,9 @@ public class MemberInformation implements Serializable {
   private String cacheXmlFilePath;
   private String host;
   private String processId;
-  private String locatorBindAddress;
   private int locatorPort;
+  private int httpServicePort;
+  private String httpServiceBindAddress;
   private boolean isServer;
   private List<CacheServerInfo> cacheServerList;
   private int clientCount;
@@ -170,14 +171,6 @@ public class MemberInformation implements Serializable {
     this.processId = processId;
   }
 
-  public String getLocatorBindAddress() {
-    return locatorBindAddress;
-  }
-
-  public void setLocatorBindAddress(String locatorBindAddress) {
-    this.locatorBindAddress = locatorBindAddress;
-  }
-
   public int getLocatorPort() {
     return locatorPort;
   }
@@ -186,6 +179,22 @@ public class MemberInformation implements Serializable {
     this.locatorPort = locatorPort;
   }
 
+  public int getHttpServicePort() {
+    return httpServicePort;
+  }
+
+  public void setHttpServicePort(int httpServicePort) {
+    this.httpServicePort = httpServicePort;
+  }
+
+  public String getHttpServiceBindAddress() {
+    return httpServiceBindAddress;
+  }
+
+  public void setHttpServiceBindAddress(String httpServiceBindAddress) {
+    this.httpServiceBindAddress = httpServiceBindAddress;
+  }
+
   public boolean isServer() {
     return isServer;
   }
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/GetMemberInformationFunction.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/GetMemberInformationFunction.java
index 999f9eb..88c4ee4 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/GetMemberInformationFunction.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/GetMemberInformationFunction.java
@@ -25,9 +25,11 @@ import org.apache.geode.cache.Cache;
 import org.apache.geode.cache.CacheClosedException;
 import org.apache.geode.cache.execute.FunctionContext;
 import org.apache.geode.cache.server.CacheServer;
+import org.apache.geode.distributed.DistributedMember;
 import org.apache.geode.distributed.internal.DistributionConfig;
 import org.apache.geode.distributed.internal.InternalDistributedSystem;
 import org.apache.geode.internal.cache.CacheClientStatus;
+import org.apache.geode.internal.cache.InternalCache;
 import org.apache.geode.internal.cache.execute.InternalFunction;
 import org.apache.geode.internal.cache.tier.InternalClientMembership;
 import org.apache.geode.internal.cache.tier.sockets.ClientProxyMembershipID;
@@ -41,7 +43,8 @@ import 
org.apache.geode.management.internal.cli.domain.MemberInformation;
  */
 
 public class GetMemberInformationFunction implements InternalFunction {
-  private static final long serialVersionUID = 1L;
+
+  private static final long serialVersionUID = 1404642539058875565L;
 
   @Override
   public String getId() {
@@ -73,19 +76,29 @@ public class GetMemberInformationFunction implements 
InternalFunction {
 
       InternalDistributedSystem system = (InternalDistributedSystem) 
cache.getDistributedSystem();
       DistributionConfig config = system.getConfig();
-      String serverBindAddress = config.getServerBindAddress();
-      MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
+      DistributedMember member =
+          
CliUtil.getDistributedMemberByNameOrId(functionContext.getMemberName(),
+              (InternalCache) functionContext.getCache());
 
       MemberInformation memberInfo = new MemberInformation();
+
+      memberInfo.setName(member.getName());
+      memberInfo.setId(member.getId());
+      memberInfo.setHost(member.getHost());
+      memberInfo.setProcessId("" + member.getProcessId());
+
       memberInfo.setGroups(config.getGroups());
       memberInfo.setLogFilePath(config.getLogFile().getCanonicalPath());
       
memberInfo.setStatArchiveFilePath(config.getStatisticArchiveFile().getCanonicalPath());
       memberInfo.setWorkingDirPath(System.getProperty("user.dir"));
       
memberInfo.setCacheXmlFilePath(config.getCacheXmlFile().getCanonicalPath());
       memberInfo.setLocators(config.getLocators());
-      memberInfo.setServerBindAddress(serverBindAddress);
+      memberInfo.setServerBindAddress(config.getServerBindAddress());
       memberInfo.setOffHeapMemorySize(config.getOffHeapMemorySize());
+      memberInfo.setHttpServicePort(config.getHttpServicePort());
+      memberInfo.setHttpServiceBindAddress(config.getHttpServiceBindAddress());
 
+      MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
       MemoryUsage memUsage = memoryMXBean.getHeapMemoryUsage();
       memberInfo.setHeapUsage(Long.toString(bytesToMeg(memUsage.getUsed())));
       memberInfo.setMaxHeapSize(Long.toString(bytesToMeg(memUsage.getMax())));
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/MemberInformation.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/MemberInformation.java
deleted file mode 100644
index a59f23a..0000000
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/util/MemberInformation.java
+++ /dev/null
@@ -1,180 +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.geode.management.internal.cli.util;
-
-import java.io.Serializable;
-
-
-/***
- * Data class to hold the information of the member Used in describe member 
command
- *
- */
-public class MemberInformation implements Serializable {
-  private static final long serialVersionUID = 1L;
-  private String name;
-  private String id;
-  private String workingDirPath;
-  private String groups;
-  private String logFilePath;
-  private String statArchiveFilePath;
-  private String cpuUsage;
-  private String serverBindAddress;
-  private String locators;
-  private String heapUsage;
-  private String maxHeapSize;
-  private String initHeapSize;
-  private String cacheXmlFilePath;
-  private String host;
-  private String processId;
-  private String locatorBindAddress;
-  private int locatorPort;
-
-
-  public String getName() {
-    return name;
-  }
-
-  public void setName(String name) {
-    this.name = name;
-  }
-
-  public String getId() {
-    return id;
-  }
-
-  public void setId(String id) {
-    this.id = id;
-  }
-
-  public String getWorkingDirPath() {
-    return workingDirPath;
-  }
-
-  public void setWorkingDirPath(String workingDirPath) {
-    this.workingDirPath = workingDirPath;
-  }
-
-  public String getGroups() {
-    return groups;
-  }
-
-  public void setGroups(String groups) {
-    this.groups = groups;
-  }
-
-  public String getLogFilePath() {
-    return logFilePath;
-  }
-
-  public void setLogFilePath(String logFilePath) {
-    this.logFilePath = logFilePath;
-  }
-
-  public String getStatArchiveFilePath() {
-    return statArchiveFilePath;
-  }
-
-  public void setStatArchiveFilePath(String statArchiveFilePath) {
-    this.statArchiveFilePath = statArchiveFilePath;
-  }
-
-  public String getCpuUsage() {
-    return cpuUsage;
-  }
-
-  public void setCpuUsage(String cpuUsage) {
-    this.cpuUsage = cpuUsage;
-  }
-
-  public String getServerBindAddress() {
-    return serverBindAddress;
-  }
-
-  public void setServerBindAddress(String serverBindAddress) {
-    this.serverBindAddress = serverBindAddress;
-  }
-
-  public String getLocators() {
-    return locators;
-  }
-
-  public void setLocators(String locators) {
-    this.locators = locators;
-  }
-
-  public String getHeapUsage() {
-    return heapUsage;
-  }
-
-  public void setHeapUsage(String heapUsage) {
-    this.heapUsage = heapUsage;
-  }
-
-  public String getMaxHeapSize() {
-    return maxHeapSize;
-  }
-
-  public void setMaxHeapSize(String maxHeapSize) {
-    this.maxHeapSize = maxHeapSize;
-  }
-
-  public String getCacheXmlFilePath() {
-    return cacheXmlFilePath;
-  }
-
-  public void setCacheXmlFilePath(String cacheXmlFilePath) {
-    this.cacheXmlFilePath = cacheXmlFilePath;
-  }
-
-  public String getInitHeapSize() {
-    return initHeapSize;
-  }
-
-  public void setInitHeapSize(String initHeapSize) {
-    this.initHeapSize = initHeapSize;
-  }
-
-  public String getHost() {
-    return host;
-  }
-
-  public void setHost(String host) {
-    this.host = host;
-  }
-
-  public String getProcessId() {
-    return processId;
-  }
-
-  public void setProcessId(String processId) {
-    this.processId = processId;
-  }
-
-  public String getLocatorBindAddress() {
-    return locatorBindAddress;
-  }
-
-  public void setLocatorBindAddress(String locatorBindAddress) {
-    this.locatorBindAddress = locatorBindAddress;
-  }
-
-  public int getLocatorPort() {
-    return locatorPort;
-  }
-
-  public void setLocatorPort(int locatorPort) {
-    this.locatorPort = locatorPort;
-  }
-}
diff --git 
a/geode-core/src/main/resources/META-INF/services/org.apache.geode.management.spi.ClusterManagementServiceProviderFactory
 
b/geode-core/src/main/resources/META-INF/services/org.apache.geode.management.spi.ClusterManagementServiceProviderFactory
new file mode 100644
index 0000000..ec5fe49
--- /dev/null
+++ 
b/geode-core/src/main/resources/META-INF/services/org.apache.geode.management.spi.ClusterManagementServiceProviderFactory
@@ -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.
+#
+
+org.apache.geode.management.internal.api.GeodeClusterManagementServiceProviderFactory
diff --git 
a/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt
 
b/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt
index d4105c2..7a57f84 100644
--- 
a/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt
+++ 
b/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt
@@ -524,7 +524,7 @@ 
org/apache/geode/management/internal/cli/domain/FixedPartitionAttributesInfo,tru
 
org/apache/geode/management/internal/cli/domain/IndexDetails,true,-2198907141534201288,fromClause:java/lang/String,indexName:java/lang/String,indexStatisticsDetails:org/apache/geode/management/internal/cli/domain/IndexDetails$IndexStatisticsDetails,indexType:org/apache/geode/cache/query/IndexType,indexedExpression:java/lang/String,isValid:boolean,memberId:java/lang/String,memberName:java/lang/String,projectionAttributes:java/lang/String,regionName:java/lang/String,regionPath:java/lang/String
 
org/apache/geode/management/internal/cli/domain/IndexDetails$IndexStatisticsDetails,false,numberOfKeys:java/lang/Long,numberOfUpdates:java/lang/Long,numberOfValues:java/lang/Long,totalUpdateTime:java/lang/Long,totalUses:java/lang/Long
 
org/apache/geode/management/internal/cli/domain/MemberConfigurationInfo,false,cacheAttributes:java/util/Map,cacheServerAttributes:java/util/List,gfePropsRuntime:java/util/Map,gfePropsSetFromFile:java/util/Map,gfePropsSetUsingApi:java/util/Map,gfePropsSetWithDefaults:java/util/Map,jvmInputArguments:java/util/List,pdxAttributes:java/util/Map,systemProperties:java/util/Properties
-org/apache/geode/management/internal/cli/domain/MemberInformation,true,1,cacheServerList:java/util/List,cacheXmlFilePath:java/lang/String,clientCount:int,cpuUsage:double,groups:java/lang/String,heapUsage:java/lang/String,host:java/lang/String,hostedRegions:java/util/Set,id:java/lang/String,initHeapSize:java/lang/String,isServer:boolean,locatorBindAddress:java/lang/String,locatorPort:int,locators:java/lang/String,logFilePath:java/lang/String,maxHeapSize:java/lang/String,name:java/lang/Str
 [...]
+org/apache/geode/management/internal/cli/domain/MemberInformation,true,1,cacheServerList:java/util/List,cacheXmlFilePath:java/lang/String,clientCount:int,cpuUsage:double,groups:java/lang/String,heapUsage:java/lang/String,host:java/lang/String,hostedRegions:java/util/Set,httpServiceBindAddress:java/lang/String,httpServicePort:int,id:java/lang/String,initHeapSize:java/lang/String,isServer:boolean,locatorPort:int,locators:java/lang/String,logFilePath:java/lang/String,maxHeapSize:java/lang/S
 [...]
 
org/apache/geode/management/internal/cli/domain/PartitionAttributesInfo,true,1,colocatedWith:java/lang/String,fpaInfoList:java/util/List,localMaxMemory:int,nonDefaultAttributes:java/util/Map,partitionResolverName:java/lang/String,recoveryDelay:long,redundantCopies:int,startupRecoveryDelay:long,totalNumBuckets:int
 
org/apache/geode/management/internal/cli/domain/RegionAttributesInfo,true,336184564012988487,asyncEventQueueIDs:java/util/Set,cacheListenerClassNames:java/util/List,cacheLoaderClassName:java/lang/String,cacheWriterClassName:java/lang/String,cloningEnabled:boolean,compressorClassName:java/lang/String,concurrencyChecksEnabled:boolean,concurrencyLevel:int,customExpiryIdleTimeoutClass:java/lang/String,customExpiryTTLClass:java/lang/String,dataPolicy:org/apache/geode/cache/DataPolicy,diskStor
 [...]
 
org/apache/geode/management/internal/cli/domain/RegionDescription,true,6461449275798378332,cndEvictionAttributes:java/util/Map,cndPartitionAttributes:java/util/Map,cndRegionAttributes:java/util/Map,dataPolicy:org/apache/geode/cache/DataPolicy,isAccessor:boolean,isLocal:boolean,isPartition:boolean,isPersistent:boolean,isReplicate:boolean,name:java/lang/String,regionDescPerMemberMap:java/util/Map,scope:org/apache/geode/cache/Scope
@@ -569,7 +569,7 @@ 
org/apache/geode/management/internal/cli/functions/GatewaySenderDestroyFunction,
 
org/apache/geode/management/internal/cli/functions/GatewaySenderDestroyFunctionArgs,true,3848480256348119530,id:java/lang/String,ifExists:boolean
 
org/apache/geode/management/internal/cli/functions/GatewaySenderFunctionArgs,true,4636678328980816780,alertThreshold:java/lang/Integer,batchSize:java/lang/Integer,batchTimeInterval:java/lang/Integer,diskStoreName:java/lang/String,diskSynchronous:java/lang/Boolean,dispatcherThreads:java/lang/Integer,enableBatchConflation:java/lang/Boolean,enablePersistence:java/lang/Boolean,gatewayEventFilters:java/util/List,gatewayTransportFilters:java/util/List,id:java/lang/String,manualStart:java/lang/
 [...]
 
org/apache/geode/management/internal/cli/functions/GetMemberConfigInformationFunction,true,1
-org/apache/geode/management/internal/cli/functions/GetMemberInformationFunction,true,1
+org/apache/geode/management/internal/cli/functions/GetMemberInformationFunction,true,1404642539058875565
 
org/apache/geode/management/internal/cli/functions/GetRegionDescriptionFunction,true,1
 org/apache/geode/management/internal/cli/functions/GetRegionsFunction,true,1
 
org/apache/geode/management/internal/cli/functions/GetStackTracesFunction,true,1
@@ -615,7 +615,6 @@ 
org/apache/geode/management/internal/cli/util/ExportLogsCacheWriter,false,curren
 
org/apache/geode/management/internal/cli/util/FixedPartitionAttributesInfo,false,isPrimary:boolean,numBuckets:int,partitionName:java/lang/String
 
org/apache/geode/management/internal/cli/util/JConsoleNotFoundException,true,-1485615321440327206
 org/apache/geode/management/internal/cli/util/LogFilter$LineFilterResult,false
-org/apache/geode/management/internal/cli/util/MemberInformation,true,1,cacheXmlFilePath:java/lang/String,cpuUsage:java/lang/String,groups:java/lang/String,heapUsage:java/lang/String,host:java/lang/String,id:java/lang/String,initHeapSize:java/lang/String,locatorBindAddress:java/lang/String,locatorPort:int,locators:java/lang/String,logFilePath:java/lang/String,maxHeapSize:java/lang/String,name:java/lang/String,processId:java/lang/String,serverBindAddress:java/lang/String,statArchiveFilePat
 [...]
 
org/apache/geode/management/internal/cli/util/VisualVmNotFoundException,true,-8491645604829510102
 
org/apache/geode/management/internal/configuration/domain/SharedConfigurationStatus,false
 
org/apache/geode/management/internal/configuration/functions/DownloadJarFunction,true,1
diff --git 
a/geode-core/src/test/java/org/apache/geode/management/internal/api/ClusterManagementResultTest.java
 
b/geode-core/src/test/java/org/apache/geode/management/internal/api/ClusterManagementResultTest.java
index d58c919..3473d1e 100644
--- 
a/geode-core/src/test/java/org/apache/geode/management/internal/api/ClusterManagementResultTest.java
+++ 
b/geode-core/src/test/java/org/apache/geode/management/internal/api/ClusterManagementResultTest.java
@@ -22,6 +22,8 @@ import static org.assertj.core.api.Assertions.assertThat;
 import org.junit.Before;
 import org.junit.Test;
 
+import org.apache.geode.management.api.ClusterManagementResult;
+
 public class ClusterManagementResultTest {
   private ClusterManagementResult result;
 
diff --git 
a/geode-core/src/test/java/org/apache/geode/management/internal/api/LocatorClusterManagementServiceTest.java
 
b/geode-core/src/test/java/org/apache/geode/management/internal/api/LocatorClusterManagementServiceTest.java
index f6aa96d..e3dbd39 100644
--- 
a/geode-core/src/test/java/org/apache/geode/management/internal/api/LocatorClusterManagementServiceTest.java
+++ 
b/geode-core/src/test/java/org/apache/geode/management/internal/api/LocatorClusterManagementServiceTest.java
@@ -35,6 +35,7 @@ import org.apache.geode.cache.configuration.RegionConfig;
 import org.apache.geode.distributed.ConfigurationPersistenceService;
 import org.apache.geode.distributed.DistributedMember;
 import org.apache.geode.distributed.internal.DistributionManager;
+import org.apache.geode.management.api.ClusterManagementResult;
 import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
 import org.apache.geode.management.internal.exceptions.EntityExistsException;
 
diff --git 
a/geode-dunit/src/main/java/org/apache/geode/test/dunit/rules/ClusterStartupRule.java
 
b/geode-dunit/src/main/java/org/apache/geode/test/dunit/rules/ClusterStartupRule.java
index cd87286..c842715 100644
--- 
a/geode-dunit/src/main/java/org/apache/geode/test/dunit/rules/ClusterStartupRule.java
+++ 
b/geode-dunit/src/main/java/org/apache/geode/test/dunit/rules/ClusterStartupRule.java
@@ -74,6 +74,8 @@ public class ClusterStartupRule implements 
SerializableTestRule {
   public static MemberStarterRule<?> memberStarter;
   public static ClientCacheRule clientCacheRule;
 
+  private boolean skipLocalDistributedSystemCleanup;
+
   public static InternalCache getCache() {
     if (memberStarter == null) {
       return null;
@@ -164,7 +166,9 @@ public class ClusterStartupRule implements 
SerializableTestRule {
 
   private void after(Description description) throws Throwable {
 
-    MemberStarterRule.disconnectDSIfAny();
+    if (!skipLocalDistributedSystemCleanup) {
+      MemberStarterRule.disconnectDSIfAny();
+    }
 
     // stop all the members in the order of clients, servers and locators
     List<VMProvider> vms = new ArrayList<>();
@@ -188,6 +192,19 @@ public class ClusterStartupRule implements 
SerializableTestRule {
     DUnitLauncher.closeAndCheckForSuspects();
   }
 
+  public boolean isSkipLocalDistributedSystemCleanup() {
+    return skipLocalDistributedSystemCleanup;
+  }
+
+  /**
+   * In some weird situations you may not want to do local DS cleanup as that 
lifecyle is deferred
+   * elsewhere - see {@code LocatorCleanupEventListener} and any test that 
uses {@code
+   * PlainLocatorContextLoader} or {@code 
LocatorWithSecurityManagerContextLoader}
+   */
+  public void setSkipLocalDistributedSystemCleanup(boolean 
skipLocalDistributedSystemCleanup) {
+    this.skipLocalDistributedSystemCleanup = skipLocalDistributedSystemCleanup;
+  }
+
   public MemberVM startLocatorVM(int index, int... locatorPort) {
     return startLocatorVM(index, x -> x.withConnectionToLocator(locatorPort));
   }
@@ -326,8 +343,8 @@ public class ClusterStartupRule implements 
SerializableTestRule {
   /**
    * gracefully stop the member/client inside this vm
    *
-   * if this vm is a server/locator, it stops them and cleans the working dir
-   * if this vm is a client, it closes the client cache.
+   * if this vm is a server/locator, it stops them and cleans the working dir 
if this vm is a
+   * client, it closes the client cache.
    *
    * @param index vm index
    */
diff --git a/geode-management/build.gradle b/geode-management/build.gradle
index d89f506..1c915dc 100755
--- a/geode-management/build.gradle
+++ b/geode-management/build.gradle
@@ -24,6 +24,7 @@ dependencies {
   compile('com.fasterxml.jackson.core:jackson-databind')
   compile('com.fasterxml.jackson.core:jackson-core')
   compile('com.fasterxml.jackson.core:jackson-annotations')
+  compile('org.springframework:spring-web')
 
   compileOnly(project(':geode-common')) {
     exclude module: 'junit'
diff --git 
a/geode-management/src/main/java/org/apache/geode/cache/configuration/RegionConfig.java
 
b/geode-management/src/main/java/org/apache/geode/cache/configuration/RegionConfig.java
index 7522af8..27f2e73 100644
--- 
a/geode-management/src/main/java/org/apache/geode/cache/configuration/RegionConfig.java
+++ 
b/geode-management/src/main/java/org/apache/geode/cache/configuration/RegionConfig.java
@@ -30,6 +30,7 @@ import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlType;
 
 import org.apache.geode.annotations.Experimental;
+import org.apache.geode.management.api.RestfulEndpoint;
 
 
 /**
@@ -149,7 +150,7 @@ import org.apache.geode.annotations.Experimental;
 @XmlType(name = "region-type", namespace = 
"http://geode.apache.org/schema/cache";,
     propOrder = {"regionAttributes", "indexes", "entries", "regionElements", 
"regions"})
 @Experimental
-public class RegionConfig implements CacheElement {
+public class RegionConfig implements CacheElement, RestfulEndpoint {
   @XmlElement(name = "region-attributes", namespace = 
"http://geode.apache.org/schema/cache";)
   protected RegionAttributesType regionAttributes;
   @XmlElement(name = "index", namespace = 
"http://geode.apache.org/schema/cache";)
@@ -172,6 +173,11 @@ public class RegionConfig implements CacheElement {
     this.type = refid;
   }
 
+  @Override
+  public String getEndpoint() {
+    return "/v2/regions";
+  }
+
   public RegionAttributesType getRegionAttributes() {
     return regionAttributes;
   }
diff --git 
a/geode-management/src/main/java/org/apache/geode/management/internal/api/ClusterManagementResult.java
 
b/geode-management/src/main/java/org/apache/geode/management/api/ClusterManagementResult.java
similarity index 97%
rename from 
geode-management/src/main/java/org/apache/geode/management/internal/api/ClusterManagementResult.java
rename to 
geode-management/src/main/java/org/apache/geode/management/api/ClusterManagementResult.java
index a4b03fb..67bdd2c 100644
--- 
a/geode-management/src/main/java/org/apache/geode/management/internal/api/ClusterManagementResult.java
+++ 
b/geode-management/src/main/java/org/apache/geode/management/api/ClusterManagementResult.java
@@ -12,7 +12,7 @@
  * or implied. See the License for the specific language governing permissions 
and limitations under
  * the License.
  */
-package org.apache.geode.management.internal.api;
+package org.apache.geode.management.api;
 
 import java.util.HashMap;
 import java.util.Map;
diff --git 
a/geode-management/src/main/java/org/apache/geode/management/internal/api/ClusterManagementService.java
 
b/geode-management/src/main/java/org/apache/geode/management/api/ClusterManagementService.java
similarity index 51%
rename from 
geode-management/src/main/java/org/apache/geode/management/internal/api/ClusterManagementService.java
rename to 
geode-management/src/main/java/org/apache/geode/management/api/ClusterManagementService.java
index 1a88592..c87b641 100644
--- 
a/geode-management/src/main/java/org/apache/geode/management/internal/api/ClusterManagementService.java
+++ 
b/geode-management/src/main/java/org/apache/geode/management/api/ClusterManagementService.java
@@ -13,28 +13,52 @@
  * the License.
  */
 
-package org.apache.geode.management.internal.api;
+package org.apache.geode.management.api;
 
 import org.apache.geode.annotations.Experimental;
 import org.apache.geode.cache.configuration.CacheElement;
 
 /**
- * this is responsible for applying and persisting cache configuration changes 
on locators
- * and/or servers.
+ * this is responsible for applying and persisting cache configuration changes 
on locators and/or
+ * servers.
  */
 @Experimental
 public interface ClusterManagementService {
+
   /**
-   * This method will try to create the element on all the applicable members 
in the cluster and
-   * persist the configuration in the cluster configuration if persistence is 
enabled.
+   * This method will create the element on all the applicable members in the 
cluster and persist
+   * the configuration in the cluster configuration if persistence is enabled.
    *
-   * @param config this holds the configuration attributes of the element you 
are trying to create
-   *        on the cluster
+   * @param config this holds the configuration attributes of the element to 
be created on the
+   *        cluster
+   * @param group the server group to which this config applies
    * @throws IllegalArgumentException, NoMemberException, EntityExistsException
+   * @see CacheElement
    */
   ClusterManagementResult create(CacheElement config, String group);
 
+  /**
+   * This method will delete the element on all the applicable members in the 
cluster and update the
+   * configuration in the cluster configuration if persistence is enabled.
+   *
+   * @param config this holds the configuration attributes of the element to 
be deleted on the
+   *        cluster
+   * @param group the server group to which this config applies
+   * @throws IllegalArgumentException, NoMemberException, EntityExistsException
+   * @see CacheElement
+   */
   ClusterManagementResult delete(CacheElement config, String group);
 
+  /**
+   * This method will update the element on all the applicable members in the 
cluster and persist
+   * the updated configuration in the cluster configuration if persistence is 
enabled.
+   *
+   * @param config this holds the configuration attributes of the element to 
be updated on the
+   *        cluster
+   * @param group the server group to which this config applies
+   * @throws IllegalArgumentException, NoMemberException, EntityExistsException
+   * @see CacheElement
+   */
   ClusterManagementResult update(CacheElement config, String group);
+
 }
diff --git 
a/geode-management/src/main/java/org/apache/geode/management/internal/api/Status.java
 
b/geode-management/src/main/java/org/apache/geode/management/api/RestfulEndpoint.java
similarity index 59%
copy from 
geode-management/src/main/java/org/apache/geode/management/internal/api/Status.java
copy to 
geode-management/src/main/java/org/apache/geode/management/api/RestfulEndpoint.java
index 9a8a5cb..81736df 100644
--- 
a/geode-management/src/main/java/org/apache/geode/management/internal/api/Status.java
+++ 
b/geode-management/src/main/java/org/apache/geode/management/api/RestfulEndpoint.java
@@ -12,33 +12,10 @@
  * or implied. See the License for the specific language governing permissions 
and limitations under
  * the License.
  */
-package org.apache.geode.management.internal.api;
 
-public class Status {
-  boolean success;
-  String message;
+package org.apache.geode.management.api;
 
-  // needed for json deserialization
-  public Status() {}
+public interface RestfulEndpoint {
 
-  public Status(boolean success, String message) {
-    this.success = success;
-    this.message = message;
-  }
-
-  public boolean isSuccess() {
-    return success;
-  }
-
-  public void setSuccess(boolean success) {
-    this.success = success;
-  }
-
-  public String getMessage() {
-    return message;
-  }
-
-  public void setMessage(String message) {
-    this.message = message;
-  }
+  String getEndpoint();
 }
diff --git 
a/geode-management/src/main/java/org/apache/geode/management/internal/api/Status.java
 b/geode-management/src/main/java/org/apache/geode/management/api/Status.java
similarity index 96%
rename from 
geode-management/src/main/java/org/apache/geode/management/internal/api/Status.java
rename to 
geode-management/src/main/java/org/apache/geode/management/api/Status.java
index 9a8a5cb..e50c85a 100644
--- 
a/geode-management/src/main/java/org/apache/geode/management/internal/api/Status.java
+++ b/geode-management/src/main/java/org/apache/geode/management/api/Status.java
@@ -12,7 +12,7 @@
  * or implied. See the License for the specific language governing permissions 
and limitations under
  * the License.
  */
-package org.apache.geode.management.internal.api;
+package org.apache.geode.management.api;
 
 public class Status {
   boolean success;
diff --git 
a/geode-management/src/main/java/org/apache/geode/management/client/ClusterManagementServiceProvider.java
 
b/geode-management/src/main/java/org/apache/geode/management/client/ClusterManagementServiceProvider.java
new file mode 100644
index 0000000..c378d46
--- /dev/null
+++ 
b/geode-management/src/main/java/org/apache/geode/management/client/ClusterManagementServiceProvider.java
@@ -0,0 +1,119 @@
+/*
+ * 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.client;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ServiceLoader;
+
+import org.springframework.http.client.ClientHttpRequestFactory;
+
+import org.apache.geode.annotations.Experimental;
+import org.apache.geode.management.api.ClusterManagementService;
+import org.apache.geode.management.spi.ClusterManagementServiceProviderFactory;
+
+/**
+ * Top-level entry point for client interaction with the {@link 
ClusterManagementService}. A user
+ * can create an instance of the {@code ClusterManagementService} (CMS for 
short) in several ways,
+ * each providing various level of control or expediency.
+ * <p/>
+ * Calling {@code getFactory(context)} will return an explicit instance of 
{@link
+ * ClusterManagementServiceProviderFactory}. Methods on this factory can then 
be called to create or
+ * retrieve instances of a CMS. New {@link ClusterManagementServiceProvider}s 
can be written if
+ * specific customization or parameterization is required.
+ * <p/>
+ * A note about contexts. A context is simply a unique string which identifies 
a specific instance
+ * of CMS that will be returned. Contexts map to the different uses of a CMS. 
Currently, the
+ * following contexts are provided:
+ * <ul>
+ * <li>
+ * {@code JAVA_CLIENT_CONTEXT} ("java-client") - would be used to retrieve a 
CMS instance on a pure
+ * Java client - i.e. an app that is not running in the context of a Geode 
client or server. This
+ * context is available when using the <i>geode-management</i> module.
+ * </li>
+ * <li>{@code GEODE_CONTEXT} ("geode") - would be used to retrieve a CMS 
instance
+ * from a JVM where either a {@code Cache} or {@code ClientCache} exists. This 
context is available
+ * when using the <i>geode-core</i> module.
+ * </li>
+ * </ul>
+ * If the URL of the Cluster Management Service is known, the {@code 
getService(url)} method can be
+ * called. This implicitly uses the {@code JAVA_CLIENT_CONTEXT}. For further 
control the CMS can be
+ * configured with a {@link ClientHttpRequestFactory} by calling {@code
+ * getService(requestFactory)}.
+ * <p/>
+ * Finally, the simplest way to create a CMS instance is simply to call {@code 
getService()}. This
+ * method will attempt to infer the context and use an appropriate service 
provider to create a CMS
+ * instance.
+ */
+@Experimental
+public class ClusterManagementServiceProvider {
+
+  public static final String JAVA_CLIENT_CONTEXT = "java-client";
+  public static final String GEODE_CONTEXT = "geode";
+
+  private static List<ClusterManagementServiceProviderFactory> 
providerFactories = null;
+
+  public static ClusterManagementService getService() {
+    ClusterManagementServiceProviderFactory factory;
+    try {
+      factory = getFactory(GEODE_CONTEXT);
+      try {
+        ClusterManagementService cms = factory.create();
+        return cms;
+      } catch (IllegalStateException ex) {
+        // Ignored
+      }
+    } catch (IllegalArgumentException iex) {
+      // Ig
+    } catch (Exception iex) {
+      iex.printStackTrace();
+    }
+
+    throw new IllegalStateException(
+        "Unable to get ClusterManagementService using any of the default 
contexts");
+  }
+
+  public static ClusterManagementService getService(String clusterUrl) {
+    return getFactory(JAVA_CLIENT_CONTEXT).create(clusterUrl);
+  }
+
+  public static ClusterManagementService getService(ClientHttpRequestFactory 
requestFactory) {
+    return getFactory(JAVA_CLIENT_CONTEXT).create(requestFactory);
+  }
+
+  public static synchronized ClusterManagementServiceProviderFactory 
getFactory(String context) {
+    if (providerFactories == null) {
+      loadClusterManagementServiceProviderFactories();
+    }
+
+    ClusterManagementServiceProviderFactory factory = 
providerFactories.stream()
+        .filter(x -> x.getContext().equalsIgnoreCase(context))
+        .findFirst()
+        .orElseThrow(
+            () -> new IllegalArgumentException("Did not find provider for 
context: " + context));
+
+    return factory;
+  }
+
+  private static void loadClusterManagementServiceProviderFactories() {
+    providerFactories = new ArrayList<>();
+
+    for (ClusterManagementServiceProviderFactory factory : ServiceLoader
+        .load(ClusterManagementServiceProviderFactory.class)) {
+      providerFactories.add(factory);
+    }
+  }
+}
diff --git 
a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/StandardRequestPostProcessor.java
 
b/geode-management/src/main/java/org/apache/geode/management/client/RestTemplateResponseErrorHandler.java
similarity index 56%
copy from 
geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/StandardRequestPostProcessor.java
copy to 
geode-management/src/main/java/org/apache/geode/management/client/RestTemplateResponseErrorHandler.java
index 92a3d5f..6ae39c0 100644
--- 
a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/StandardRequestPostProcessor.java
+++ 
b/geode-management/src/main/java/org/apache/geode/management/client/RestTemplateResponseErrorHandler.java
@@ -13,18 +13,23 @@
  * the License.
  */
 
-package org.apache.geode.management.internal.rest;
+package org.apache.geode.management.client;
 
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.MediaType;
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.test.web.servlet.request.RequestPostProcessor;
+import java.io.IOException;
+
+import org.springframework.http.client.ClientHttpResponse;
+import org.springframework.web.client.ResponseErrorHandler;
+
+public class RestTemplateResponseErrorHandler implements ResponseErrorHandler {
+  @Override
+  public boolean hasError(ClientHttpResponse response) throws IOException {
+    // All errors should be handled by the server and be returned as part of 
the
+    // ResponseEntity<ClusterManagementResult>.
+    return false;
+  }
 
-class StandardRequestPostProcessor implements RequestPostProcessor {
   @Override
-  public MockHttpServletRequest postProcessRequest(MockHttpServletRequest 
request) {
-    request.addHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON);
-    request.addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
-    return request;
+  public void handleError(ClientHttpResponse response) throws IOException {
+    // this should not be necessary
   }
 }
diff --git 
a/geode-management/src/main/java/org/apache/geode/management/internal/ClusterManagementClient.java
 
b/geode-management/src/main/java/org/apache/geode/management/internal/ClusterManagementClient.java
new file mode 100644
index 0000000..5eeb647
--- /dev/null
+++ 
b/geode-management/src/main/java/org/apache/geode/management/internal/ClusterManagementClient.java
@@ -0,0 +1,105 @@
+/*
+ * 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;
+
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.client.ClientHttpRequestFactory;
+import org.springframework.web.client.ResponseErrorHandler;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.DefaultUriTemplateHandler;
+import sun.reflect.generics.reflectiveObjects.NotImplementedException;
+
+import org.apache.geode.annotations.Experimental;
+import org.apache.geode.cache.configuration.CacheElement;
+import org.apache.geode.management.api.ClusterManagementResult;
+import org.apache.geode.management.api.ClusterManagementService;
+import org.apache.geode.management.api.RestfulEndpoint;
+import org.apache.geode.management.client.RestTemplateResponseErrorHandler;
+
+/**
+ * Implementation of {@link ClusterManagementService} interface which 
represents the cluster
+ * management service as used by a Java client.
+ * <p/>
+ * In order to manipulate Geode components (Regions, etc.) clients can 
construct instances of {@link
+ * CacheElement}s and call the corresponding {@link 
ClusterManagementClient#create(CacheElement,
+ * String)}, {@link ClusterManagementClient#delete(CacheElement, String)} or 
{@link
+ * ClusterManagementClient#update(CacheElement, String)} method. The returned 
{@link
+ * ClusterManagementResult} will contain all necessary information about the 
outcome of the call.
+ * This will include the result of persisting the config as part of the 
cluster configuration as
+ * well as creating the actual component in the cluster.
+ * <p/>
+ * All create calls are idempotent and will not return an error if the desired 
component already
+ * exists.
+ */
+@Experimental
+public class ClusterManagementClient implements ClusterManagementService {
+
+  private static final ResponseErrorHandler DEFAULT_ERROR_HANDLER =
+      new RestTemplateResponseErrorHandler();
+
+  private final RestTemplate restTemplate;
+
+  private ClusterManagementClient() {
+    restTemplate = new RestTemplate();
+    restTemplate.setErrorHandler(DEFAULT_ERROR_HANDLER);
+  }
+
+  public ClusterManagementClient(ClientHttpRequestFactory requestFactory) {
+    this();
+    this.restTemplate.setRequestFactory(requestFactory);
+  }
+
+  public ClusterManagementClient(String clusterUrl) {
+    this();
+    DefaultUriTemplateHandler templateHandler = new 
DefaultUriTemplateHandler();
+    templateHandler.setBaseUrl(clusterUrl);
+    restTemplate.setUriTemplateHandler(templateHandler);
+  }
+
+  @Override
+  public ClusterManagementResult create(CacheElement config, String group) {
+    String endPoint = getEndpoint(config);
+
+    ResponseEntity<ClusterManagementResult> result = 
restTemplate.postForEntity(endPoint, config,
+        ClusterManagementResult.class);
+
+    return result.getBody();
+  }
+
+  @Override
+  public ClusterManagementResult delete(CacheElement config, String group) {
+    throw new NotImplementedException();
+  }
+
+  @Override
+  public ClusterManagementResult update(CacheElement config, String group) {
+    throw new NotImplementedException();
+  }
+
+  public RestTemplate getRestTemplate() {
+    return restTemplate;
+  }
+
+  private String getEndpoint(CacheElement config) {
+    if (!(config instanceof RestfulEndpoint)) {
+      throw new IllegalArgumentException(
+          String.format("The config type %s does not have a RESTful endpoint 
defined",
+              config.getClass().getName()));
+    }
+
+    return ((RestfulEndpoint) config).getEndpoint();
+  }
+}
diff --git 
a/geode-management/src/main/java/org/apache/geode/management/spi/ClusterManagementServiceProviderFactory.java
 
b/geode-management/src/main/java/org/apache/geode/management/spi/ClusterManagementServiceProviderFactory.java
new file mode 100644
index 0000000..44136f2
--- /dev/null
+++ 
b/geode-management/src/main/java/org/apache/geode/management/spi/ClusterManagementServiceProviderFactory.java
@@ -0,0 +1,60 @@
+/*
+ * 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.spi;
+
+import org.springframework.http.client.ClientHttpRequestFactory;
+
+import org.apache.geode.management.api.ClusterManagementService;
+
+/**
+ * A Server Provider interface which should be implemented to create instances 
of {@link
+ * ClusterManagementService} for a given context.
+ */
+public interface ClusterManagementServiceProviderFactory {
+
+  /**
+   * Returns a list of the contexts which this provider supports.
+   *
+   * @return a list of names of supported contexts of this factory
+   */
+  String getContext();
+
+  /**
+   * Create a {@code ClusterManagementService} instance. Throws an {@code 
IllegalStateException}
+   * if the instance cannot be created. This method would typically be used by 
an implementation
+   * that is able to infer the correct Cluster Management endpoint URL to use.
+   *
+   * @return an instance of the {@code ClusterManagementService}
+   */
+  ClusterManagementService create() throws IllegalStateException;
+
+  /**
+   * Create a {@code ClusterManagementService} that will use the given URL.
+   *
+   * @param clusterUrl the URL to conect to
+   * @return an instance of {@code ClusterManagementService}
+   */
+  ClusterManagementService create(String clusterUrl);
+
+  /**
+   * Create a {@code ClusterManagementService} that will use the given {@link
+   * ClientHttpRequestFactory} to establish connections with the Cluster 
Management endpoint.
+   *
+   * @param requestFactory the {@code ClientHttpRequestFactory} to use for new 
connections.
+   * @return an instance of {@code ClusterManagementService}
+   */
+  ClusterManagementService create(ClientHttpRequestFactory requestFactory);
+}
diff --git 
a/geode-management/src/main/java/org/apache/geode/management/spi/JavaClientClusterManagementProviderFactory.java
 
b/geode-management/src/main/java/org/apache/geode/management/spi/JavaClientClusterManagementProviderFactory.java
new file mode 100644
index 0000000..666ce51
--- /dev/null
+++ 
b/geode-management/src/main/java/org/apache/geode/management/spi/JavaClientClusterManagementProviderFactory.java
@@ -0,0 +1,54 @@
+/*
+ * 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.spi;
+
+import org.springframework.http.client.ClientHttpRequestFactory;
+
+import org.apache.geode.management.api.ClusterManagementService;
+import org.apache.geode.management.client.ClusterManagementServiceProvider;
+import org.apache.geode.management.internal.ClusterManagementClient;
+
+/**
+ * A Service Provider factory which will be used to create {@link 
ClusterManagementService}
+ * instances from pure Java code - i.e. the Cluster Management endpoint URL 
<b>cannot</b> be
+ * inferred from the implied runtime context but needs to be specifically 
configured using a given
+ * URL or {@code ClientHttpRequestFactory}.
+ */
+public class JavaClientClusterManagementProviderFactory
+    implements ClusterManagementServiceProviderFactory {
+
+  @Override
+  public String getContext() {
+    return ClusterManagementServiceProvider.JAVA_CLIENT_CONTEXT;
+  }
+
+  @Override
+  public ClusterManagementService create() throws IllegalArgumentException {
+    throw new IllegalArgumentException(String.format(
+        "When using a %s context, you must call create(String) or 
create(ClientHttpRequestFactory)",
+        ClusterManagementServiceProvider.JAVA_CLIENT_CONTEXT));
+  }
+
+  @Override
+  public ClusterManagementService create(String clusterUrl) {
+    return new ClusterManagementClient(clusterUrl);
+  }
+
+  @Override
+  public ClusterManagementService create(ClientHttpRequestFactory 
requestFactory) {
+    return new ClusterManagementClient(requestFactory);
+  }
+}
diff --git 
a/geode-management/src/main/resources/META-INF/services/org.apache.geode.management.spi.ClusterManagementServiceProviderFactory
 
b/geode-management/src/main/resources/META-INF/services/org.apache.geode.management.spi.ClusterManagementServiceProviderFactory
new file mode 100644
index 0000000..5863340
--- /dev/null
+++ 
b/geode-management/src/main/resources/META-INF/services/org.apache.geode.management.spi.ClusterManagementServiceProviderFactory
@@ -0,0 +1,17 @@
+#
+# 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.
+#
+
+
+org.apache.geode.management.spi.JavaClientClusterManagementProviderFactory
diff --git a/geode-management/src/test/resources/expected-pom.xml 
b/geode-management/src/test/resources/expected-pom.xml
index 14ab573..66e0853 100644
--- a/geode-management/src/test/resources/expected-pom.xml
+++ b/geode-management/src/test/resources/expected-pom.xml
@@ -55,6 +55,11 @@
       <artifactId>jackson-annotations</artifactId>
       <scope>compile</scope>
     </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-web</artifactId>
+      <scope>compile</scope>
+    </dependency>
   </dependencies>
   <dependencyManagement>
     <dependencies>
diff --git a/geode-web-management/build.gradle 
b/geode-web-management/build.gradle
index f3868c8..46ab5f6 100644
--- a/geode-web-management/build.gradle
+++ b/geode-web-management/build.gradle
@@ -124,6 +124,10 @@ dependencies {
   distributedTestCompile(project(':geode-dunit')) {
     exclude module: 'geode-core'
   }
+    
+  distributedTestRuntimeOnly('org.apache.logging.log4j:log4j-slf4j-impl') {
+    exclude module: 'slf4j-api'
+  }
 }
 
 war {
diff --git 
a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/PlainLocatorContextLoader.java
 
b/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/BaseLocatorContextLoader.java
similarity index 76%
copy from 
geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/PlainLocatorContextLoader.java
copy to 
geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/BaseLocatorContextLoader.java
index e2a28b7..fc27eec 100644
--- 
a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/PlainLocatorContextLoader.java
+++ 
b/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/BaseLocatorContextLoader.java
@@ -17,6 +17,7 @@ package org.apache.geode.management.internal.rest;
 
 import org.springframework.test.context.web.GenericXmlWebContextLoader;
 import org.springframework.test.context.web.WebMergedContextConfiguration;
+import org.springframework.web.context.WebApplicationContext;
 import org.springframework.web.context.support.GenericWebApplicationContext;
 
 import org.apache.geode.internal.cache.HttpService;
@@ -28,24 +29,26 @@ import org.apache.geode.test.junit.rules.LocatorStarterRule;
  * ServletContext so that it can be retrieved and cleaned up in the 
LocatorCleanupEventListener.
  * There has to be a better way...
  */
-class PlainLocatorContextLoader extends GenericXmlWebContextLoader {
+public abstract class BaseLocatorContextLoader extends 
GenericXmlWebContextLoader {
 
-  private LocatorStarterRule locator = new LocatorStarterRule()
-      .withAutoStart();
+  public abstract LocatorStarterRule getLocator();
 
   @Override
   protected void loadBeanDefinitions(GenericWebApplicationContext context,
       WebMergedContextConfiguration webMergedConfig) {
 
-    locator.before();
+    getLocator().before();
 
     super.loadBeanDefinitions(context, webMergedConfig);
     
context.getServletContext().setAttribute(HttpService.SECURITY_SERVICE_SERVLET_CONTEXT_PARAM,
-        locator.getCache().getSecurityService());
+        getLocator().getCache().getSecurityService());
     
context.getServletContext().setAttribute(HttpService.CLUSTER_MANAGEMENT_SERVICE_CONTEXT_PARAM,
-        locator.getLocator().getClusterManagementService());
+        getLocator().getLocator().getClusterManagementService());
 
-    context.getServletContext().setAttribute("locator", locator);
+    context.getServletContext().setAttribute("locator", getLocator());
   }
 
+  public static LocatorStarterRule getLocatorFromContext(WebApplicationContext 
context) {
+    return (LocatorStarterRule) 
context.getServletContext().getAttribute("locator");
+  }
 }
diff --git 
a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/LocatorWithSecurityManagerContextLoader.java
 
b/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/LocatorWithSecurityManagerContextLoader.java
index 4f03a2a..696e16a 100644
--- 
a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/LocatorWithSecurityManagerContextLoader.java
+++ 
b/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/LocatorWithSecurityManagerContextLoader.java
@@ -15,33 +15,22 @@
 
 package org.apache.geode.management.internal.rest;
 
-import org.springframework.test.context.web.GenericXmlWebContextLoader;
-import org.springframework.test.context.web.WebMergedContextConfiguration;
-import org.springframework.web.context.support.GenericWebApplicationContext;
-
-import org.apache.geode.internal.cache.HttpService;
 import org.apache.geode.security.SimpleTestSecurityManager;
 import org.apache.geode.test.junit.rules.LocatorStarterRule;
 
-class LocatorWithSecurityManagerContextLoader extends 
GenericXmlWebContextLoader {
-
-  private LocatorStarterRule locator = new LocatorStarterRule()
-      .withSecurityManager(SimpleTestSecurityManager.class)
-      .withAutoStart();
-
-  @Override
-  protected void loadBeanDefinitions(GenericWebApplicationContext context,
-      WebMergedContextConfiguration webMergedConfig) {
+public class LocatorWithSecurityManagerContextLoader extends 
BaseLocatorContextLoader {
 
-    locator.before();
+  private final LocatorStarterRule locator;
 
-    super.loadBeanDefinitions(context, webMergedConfig);
-    
context.getServletContext().setAttribute(HttpService.SECURITY_SERVICE_SERVLET_CONTEXT_PARAM,
-        locator.getCache().getSecurityService());
-    
context.getServletContext().setAttribute(HttpService.CLUSTER_MANAGEMENT_SERVICE_CONTEXT_PARAM,
-        locator.getLocator().getClusterManagementService());
+  public LocatorWithSecurityManagerContextLoader() {
+    locator = new LocatorStarterRule()
+        .withSecurityManager(SimpleTestSecurityManager.class)
+        .withAutoStart();
+  }
 
-    context.getServletContext().setAttribute("locator", locator);
+  @Override
+  public LocatorStarterRule getLocator() {
+    return locator;
   }
 
 }
diff --git 
a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/PlainLocatorContextLoader.java
 
b/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/PlainLocatorContextLoader.java
index e2a28b7..adedec8 100644
--- 
a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/PlainLocatorContextLoader.java
+++ 
b/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/PlainLocatorContextLoader.java
@@ -15,37 +15,19 @@
 
 package org.apache.geode.management.internal.rest;
 
-import org.springframework.test.context.web.GenericXmlWebContextLoader;
-import org.springframework.test.context.web.WebMergedContextConfiguration;
-import org.springframework.web.context.support.GenericWebApplicationContext;
-
-import org.apache.geode.internal.cache.HttpService;
 import org.apache.geode.test.junit.rules.LocatorStarterRule;
 
-/**
- * This is quite horrible. In particular we're trying to link the lifecycle of 
the
- * LocatorStarterRule and Spring's application context. The locator is 
injected into the
- * ServletContext so that it can be retrieved and cleaned up in the 
LocatorCleanupEventListener.
- * There has to be a better way...
- */
-class PlainLocatorContextLoader extends GenericXmlWebContextLoader {
-
-  private LocatorStarterRule locator = new LocatorStarterRule()
-      .withAutoStart();
-
-  @Override
-  protected void loadBeanDefinitions(GenericWebApplicationContext context,
-      WebMergedContextConfiguration webMergedConfig) {
-
-    locator.before();
+public class PlainLocatorContextLoader extends BaseLocatorContextLoader {
 
-    super.loadBeanDefinitions(context, webMergedConfig);
-    
context.getServletContext().setAttribute(HttpService.SECURITY_SERVICE_SERVLET_CONTEXT_PARAM,
-        locator.getCache().getSecurityService());
-    
context.getServletContext().setAttribute(HttpService.CLUSTER_MANAGEMENT_SERVICE_CONTEXT_PARAM,
-        locator.getLocator().getClusterManagementService());
+  private final LocatorStarterRule locator;
 
-    context.getServletContext().setAttribute("locator", locator);
+  public PlainLocatorContextLoader() {
+    locator = new LocatorStarterRule()
+        .withAutoStart();
   }
 
+  @Override
+  public LocatorStarterRule getLocator() {
+    return locator;
+  }
 }
diff --git 
a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/StandardRequestPostProcessor.java
 
b/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/StandardRequestPostProcessor.java
index 92a3d5f..b1282f0 100644
--- 
a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/StandardRequestPostProcessor.java
+++ 
b/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/StandardRequestPostProcessor.java
@@ -20,7 +20,7 @@ import org.springframework.http.MediaType;
 import org.springframework.mock.web.MockHttpServletRequest;
 import org.springframework.test.web.servlet.request.RequestPostProcessor;
 
-class StandardRequestPostProcessor implements RequestPostProcessor {
+public class StandardRequestPostProcessor implements RequestPostProcessor {
   @Override
   public MockHttpServletRequest postProcessRequest(MockHttpServletRequest 
request) {
     request.addHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON);
diff --git 
a/geode-web-management/src/distributedTest/java/org/apache/geode/management/client/ClusterManagementClientDUnitTest.java
 
b/geode-web-management/src/distributedTest/java/org/apache/geode/management/client/ClusterManagementClientDUnitTest.java
new file mode 100644
index 0000000..06a6f4f
--- /dev/null
+++ 
b/geode-web-management/src/distributedTest/java/org/apache/geode/management/client/ClusterManagementClientDUnitTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.client;
+
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.test.context.support.WithMockUser;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.test.web.client.MockMvcClientHttpRequestFactory;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.client.ResponseErrorHandler;
+import org.springframework.web.context.WebApplicationContext;
+
+import org.apache.geode.cache.configuration.RegionConfig;
+import org.apache.geode.management.api.ClusterManagementResult;
+import org.apache.geode.management.api.ClusterManagementService;
+import org.apache.geode.management.internal.rest.BaseLocatorContextLoader;
+import org.apache.geode.management.internal.rest.PlainLocatorContextLoader;
+import org.apache.geode.test.dunit.rules.ClusterStartupRule;
+import org.apache.geode.test.dunit.rules.MemberVM;
+
+@RunWith(SpringRunner.class)
+@ContextConfiguration(locations = 
{"classpath*:WEB-INF/geode-management-servlet.xml"},
+    loader = PlainLocatorContextLoader.class)
+@WebAppConfiguration
+public class ClusterManagementClientDUnitTest {
+  private static final ResponseErrorHandler ERROR_HANDLER = new 
RestTemplateResponseErrorHandler();
+
+  @Autowired
+  private WebApplicationContext webApplicationContext;
+
+  @Rule
+  public ClusterStartupRule cluster = new ClusterStartupRule(1);
+
+  private MemberVM server1;
+  private ClusterManagementService client;
+
+  @Before
+  public void before() {
+    cluster.setSkipLocalDistributedSystemCleanup(true);
+    MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
+        .build();
+    MockMvcClientHttpRequestFactory requestFactory = new 
MockMvcClientHttpRequestFactory(mockMvc);
+    client = ClusterManagementServiceProvider.getService(requestFactory);
+
+    server1 = cluster.startServerVM(0,
+        
BaseLocatorContextLoader.getLocatorFromContext(webApplicationContext).getPort());
+  }
+
+  @Test
+  @WithMockUser
+  public void createRegion() {
+    RegionConfig region = new RegionConfig();
+    region.setName("customer");
+    region.setType("REPLICATE");
+
+    ClusterManagementResult result = client.create(region, "");
+
+    // This all fails in light of running this test repeatedly as a stress 
test. Until we introduce
+    // idempotency and/or the ability to call client.delete we can't do this. 
But it will get fixed
+    // assertThat(result.isSuccessful()).isTrue();
+
+    // Not implemented yet
+    // result = client.delete(region, "");
+    // assertThat(result.isSuccessful()).isTrue();
+  }
+}
diff --git 
a/geode-web-management/src/integrationTest/java/org/apache/geode/management/internal/rest/RegionManagementIntegrationTest.java
 
b/geode-web-management/src/integrationTest/java/org/apache/geode/management/internal/rest/RegionManagementIntegrationTest.java
index 5df6a11..14ef4a2 100644
--- 
a/geode-web-management/src/integrationTest/java/org/apache/geode/management/internal/rest/RegionManagementIntegrationTest.java
+++ 
b/geode-web-management/src/integrationTest/java/org/apache/geode/management/internal/rest/RegionManagementIntegrationTest.java
@@ -44,8 +44,7 @@ import org.apache.geode.cache.configuration.RegionConfig;
 @WebAppConfiguration
 public class RegionManagementIntegrationTest {
 
-  static RequestPostProcessor POST_PROCESSOR =
-      new StandardRequestPostProcessor();
+  static RequestPostProcessor POST_PROCESSOR = new 
StandardRequestPostProcessor();
 
   @Autowired
   private WebApplicationContext webApplicationContext;
diff --git 
a/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/controllers/ManagementControllerAdvice.java
 
b/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/controllers/ManagementControllerAdvice.java
index dba5499..9e8265d 100644
--- 
a/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/controllers/ManagementControllerAdvice.java
+++ 
b/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/controllers/ManagementControllerAdvice.java
@@ -26,7 +26,7 @@ import 
org.springframework.web.bind.annotation.ControllerAdvice;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 
 import org.apache.geode.internal.logging.LogService;
-import org.apache.geode.management.internal.api.ClusterManagementResult;
+import org.apache.geode.management.api.ClusterManagementResult;
 import org.apache.geode.management.internal.exceptions.EntityExistsException;
 import org.apache.geode.security.AuthenticationFailedException;
 import org.apache.geode.security.NotAuthorizedException;
@@ -50,7 +50,7 @@ public class ManagementControllerAdvice {
   }
 
   @ExceptionHandler({AuthenticationFailedException.class, 
AuthenticationException.class})
-  public ResponseEntity<ClusterManagementResult> 
unauthorized(AuthenticationFailedException e) {
+  public ResponseEntity<ClusterManagementResult> unauthorized(Exception e) {
     return new ResponseEntity<>(new ClusterManagementResult(false, 
e.getMessage()),
         HttpStatus.UNAUTHORIZED);
   }
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 f1ebae2..e59c0a1 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
@@ -26,7 +26,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 
 import org.apache.geode.cache.configuration.RegionConfig;
-import org.apache.geode.management.internal.api.ClusterManagementResult;
+import org.apache.geode.management.api.ClusterManagementResult;
 
 @Controller("regionManagement")
 @RequestMapping(MANAGEMENT_API_VERSION)
diff --git 
a/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/security/RestSecurityConfiguration.java
 
b/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/security/RestSecurityConfiguration.java
index 2bc6bc6..1edbb79 100644
--- 
a/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/security/RestSecurityConfiguration.java
+++ 
b/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/security/RestSecurityConfiguration.java
@@ -37,7 +37,7 @@ import 
org.springframework.security.config.http.SessionCreationPolicy;
 import org.springframework.security.core.AuthenticationException;
 import org.springframework.security.web.AuthenticationEntryPoint;
 
-import org.apache.geode.management.internal.api.ClusterManagementResult;
+import org.apache.geode.management.api.ClusterManagementResult;
 
 @Configuration
 @EnableWebSecurity

Reply via email to