You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by je...@apache.org on 2019/05/08 15:45:06 UTC

[geode] branch develop updated: GEODE-6745: Add status to list members output for REST v2 (#3558)

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 ab6de19  GEODE-6745: Add status to list members output for REST v2 (#3558)
ab6de19 is described below

commit ab6de191b74fd916a0bbc0053bf4e2f6f8540090
Author: Jens Deppe <jd...@pivotal.io>
AuthorDate: Wed May 8 08:44:53 2019 -0700

    GEODE-6745: Add status to list members output for REST v2 (#3558)
---
 .../rest/MemberManagementServiceDunitTest.java     |   4 +-
 .../integrationTest/resources/assembly_content.txt |   1 +
 .../internal/cli/domain/CacheServerInfo.java       |  30 +++---
 .../internal/cli/domain/MemberInformation.java     |  33 ++++---
 .../functions/GetMemberInformationFunction.java    |  27 ++++--
 .../mutators/MemberConfigManager.java              |  16 +++-
 .../sanctioned-geode-core-serializables.txt        |   4 +-
 .../management/configuration/MemberConfig.java     |  98 ++++++++++++++++---
 .../configuration/CacheElementJsonMappingTest.java |   2 +-
 .../internal/rest/BaseLocatorContextLoader.java    |   9 +-
 ...catorContextLoader.java => GeodeComponent.java} |  21 ++--
 .../internal/rest/LocatorCleanupEventListener.java |   7 +-
 ...ader.java => LocatorLauncherContextLoader.java} |  21 ++--
 .../internal/rest/LocatorWebContext.java           |   5 +-
 .../LocatorWithSecurityManagerContextLoader.java   |   8 +-
 .../internal/rest/PlainLocatorContextLoader.java   |   8 +-
 .../internal/rest/WrappedLocatorLauncher.java      |  71 ++++++++++++++
 ...tLoader.java => WrappedLocatorStarterRule.java} |  35 +++++--
 .../client/MemberManagementServiceDUnitTest.java   |  53 +++++++++--
 ...MemberManagementServiceRestIntegrationTest.java | 106 +++++++++++++++++++++
 20 files changed, 443 insertions(+), 116 deletions(-)

diff --git a/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/MemberManagementServiceDunitTest.java b/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/MemberManagementServiceDunitTest.java
index 79f8f5d..563cbd3 100644
--- a/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/MemberManagementServiceDunitTest.java
+++ b/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/MemberManagementServiceDunitTest.java
@@ -64,7 +64,7 @@ public class MemberManagementServiceDunitTest {
             "locator-0");
     assertThat(memberConfig.isCoordinator()).isTrue();
     assertThat(memberConfig.isLocator()).isTrue();
-    assertThat(memberConfig.getPorts().get(0)).isEqualTo(locator.getPort());
+    assertThat(memberConfig.getPort()).isEqualTo(locator.getPort());
   }
 
   @Test
@@ -80,7 +80,7 @@ public class MemberManagementServiceDunitTest {
     MemberConfig memberConfig = (MemberConfig) result.getResult(RuntimeCacheElement.class).get(0);
     assertThat(memberConfig.isCoordinator()).isTrue();
     assertThat(memberConfig.isLocator()).isTrue();
-    assertThat(memberConfig.getPorts().get(0)).isEqualTo(locator.getPort());
+    assertThat(memberConfig.getPort()).isEqualTo(locator.getPort());
   }
 
   @Test
diff --git a/geode-assembly/src/integrationTest/resources/assembly_content.txt b/geode-assembly/src/integrationTest/resources/assembly_content.txt
index d81b906..a6a30ae 100644
--- a/geode-assembly/src/integrationTest/resources/assembly_content.txt
+++ b/geode-assembly/src/integrationTest/resources/assembly_content.txt
@@ -715,6 +715,7 @@ javadoc/org/apache/geode/management/client/JavaClientClusterManagementServiceCon
 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/configuration/MemberConfig.CacheServerConfig.html
 javadoc/org/apache/geode/management/configuration/MemberConfig.html
 javadoc/org/apache/geode/management/configuration/RuntimeCacheElement.html
 javadoc/org/apache/geode/management/configuration/RuntimeRegionConfig.html
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/CacheServerInfo.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/CacheServerInfo.java
index 1deab35..9088811 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/CacheServerInfo.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/CacheServerInfo.java
@@ -16,6 +16,8 @@ package org.apache.geode.management.internal.cli.domain;
 
 import java.io.Serializable;
 
+import org.apache.geode.cache.server.CacheServer;
+
 public class CacheServerInfo implements Serializable {
 
   private static final long serialVersionUID = 1L;
@@ -23,35 +25,35 @@ public class CacheServerInfo implements Serializable {
   private String bindAddress;
   private int port;
   private boolean isRunning;
+  private int maxConnections;
+  private int maxThreads;
 
-  public CacheServerInfo(String bindAddress, int port, boolean isRunning) {
-    this.setBindAddress(bindAddress);
-    this.setPort(port);
-    this.setRunning(isRunning);
+  public CacheServerInfo(CacheServer cacheServer) {
+    bindAddress = cacheServer.getBindAddress();
+    port = cacheServer.getPort();
+    isRunning = cacheServer.isRunning();
+    maxConnections = cacheServer.getMaxConnections();
+    maxThreads = cacheServer.getMaxThreads();
   }
 
   public String getBindAddress() {
     return bindAddress;
   }
 
-  public void setBindAddress(String bindAddress) {
-    this.bindAddress = bindAddress;
-  }
-
   public int getPort() {
     return port;
   }
 
-  public void setPort(int port) {
-    this.port = port;
+  public int getMaxThreads() {
+    return maxThreads;
   }
 
-  public boolean isRunning() {
-    return isRunning;
+  public int getMaxConnections() {
+    return maxConnections;
   }
 
-  public void setRunning(boolean isRunning) {
-    this.isRunning = isRunning;
+  public boolean isRunning() {
+    return isRunning;
   }
 
   public String toString() {
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 80c4afe..06afe6c 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
@@ -35,12 +35,13 @@ public class MemberInformation implements Serializable {
   private String statArchiveFilePath;
   private String serverBindAddress;
   private String locators;
-  private String heapUsage;
-  private String maxHeapSize;
-  private String initHeapSize;
+  private String status;
+  private long heapUsage;
+  private long maxHeapSize;
+  private long initHeapSize;
   private String cacheXmlFilePath;
   private String host;
-  private String processId;
+  private int processId;
   private int locatorPort;
   private int httpServicePort;
   private String httpServiceBindAddress;
@@ -133,19 +134,27 @@ public class MemberInformation implements Serializable {
     this.locators = locators;
   }
 
-  public String getHeapUsage() {
+  public String getStatus() {
+    return status;
+  }
+
+  public void setStatus(String status) {
+    this.status = status;
+  }
+
+  public long getHeapUsage() {
     return heapUsage;
   }
 
-  public void setHeapUsage(String heapUsage) {
+  public void setHeapUsage(long heapUsage) {
     this.heapUsage = heapUsage;
   }
 
-  public String getMaxHeapSize() {
+  public long getMaxHeapSize() {
     return maxHeapSize;
   }
 
-  public void setMaxHeapSize(String maxHeapSize) {
+  public void setMaxHeapSize(long maxHeapSize) {
     this.maxHeapSize = maxHeapSize;
   }
 
@@ -157,11 +166,11 @@ public class MemberInformation implements Serializable {
     this.cacheXmlFilePath = cacheXmlFilePath;
   }
 
-  public String getInitHeapSize() {
+  public long getInitHeapSize() {
     return initHeapSize;
   }
 
-  public void setInitHeapSize(String initHeapSize) {
+  public void setInitHeapSize(long initHeapSize) {
     this.initHeapSize = initHeapSize;
   }
 
@@ -173,11 +182,11 @@ public class MemberInformation implements Serializable {
     this.host = host;
   }
 
-  public String getProcessId() {
+  public int getProcessId() {
     return processId;
   }
 
-  public void setProcessId(String processId) {
+  public void setProcessId(int processId) {
     this.processId = processId;
   }
 
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 18457ad..b96ae10 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
@@ -28,6 +28,8 @@ 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.LocatorLauncher;
+import org.apache.geode.distributed.ServerLauncher;
 import org.apache.geode.distributed.internal.DistributionConfig;
 import org.apache.geode.distributed.internal.InternalDistributedSystem;
 import org.apache.geode.distributed.internal.InternalLocator;
@@ -91,7 +93,7 @@ public class GetMemberInformationFunction implements InternalFunction {
       memberInfo.setName(member.getName());
       memberInfo.setId(member.getId());
       memberInfo.setHost(member.getHost());
-      memberInfo.setProcessId("" + member.getProcessId());
+      memberInfo.setProcessId(member.getProcessId());
 
       SSLConfig sslConfig = SSLConfigurationFactory.getSSLConfigForComponent(config,
           SecurableCommunicationChannel.WEB);
@@ -106,14 +108,13 @@ public class GetMemberInformationFunction implements InternalFunction {
       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())));
-      memberInfo.setInitHeapSize(Long.toString(bytesToMeg(memUsage.getInit())));
+      memberInfo.setHeapUsage(bytesToMeg(memUsage.getUsed()));
+      memberInfo.setMaxHeapSize(bytesToMeg(memUsage.getMax()));
+      memberInfo.setInitHeapSize(bytesToMeg(memUsage.getInit()));
       memberInfo.setHostedRegions(CliUtil.getAllRegionNames(cache));
 
       List<CacheServer> csList = cache.getCacheServers();
@@ -125,11 +126,7 @@ public class GetMemberInformationFunction implements InternalFunction {
         while (iters.hasNext()) {
           CacheServer cs = iters.next();
 
-          String bindAddress = cs.getBindAddress();
-          int port = cs.getPort();
-          boolean isRunning = cs.isRunning();
-
-          CacheServerInfo cacheServerInfo = new CacheServerInfo(bindAddress, port, isRunning);
+          CacheServerInfo cacheServerInfo = new CacheServerInfo(cs);
           memberInfo.addCacheServerInfo(cacheServerInfo);
         }
         Map<ClientProxyMembershipID, CacheClientStatus> allConnectedClients =
@@ -142,12 +139,22 @@ public class GetMemberInformationFunction implements InternalFunction {
           numConnections = numConnections + status.getNumberOfConnections();
         }
         memberInfo.setClientCount(numConnections);
+
+        ServerLauncher.ServerState state = ServerLauncher.getServerState();
+        if (state != null) {
+          memberInfo.setStatus(state.getStatus().getDescription());
+        }
       } else {
         memberInfo.setServer(false);
         InternalLocator locator = InternalLocator.getLocator();
         if (locator != null) {
           memberInfo.setLocatorPort(locator.getPort());
         }
+
+        LocatorLauncher.LocatorState state = LocatorLauncher.getLocatorState();
+        if (state != null) {
+          memberInfo.setStatus(state.getStatus().getDescription());
+        }
       }
       functionContext.getResultSender().lastResult(memberInfo);
     } catch (CacheClosedException e) {
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/mutators/MemberConfigManager.java b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/mutators/MemberConfigManager.java
index 3cbf533..06d275b 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/mutators/MemberConfigManager.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/mutators/MemberConfigManager.java
@@ -16,7 +16,6 @@
 package org.apache.geode.management.internal.configuration.mutators;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 import java.util.Set;
 import java.util.stream.Collectors;
@@ -82,19 +81,26 @@ public class MemberConfigManager implements ConfigurationManager<MemberConfig> {
 
     ArrayList<MemberInformation> output = (ArrayList<MemberInformation>) rc.getResult();
 
-
     for (MemberInformation mInfo : output) {
       MemberConfig member = new MemberConfig();
       member.setId(mInfo.getName());
       member.setHost(mInfo.getHost());
       member.setPid(mInfo.getProcessId());
+      member.setStatus(mInfo.getStatus());
+      member.setInitialHeap(mInfo.getInitHeapSize());
+      member.setMaxHeap(mInfo.getMaxHeapSize());
 
       if (mInfo.isServer() && mInfo.getCacheServeInfo() != null) {
-        member.setPorts(mInfo.getCacheServeInfo().stream().map(CacheServerInfo::getPort)
-            .collect(Collectors.toList()));
+        for (CacheServerInfo info : mInfo.getCacheServeInfo()) {
+          MemberConfig.CacheServerConfig csConfig = new MemberConfig.CacheServerConfig();
+          csConfig.setPort(info.getPort());
+          csConfig.setMaxConnections(info.getMaxConnections());
+          csConfig.setMaxThreads(info.getMaxThreads());
+          member.addCacheServer(csConfig);
+        }
         member.setLocator(false);
       } else {
-        member.setPorts(Arrays.asList(mInfo.getLocatorPort()));
+        member.setPort(mInfo.getLocatorPort());
         member.setLocator(true);
       }
 
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 fabf1c7..9cce709 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
@@ -454,7 +454,7 @@ org/apache/geode/management/internal/cli/CliUtil$DeflaterInflaterData,true,11048
 org/apache/geode/management/internal/cli/commands/CreateJndiBindingCommand$DATASOURCE_TYPE,false,type:java/lang/String
 org/apache/geode/management/internal/cli/commands/ImportClusterConfigurationCommand$Action,false
 org/apache/geode/management/internal/cli/domain/AsyncEventQueueDetails,true,1,batchSize:int,diskStoreName:java/lang/String,id:java/lang/String,listener:java/lang/String,listenerProperties:java/util/Properties,maxQueueMemory:int,persistent:boolean
-org/apache/geode/management/internal/cli/domain/CacheServerInfo,true,1,bindAddress:java/lang/String,isRunning:boolean,port:int
+org/apache/geode/management/internal/cli/domain/CacheServerInfo,true,1,bindAddress:java/lang/String,isRunning:boolean,maxConnections:int,maxThreads:int,port:int
 org/apache/geode/management/internal/cli/domain/ClassName,true,1,className:java/lang/String,initProperties:java/util/Properties
 org/apache/geode/management/internal/cli/domain/DataCommandRequest,false,command:java/lang/String,key:java/lang/String,keyClass:java/lang/String,loadOnCacheMiss:boolean,principal:java/lang/Object,putIfAbsent:boolean,query:java/lang/String,recursive:boolean,regionName:java/lang/String,removeAllKeys:java/lang/String,value:java/lang/String,valueClass:java/lang/String
 org/apache/geode/management/internal/cli/domain/DataCommandResult,true,2601227194108110936,command:java/lang/String,error:java/lang/Throwable,errorString:java/lang/String,getResult:java/lang/Object,hasResultForAggregation:boolean,infoString:java/lang/String,inputKey:java/lang/Object,inputQuery:java/lang/Object,inputValue:java/lang/Object,keyClass:java/lang/String,limit:int,locateEntryLocations:java/util/List,locateEntryResult:org/apache/geode/management/internal/cli/domain/DataCommandRes [...]
@@ -471,7 +471,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,httpServiceBindAddress:java/lang/String,httpServicePort:int,id:java/lang/String,initHeapSize:java/lang/String,isSecured:boolean,isServer:boolean,locatorPort:int,locators:java/lang/String,logFilePath:java/lang/String,maxHe [...]
+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:long,host:java/lang/String,hostedRegions:java/util/Set,httpServiceBindAddress:java/lang/String,httpServicePort:int,id:java/lang/String,initHeapSize:long,isSecured:boolean,isServer:boolean,locatorPort:int,locators:java/lang/String,logFilePath:java/lang/String,maxHeapSize:long,name:java/la [...]
 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
diff --git a/geode-management/src/main/java/org/apache/geode/management/configuration/MemberConfig.java b/geode-management/src/main/java/org/apache/geode/management/configuration/MemberConfig.java
index cb2a5c7..d2fd978 100644
--- a/geode-management/src/main/java/org/apache/geode/management/configuration/MemberConfig.java
+++ b/geode-management/src/main/java/org/apache/geode/management/configuration/MemberConfig.java
@@ -15,15 +15,17 @@
 
 package org.apache.geode.management.configuration;
 
+import java.util.ArrayList;
 import java.util.List;
 
+import com.fasterxml.jackson.annotation.JsonInclude;
+
 import org.apache.geode.annotations.Experimental;
 import org.apache.geode.cache.configuration.CacheElement;
 import org.apache.geode.management.api.RestfulEndpoint;
 
 @Experimental
-public class MemberConfig extends CacheElement
-    implements RuntimeCacheElement, RestfulEndpoint {
+public class MemberConfig extends CacheElement implements RuntimeCacheElement, RestfulEndpoint {
 
   private static final long serialVersionUID = -6262538068604902018L;
 
@@ -33,13 +35,49 @@ public class MemberConfig extends CacheElement
   private boolean isCoordinator;
   private String id;
   private String host;
-  private String pid;
-  private List<Integer> ports;
-
-  public MemberConfig() {
-
+  private String status;
+  private int pid;
+  // Only relevant for locators - will be suppressed if null
+  private Integer port;
+  // Only relevant for servers - will be suppressed if empty
+  private List<CacheServerConfig> cacheServers = new ArrayList<>();
+  private long maxHeap;
+  private long initialHeap;
+
+  public static class CacheServerConfig {
+    private int port;
+    private int maxConnections;
+    private int maxThreads;
+
+    public CacheServerConfig() {}
+
+    public int getPort() {
+      return port;
+    }
+
+    public void setPort(int port) {
+      this.port = port;
+    }
+
+    public int getMaxConnections() {
+      return maxConnections;
+    }
+
+    public void setMaxConnections(int maxConnections) {
+      this.maxConnections = maxConnections;
+    }
+
+    public int getMaxThreads() {
+      return maxThreads;
+    }
+
+    public void setMaxThreads(int maxThreads) {
+      this.maxThreads = maxThreads;
+    }
   }
 
+  public MemberConfig() {}
+
   public void setId(String id) {
     this.id = id;
   }
@@ -68,20 +106,38 @@ public class MemberConfig extends CacheElement
     this.host = host;
   }
 
-  public String getPid() {
+  public String getStatus() {
+    return status;
+  }
+
+  public void setStatus(String status) {
+    this.status = status;
+  }
+
+  public int getPid() {
     return pid;
   }
 
-  public void setPid(String pid) {
+  public void setPid(int pid) {
     this.pid = pid;
   }
 
-  public List<Integer> getPorts() {
-    return ports;
+  @JsonInclude(value = JsonInclude.Include.NON_NULL)
+  public Integer getPort() {
+    return port;
+  }
+
+  public void setPort(Integer port) {
+    this.port = port;
   }
 
-  public void setPorts(List<Integer> port) {
-    this.ports = port;
+  @JsonInclude(value = JsonInclude.Include.NON_EMPTY)
+  public List<CacheServerConfig> getCacheServers() {
+    return cacheServers;
+  }
+
+  public void addCacheServer(CacheServerConfig cacheServer) {
+    cacheServers.add(cacheServer);
   }
 
   @Override
@@ -97,4 +153,20 @@ public class MemberConfig extends CacheElement
   public List<String> getGroups() {
     return groups;
   }
+
+  public long getMaxHeap() {
+    return maxHeap;
+  }
+
+  public void setMaxHeap(long maxHeap) {
+    this.maxHeap = maxHeap;
+  }
+
+  public long getInitialHeap() {
+    return initialHeap;
+  }
+
+  public void setInitialHeap(long initialHeap) {
+    this.initialHeap = initialHeap;
+  }
 }
diff --git a/geode-management/src/test/java/org/apache/geode/cache/configuration/CacheElementJsonMappingTest.java b/geode-management/src/test/java/org/apache/geode/cache/configuration/CacheElementJsonMappingTest.java
index 40af811..3ed245d 100644
--- a/geode-management/src/test/java/org/apache/geode/cache/configuration/CacheElementJsonMappingTest.java
+++ b/geode-management/src/test/java/org/apache/geode/cache/configuration/CacheElementJsonMappingTest.java
@@ -40,7 +40,7 @@ public class CacheElementJsonMappingTest {
   public static void beforeClass() throws Exception {
     member = new MemberConfig();
     member.setId("server");
-    member.setPid("123");
+    member.setPid(123);
 
     region = new RuntimeRegionConfig();
     region.setName("test");
diff --git a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/BaseLocatorContextLoader.java b/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/BaseLocatorContextLoader.java
index 16bfe8d..b687ab3 100644
--- a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/BaseLocatorContextLoader.java
+++ b/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/BaseLocatorContextLoader.java
@@ -20,7 +20,6 @@ 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
@@ -30,19 +29,19 @@ import org.apache.geode.test.junit.rules.LocatorStarterRule;
  */
 public abstract class BaseLocatorContextLoader extends GenericXmlWebContextLoader {
 
-  public abstract LocatorStarterRule getLocator();
+  public abstract GeodeComponent getLocator();
 
   @Override
   protected void loadBeanDefinitions(GenericWebApplicationContext context,
       WebMergedContextConfiguration webMergedConfig) {
 
-    getLocator().before();
+    getLocator().start();
 
     super.loadBeanDefinitions(context, webMergedConfig);
     context.getServletContext().setAttribute(HttpService.SECURITY_SERVICE_SERVLET_CONTEXT_PARAM,
-        getLocator().getCache().getSecurityService());
+        getLocator().getSecurityService());
     context.getServletContext().setAttribute(HttpService.CLUSTER_MANAGEMENT_SERVICE_CONTEXT_PARAM,
-        getLocator().getLocator().getClusterManagementService());
+        getLocator().getClusterManagementService());
     context.getServletContext().setAttribute("locator", getLocator());
   }
 }
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/GeodeComponent.java
similarity index 69%
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/GeodeComponent.java
index adedec8..192dc0b 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/GeodeComponent.java
@@ -15,19 +15,18 @@
 
 package org.apache.geode.management.internal.rest;
 
-import org.apache.geode.test.junit.rules.LocatorStarterRule;
+import org.apache.geode.internal.security.SecurityService;
+import org.apache.geode.management.api.ClusterManagementService;
 
-public class PlainLocatorContextLoader extends BaseLocatorContextLoader {
+public interface GeodeComponent {
 
-  private final LocatorStarterRule locator;
+  void start();
 
-  public PlainLocatorContextLoader() {
-    locator = new LocatorStarterRule()
-        .withAutoStart();
-  }
+  void stop();
 
-  @Override
-  public LocatorStarterRule getLocator() {
-    return locator;
-  }
+  int getPort();
+
+  SecurityService getSecurityService();
+
+  ClusterManagementService getClusterManagementService();
 }
diff --git a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/LocatorCleanupEventListener.java b/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/LocatorCleanupEventListener.java
index d7af991..243a0aa 100644
--- a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/LocatorCleanupEventListener.java
+++ b/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/LocatorCleanupEventListener.java
@@ -21,7 +21,6 @@ import org.springframework.context.event.EventListener;
 import org.springframework.stereotype.Component;
 import org.springframework.web.context.WebApplicationContext;
 
-import org.apache.geode.test.junit.rules.LocatorStarterRule;
 
 @Component
 public class LocatorCleanupEventListener {
@@ -31,10 +30,10 @@ public class LocatorCleanupEventListener {
 
   @EventListener
   public void handleContextCloseEvent(ContextClosedEvent closedEvent) {
-    LocatorStarterRule locator =
-        (LocatorStarterRule) webApplicationContext.getServletContext().getAttribute("locator");
+    GeodeComponent locator =
+        (GeodeComponent) webApplicationContext.getServletContext().getAttribute("locator");
     if (locator != null) {
-      locator.after();
+      locator.stop();
     }
   }
 }
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/LocatorLauncherContextLoader.java
similarity index 61%
copy from geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/LocatorWithSecurityManagerContextLoader.java
copy to geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/LocatorLauncherContextLoader.java
index 2738a0c..a4d76e2 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/LocatorLauncherContextLoader.java
@@ -15,22 +15,23 @@
 
 package org.apache.geode.management.internal.rest;
 
-import org.apache.geode.examples.SimpleSecurityManager;
-import org.apache.geode.test.junit.rules.LocatorStarterRule;
+import org.apache.geode.distributed.ConfigurationProperties;
+import org.apache.geode.distributed.LocatorLauncher;
 
-public class LocatorWithSecurityManagerContextLoader extends BaseLocatorContextLoader {
+public class LocatorLauncherContextLoader extends BaseLocatorContextLoader {
 
-  private final LocatorStarterRule locator;
+  private final GeodeComponent locator;
 
-  public LocatorWithSecurityManagerContextLoader() {
-    locator = new LocatorStarterRule()
-        .withSecurityManager(SimpleSecurityManager.class)
-        .withAutoStart();
+  public LocatorLauncherContextLoader() {
+    LocatorLauncher.Builder builder = new LocatorLauncher.Builder()
+        .setPort(0)
+        .setMemberName("locator-0")
+        .set(ConfigurationProperties.LOG_LEVEL, "config");
+    locator = new WrappedLocatorLauncher(builder);
   }
 
   @Override
-  public LocatorStarterRule getLocator() {
+  public GeodeComponent getLocator() {
     return locator;
   }
-
 }
diff --git a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/LocatorWebContext.java b/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/LocatorWebContext.java
index f0762a1..084d356 100644
--- a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/LocatorWebContext.java
+++ b/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/LocatorWebContext.java
@@ -26,7 +26,6 @@ import org.springframework.test.web.servlet.request.RequestPostProcessor;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 import org.springframework.web.context.WebApplicationContext;
 
-import org.apache.geode.test.junit.rules.LocatorStarterRule;
 
 /**
  * use in conjunction with any BaseLocatorContextLoader to ease the interaction with the locator
@@ -53,8 +52,8 @@ public class LocatorWebContext {
     requestFactory = new MockMvcClientHttpRequestFactory(mockMvc);
   }
 
-  public LocatorStarterRule getLocator() {
-    return (LocatorStarterRule) webApplicationContext.getServletContext().getAttribute("locator");
+  public GeodeComponent getLocator() {
+    return (GeodeComponent) webApplicationContext.getServletContext().getAttribute("locator");
   }
 
   public MockMvcClientHttpRequestFactory getRequestFactory() {
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 2738a0c..2bbeffe 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
@@ -20,16 +20,16 @@ import org.apache.geode.test.junit.rules.LocatorStarterRule;
 
 public class LocatorWithSecurityManagerContextLoader extends BaseLocatorContextLoader {
 
-  private final LocatorStarterRule locator;
+  private final GeodeComponent locator;
 
   public LocatorWithSecurityManagerContextLoader() {
-    locator = new LocatorStarterRule()
+    locator = new WrappedLocatorStarterRule(new LocatorStarterRule()
         .withSecurityManager(SimpleSecurityManager.class)
-        .withAutoStart();
+        .withAutoStart());
   }
 
   @Override
-  public LocatorStarterRule getLocator() {
+  public GeodeComponent 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 adedec8..7910503 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
@@ -19,15 +19,15 @@ import org.apache.geode.test.junit.rules.LocatorStarterRule;
 
 public class PlainLocatorContextLoader extends BaseLocatorContextLoader {
 
-  private final LocatorStarterRule locator;
+  private final GeodeComponent locator;
 
   public PlainLocatorContextLoader() {
-    locator = new LocatorStarterRule()
-        .withAutoStart();
+    locator = new WrappedLocatorStarterRule(new LocatorStarterRule()
+        .withAutoStart());
   }
 
   @Override
-  public LocatorStarterRule getLocator() {
+  public GeodeComponent getLocator() {
     return locator;
   }
 }
diff --git a/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/WrappedLocatorLauncher.java b/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/WrappedLocatorLauncher.java
new file mode 100644
index 0000000..d364efa
--- /dev/null
+++ b/geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/WrappedLocatorLauncher.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.apache.geode.management.internal.rest;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+
+import org.junit.rules.TemporaryFolder;
+
+import org.apache.geode.distributed.LocatorLauncher;
+import org.apache.geode.distributed.internal.InternalLocator;
+import org.apache.geode.internal.security.SecurityService;
+import org.apache.geode.management.api.ClusterManagementService;
+
+public class WrappedLocatorLauncher implements GeodeComponent {
+
+  private final LocatorLauncher locator;
+
+  private final TemporaryFolder temp;
+
+  public WrappedLocatorLauncher(LocatorLauncher.Builder builder) {
+    temp = new TemporaryFolder();
+    try {
+      temp.create();
+    } catch (IOException e) {
+      throw new UncheckedIOException(e);
+    }
+
+    builder.setWorkingDirectory(temp.getRoot().getAbsolutePath());
+    this.locator = builder.build();
+  }
+
+  @Override
+  public void start() {
+    locator.start();
+  }
+
+  @Override
+  public void stop() {
+    locator.stop();
+    temp.delete();
+  }
+
+  @Override
+  public int getPort() {
+    return locator.getPort();
+  }
+
+  @Override
+  public SecurityService getSecurityService() {
+    return ((InternalLocator) locator.getLocator()).getCache().getSecurityService();
+  }
+
+  @Override
+  public ClusterManagementService getClusterManagementService() {
+    return ((InternalLocator) locator.getLocator()).getClusterManagementService();
+  }
+}
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/WrappedLocatorStarterRule.java
similarity index 55%
copy from geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/LocatorWithSecurityManagerContextLoader.java
copy to geode-web-management/src/commonTest/java/org/apache/geode/management/internal/rest/WrappedLocatorStarterRule.java
index 2738a0c..87bf4f4 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/WrappedLocatorStarterRule.java
@@ -15,22 +15,39 @@
 
 package org.apache.geode.management.internal.rest;
 
-import org.apache.geode.examples.SimpleSecurityManager;
+import org.apache.geode.internal.security.SecurityService;
+import org.apache.geode.management.api.ClusterManagementService;
 import org.apache.geode.test.junit.rules.LocatorStarterRule;
 
-public class LocatorWithSecurityManagerContextLoader extends BaseLocatorContextLoader {
+public class WrappedLocatorStarterRule implements GeodeComponent {
+  private final LocatorStarterRule rule;
 
-  private final LocatorStarterRule locator;
+  public WrappedLocatorStarterRule(LocatorStarterRule rule) {
+    this.rule = rule;
+  }
+
+  @Override
+  public void start() {
+    rule.before();
+  }
+
+  @Override
+  public void stop() {
+    rule.after();
+  }
 
-  public LocatorWithSecurityManagerContextLoader() {
-    locator = new LocatorStarterRule()
-        .withSecurityManager(SimpleSecurityManager.class)
-        .withAutoStart();
+  @Override
+  public int getPort() {
+    return rule.getPort();
   }
 
   @Override
-  public LocatorStarterRule getLocator() {
-    return locator;
+  public SecurityService getSecurityService() {
+    return rule.getLocator().getCache().getSecurityService();
   }
 
+  @Override
+  public ClusterManagementService getClusterManagementService() {
+    return rule.getLocator().getClusterManagementService();
+  }
 }
diff --git a/geode-web-management/src/distributedTest/java/org/apache/geode/management/client/MemberManagementServiceDUnitTest.java b/geode-web-management/src/distributedTest/java/org/apache/geode/management/client/MemberManagementServiceDUnitTest.java
index f245bdb..08450a3 100644
--- a/geode-web-management/src/distributedTest/java/org/apache/geode/management/client/MemberManagementServiceDUnitTest.java
+++ b/geode-web-management/src/distributedTest/java/org/apache/geode/management/client/MemberManagementServiceDUnitTest.java
@@ -16,13 +16,14 @@
 package org.apache.geode.management.client;
 
 
-import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.hamcrest.Matchers.is;
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
 
 import java.util.List;
+import java.util.stream.Collectors;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -41,13 +42,13 @@ import org.apache.geode.management.api.ClusterManagementServiceConfig;
 import org.apache.geode.management.configuration.MemberConfig;
 import org.apache.geode.management.configuration.RuntimeCacheElement;
 import org.apache.geode.management.internal.ClientClusterManagementService;
+import org.apache.geode.management.internal.rest.LocatorLauncherContextLoader;
 import org.apache.geode.management.internal.rest.LocatorWebContext;
-import org.apache.geode.management.internal.rest.PlainLocatorContextLoader;
 import org.apache.geode.test.dunit.rules.ClusterStartupRule;
 
 @RunWith(SpringRunner.class)
 @ContextConfiguration(locations = {"classpath*:WEB-INF/geode-management-servlet.xml"},
-    loader = PlainLocatorContextLoader.class)
+    loader = LocatorLauncherContextLoader.class)
 @WebAppConfiguration
 public class MemberManagementServiceDUnitTest {
 
@@ -70,26 +71,46 @@ public class MemberManagementServiceDUnitTest {
         .build();
     client = new ClientClusterManagementService(config);
 
-    cluster.startServerVM(0, webContext.getLocator().getPort());
+    cluster.startServerVM(1, webContext.getLocator().getPort());
   }
 
   @Test
   @WithMockUser
-  public void listMember() {
+  public void listAllMembers() {
     MemberConfig memberConfig = new MemberConfig();
     ClusterManagementResult result = client.list(memberConfig);
 
     assertThat(result.isSuccessful()).isTrue();
     assertThat(result.getStatusCode()).isEqualTo(ClusterManagementResult.StatusCode.OK);
-    assertThat(result.getResult(RuntimeCacheElement.class).size()).isEqualTo(2);
+
+    List<MemberConfig> members = result.getResult(MemberConfig.class);
+    assertThat(members.size()).isEqualTo(2);
+    assertThat(members.stream().map(MemberConfig::getId).collect(Collectors.toList()))
+        .containsExactlyInAnyOrder("locator-0", "server-1");
+    for (MemberConfig oneMember : members) {
+      if (oneMember.isLocator()) {
+        assertThat(oneMember.getPort())
+            .as("port for locator member should not be null").isNotNull().isGreaterThan(0);
+        assertThat(oneMember.getCacheServers().size())
+            .as("locators should not have cache servers").isEqualTo(0);
+      } else {
+        assertThat(oneMember.getPort()).as("port for server member should be null").isNull();
+        assertThat(oneMember.getCacheServers().size())
+            .as("server should have one cache server").isEqualTo(1);
+        assertThat(oneMember.getCacheServers().get(0).getPort()).isGreaterThan(0);
+        assertThat(oneMember.getCacheServers().get(0).getMaxConnections()).isGreaterThan(0);
+        assertThat(oneMember.getCacheServers().get(0).getMaxThreads()).isEqualTo(0);
+      }
+    }
   }
 
   @Test
   @WithMockUser
   public void getOneMember() throws Exception {
     MemberConfig config = new MemberConfig();
-    config.setId("server-0");
+    config.setId("server-1");
     ClusterManagementResult result = client.list(config);
+
     assertThat(result.isSuccessful()).isTrue();
     assertThat(result.getStatusCode()).isEqualTo(ClusterManagementResult.StatusCode.OK);
 
@@ -99,6 +120,24 @@ public class MemberManagementServiceDUnitTest {
 
   @Test
   @WithMockUser
+  public void getMemberStatus() throws Exception {
+    MemberConfig config = new MemberConfig();
+    config.setId("locator-0");
+    ClusterManagementResult result = client.list(config);
+    assertThat(result.isSuccessful()).isTrue();
+    assertThat(result.getStatusCode()).isEqualTo(ClusterManagementResult.StatusCode.OK);
+
+    List<MemberConfig> members = result.getResult(MemberConfig.class);
+    assertThat(members.size()).isEqualTo(1);
+
+    MemberConfig memberConfig = members.get(0);
+    assertThat(memberConfig.getInitialHeap()).isGreaterThan(0);
+    assertThat(memberConfig.getMaxHeap()).isGreaterThan(0);
+    assertThat(memberConfig.getStatus()).isEqualTo("online");
+  }
+
+  @Test
+  @WithMockUser
   public void noMatchWithJavaAPI() throws Exception {
     MemberConfig config = new MemberConfig();
     // look for a member with a non-existent id
diff --git a/geode-web-management/src/integrationTest/java/org/apache/geode/management/internal/rest/MemberManagementServiceRestIntegrationTest.java b/geode-web-management/src/integrationTest/java/org/apache/geode/management/internal/rest/MemberManagementServiceRestIntegrationTest.java
new file mode 100644
index 0000000..925a329
--- /dev/null
+++ b/geode-web-management/src/integrationTest/java/org/apache/geode/management/internal/rest/MemberManagementServiceRestIntegrationTest.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.apache.geode.management.internal.rest;
+
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.is;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+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.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.web.context.WebApplicationContext;
+
+import org.apache.geode.test.dunit.rules.ClusterStartupRule;
+
+@RunWith(SpringRunner.class)
+@ContextConfiguration(locations = {"classpath*:WEB-INF/geode-management-servlet.xml"},
+    loader = LocatorLauncherContextLoader.class)
+@WebAppConfiguration
+public class MemberManagementServiceRestIntegrationTest {
+
+  @Autowired
+  private WebApplicationContext webApplicationContext;
+
+  @Rule
+  public ClusterStartupRule cluster = new ClusterStartupRule(1);
+
+  private LocatorWebContext webContext;
+
+  private ObjectMapper mapper;
+
+  @Before
+  public void before() {
+    mapper = new ObjectMapper();
+    webContext = new LocatorWebContext(webApplicationContext);
+
+    cluster.setSkipLocalDistributedSystemCleanup(true);
+    cluster.startServerVM(1, webContext.getLocator().getPort());
+  }
+
+  @Test
+  public void listLocator() throws Exception {
+    webContext.perform(get("/v2/members")
+        .param("id", "locator-0"))
+        .andDo(print())
+        .andExpect(status().isOk())
+        .andExpect(jsonPath("$.memberStatuses").doesNotExist())
+        .andExpect(jsonPath("$.statusCode", is("OK")))
+        .andExpect(jsonPath("$.result[*].id", contains("locator-0")))
+        .andExpect(jsonPath("$.result[0].port", greaterThan(0)))
+        .andExpect(jsonPath("$.result[0].locator", is(true)))
+        .andExpect(jsonPath("$.result[0].status", is("online")))
+        .andExpect(jsonPath("$.result[0].cacheServers").doesNotExist());
+  }
+
+  @Test
+  public void listServer() throws Exception {
+    webContext.perform(get("/v2/members")
+        .param("id", "server-1"))
+        .andDo(print())
+        .andExpect(status().isOk())
+        .andExpect(jsonPath("$.memberStatuses").doesNotExist())
+        .andExpect(jsonPath("$.statusCode", is("OK")))
+        .andExpect(jsonPath("$.result[*].id", contains("server-1")))
+        .andExpect(jsonPath("$.result[0].port").doesNotExist())
+        .andExpect(jsonPath("$.result[0].locator", is(false)))
+        .andExpect(jsonPath("$.result[0].cacheServers[0].port", greaterThan(0)))
+        .andExpect(jsonPath("$.result[0].cacheServers[0].maxConnections", equalTo(800)))
+        .andExpect(jsonPath("$.result[0].cacheServers[0].maxThreads", equalTo(0)));
+  }
+
+  @Test
+  public void listAllMembers() throws Exception {
+    webContext.perform(get("/v2/members"))
+        .andDo(print())
+        .andExpect(status().isOk())
+        .andExpect(jsonPath("$.memberStatuses").doesNotExist())
+        .andExpect(jsonPath("$.statusCode", is("OK")))
+        .andExpect(jsonPath("$.result[*].id", containsInAnyOrder("locator-0", "server-1")));
+  }
+}