You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by jc...@apache.org on 2019/02/15 01:32:30 UTC

[geode] branch develop updated: GEODE-6365: Add server group support for list and destroy jdbc-mapping (#3175)

This is an automated email from the ASF dual-hosted git repository.

jchen21 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 2c40a91  GEODE-6365: Add server group support for list and destroy jdbc-mapping (#3175)
2c40a91 is described below

commit 2c40a9188dea53f9bb30b0c23f9312e6ab9a2313
Author: Xiaojian Zhou <ge...@users.noreply.github.com>
AuthorDate: Thu Feb 14 17:32:12 2019 -0800

    GEODE-6365: Add server group support for list and destroy jdbc-mapping (#3175)
    
    Co-authored-by: Xiaojian Zhou <gz...@pivotal.io>
    Co-authored-by: Ben Ross <br...@pivotal.io>
    Co-authored-by: Jianxia Chen <jc...@pivotal.io>
---
 .../geode/connectors/jdbc/JdbcDistributedTest.java |   6 +-
 .../cli/CreateMappingCommandDUnitTest.java         |  13 +-
 .../cli/DestroyMappingCommandDunitTest.java        | 165 ++++++++++++++++----
 .../internal/cli/ListMappingCommandDUnitTest.java  | 171 ++++++++++++++++++---
 .../jdbc/internal/cli/CreateMappingCommand.java    |  25 +--
 .../jdbc/internal/cli/CreateMappingFunction.java   |   3 +-
 .../jdbc/internal/cli/DescribeMappingCommand.java  |  66 +++-----
 .../jdbc/internal/cli/DestroyMappingCommand.java   |  15 +-
 .../jdbc/internal/cli/DestroyMappingFunction.java  |   3 +-
 .../jdbc/internal/cli/ListMappingCommand.java      |  65 ++++++--
 .../jdbc/internal/cli/ListMappingFunction.java     |  29 ----
 .../util/internal/MappingCommandUtils.java         |  94 +++++++++++
 .../sanctioned-geode-connectors-serializables.txt  |   1 -
 .../internal/cli/CreateMappingCommandTest.java     |  23 +--
 .../internal/cli/CreateMappingFunctionTest.java    |   3 +-
 .../cli}/DescribeMappingCommandTest.java           |  11 +-
 .../cli/DestroyMappingCommandFunctionTest.java     |   5 +-
 .../internal/cli/DestroyMappingCommandTest.java    |  26 +++-
 .../jdbc/internal/cli/ListMappingCommandTest.java  |  90 +++++++++--
 .../jdbc/internal/cli/ListMappingFunctionTest.java | 166 --------------------
 .../util/internal/MappingCommandUtilsTest.java     | 137 +++++++++++++++++
 21 files changed, 735 insertions(+), 382 deletions(-)

diff --git a/geode-connectors/src/acceptanceTest/java/org/apache/geode/connectors/jdbc/JdbcDistributedTest.java b/geode-connectors/src/acceptanceTest/java/org/apache/geode/connectors/jdbc/JdbcDistributedTest.java
index 66c6fa3..33aaa87 100644
--- a/geode-connectors/src/acceptanceTest/java/org/apache/geode/connectors/jdbc/JdbcDistributedTest.java
+++ b/geode-connectors/src/acceptanceTest/java/org/apache/geode/connectors/jdbc/JdbcDistributedTest.java
@@ -37,7 +37,7 @@ import org.junit.Test;
 import org.apache.geode.cache.Region;
 import org.apache.geode.cache.client.ClientCacheFactory;
 import org.apache.geode.cache.client.ClientRegionShortcut;
-import org.apache.geode.connectors.jdbc.internal.cli.CreateMappingCommand;
+import org.apache.geode.connectors.util.internal.MappingCommandUtils;
 import org.apache.geode.pdx.PdxInstance;
 import org.apache.geode.pdx.ReflectionBasedAutoSerializer;
 import org.apache.geode.pdx.internal.AutoSerializableManager;
@@ -488,7 +488,7 @@ public abstract class JdbcDistributedTest implements Serializable {
       String key = "id1";
       Region<Object, Object> region = ClusterStartupRule.getCache().getRegion(REGION_NAME);
       JdbcAsyncWriter asyncWriter = (JdbcAsyncWriter) ClusterStartupRule.getCache()
-          .getAsyncEventQueue(CreateMappingCommand.createAsyncEventQueueName(REGION_NAME))
+          .getAsyncEventQueue(MappingCommandUtils.createAsyncEventQueueName(REGION_NAME))
           .getAsyncEventListener();
 
       region.put(key, pdxEmployee1);
@@ -689,7 +689,7 @@ public abstract class JdbcDistributedTest implements Serializable {
     if (!synchronous) {
       final String alterAsyncQueue =
           "alter async-event-queue --id="
-              + CreateMappingCommand.createAsyncEventQueueName(regionName)
+              + MappingCommandUtils.createAsyncEventQueueName(regionName)
               + " --batch-size=1 --batch-time-interval=0";
       gfsh.executeAndAssertThat(alterAsyncQueue).statusIsSuccess();
     }
diff --git a/geode-connectors/src/distributedTest/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingCommandDUnitTest.java b/geode-connectors/src/distributedTest/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingCommandDUnitTest.java
index e0a1af8..2147063 100644
--- a/geode-connectors/src/distributedTest/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingCommandDUnitTest.java
+++ b/geode-connectors/src/distributedTest/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingCommandDUnitTest.java
@@ -46,6 +46,7 @@ import org.apache.geode.connectors.jdbc.JdbcLoader;
 import org.apache.geode.connectors.jdbc.JdbcWriter;
 import org.apache.geode.connectors.jdbc.internal.JdbcConnectorService;
 import org.apache.geode.connectors.jdbc.internal.configuration.RegionMapping;
+import org.apache.geode.connectors.util.internal.MappingCommandUtils;
 import org.apache.geode.distributed.internal.InternalLocator;
 import org.apache.geode.internal.cache.InternalCache;
 import org.apache.geode.management.internal.cli.util.CommandStringBuilder;
@@ -125,7 +126,7 @@ public class CreateMappingCommandDUnitTest {
   private void setupAsyncEventQueue(String regionName) {
     gfsh.executeAndAssertThat(
         "create async-event-queue --id="
-            + CreateMappingCommand.createAsyncEventQueueName(regionName)
+            + MappingCommandUtils.createAsyncEventQueueName(regionName)
             + " --listener=" + JdbcAsyncWriter.class.getName())
         .statusIsSuccess();
   }
@@ -155,7 +156,7 @@ public class CreateMappingCommandDUnitTest {
         InternalLocator.getLocator().getConfigurationPersistenceService().getCacheConfig(groups);
     List<CacheConfig.AsyncEventQueue> queueList = cacheConfig.getAsyncEventQueues();
     CacheConfig.AsyncEventQueue queue = queueList.get(0);
-    String queueName = CreateMappingCommand.createAsyncEventQueueName(regionName);
+    String queueName = MappingCommandUtils.createAsyncEventQueueName(regionName);
     assertThat(queue.getId()).isEqualTo(queueName);
     assertThat(queue.getAsyncEventListener().getClassName())
         .isEqualTo(JdbcAsyncWriter.class.getName());
@@ -182,7 +183,7 @@ public class CreateMappingCommandDUnitTest {
     if (synchronous) {
       assertThat(attributes.getCacheWriter().getClassName()).isEqualTo(JdbcWriter.class.getName());
     } else {
-      String queueName = CreateMappingCommand.createAsyncEventQueueName(regionName);
+      String queueName = MappingCommandUtils.createAsyncEventQueueName(regionName);
       assertThat(attributes.getAsyncEventQueueIds()).isEqualTo(queueName);
     }
   }
@@ -190,7 +191,7 @@ public class CreateMappingCommandDUnitTest {
   private static void validateAsyncEventQueueCreatedOnServer(String regionName,
       boolean isParallel) {
     InternalCache cache = ClusterStartupRule.getCache();
-    String queueName = CreateMappingCommand.createAsyncEventQueueName(regionName);
+    String queueName = MappingCommandUtils.createAsyncEventQueueName(regionName);
     AsyncEventQueue queue = cache.getAsyncEventQueue(queueName);
     assertThat(queue).isNotNull();
     assertThat(queue.getAsyncEventListener()).isInstanceOf(JdbcAsyncWriter.class);
@@ -204,7 +205,7 @@ public class CreateMappingCommandDUnitTest {
     if (synchronous) {
       assertThat(region.getAttributes().getCacheWriter()).isInstanceOf(JdbcWriter.class);
     } else {
-      String queueName = CreateMappingCommand.createAsyncEventQueueName(regionName);
+      String queueName = MappingCommandUtils.createAsyncEventQueueName(regionName);
       assertThat(region.getAttributes().getAsyncEventQueueIds()).contains(queueName);
     }
   }
@@ -732,7 +733,7 @@ public class CreateMappingCommandDUnitTest {
 
     gfsh.executeAndAssertThat(csb.toString()).statusIsError()
         .containsOutput("An async-event-queue named "
-            + CreateMappingCommand.createAsyncEventQueueName(regionName)
+            + MappingCommandUtils.createAsyncEventQueueName(regionName)
             + " must not already exist.");
   }
 
diff --git a/geode-connectors/src/distributedTest/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyMappingCommandDunitTest.java b/geode-connectors/src/distributedTest/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyMappingCommandDunitTest.java
index cff48d5..c0c00de 100644
--- a/geode-connectors/src/distributedTest/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyMappingCommandDunitTest.java
+++ b/geode-connectors/src/distributedTest/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyMappingCommandDunitTest.java
@@ -36,6 +36,7 @@ import org.apache.geode.cache.configuration.RegionAttributesType;
 import org.apache.geode.cache.configuration.RegionConfig;
 import org.apache.geode.connectors.jdbc.internal.JdbcConnectorService;
 import org.apache.geode.connectors.jdbc.internal.configuration.RegionMapping;
+import org.apache.geode.connectors.util.internal.MappingCommandUtils;
 import org.apache.geode.distributed.internal.InternalLocator;
 import org.apache.geode.internal.cache.InternalCache;
 import org.apache.geode.management.internal.cli.util.CommandStringBuilder;
@@ -49,6 +50,11 @@ import org.apache.geode.test.junit.rules.serializable.SerializableTestName;
 public class DestroyMappingCommandDunitTest implements Serializable {
 
   private static final String TEST_REGION = "testRegion";
+  private static final String GROUP1_REGION = "group1Region";
+  private static final String GROUP2_REGION = "group2Region";
+  private static final String GROUP1_GROUP2_REGION = "group1Group2Region";
+  private static final String TEST_GROUP1 = "testGroup1";
+  private static final String TEST_GROUP2 = "testGroup2";
 
   @Rule
   public transient GfshCommandRule gfsh = new GfshCommandRule();
@@ -60,18 +66,34 @@ public class DestroyMappingCommandDunitTest implements Serializable {
   public SerializableTestName testName = new SerializableTestName();
 
   private MemberVM locator;
-  private MemberVM server;
+  private MemberVM server1;
+  private MemberVM server2;
+  private MemberVM server3;
+  private MemberVM server4;
 
   @Before
   public void before() throws Exception {
 
     locator = startupRule.startLocatorVM(0);
-    server = startupRule.startServerVM(1, locator.getPort());
+    server1 = startupRule.startServerVM(1, locator.getPort());
+    server2 = startupRule.startServerVM(2, TEST_GROUP1, locator.getPort());
+    server3 = startupRule.startServerVM(3, TEST_GROUP2, locator.getPort());
+    server4 = startupRule.startServerVM(4, TEST_GROUP1 + "," + TEST_GROUP2, locator.getPort());
 
     gfsh.connectAndVerify(locator);
 
     gfsh.executeAndAssertThat("create region --name=" + TEST_REGION + " --type=PARTITION")
         .statusIsSuccess();
+    gfsh.executeAndAssertThat(
+        "create region --name=" + GROUP1_REGION + " --groups=" + TEST_GROUP1 + " --type=PARTITION")
+        .statusIsSuccess();
+    gfsh.executeAndAssertThat(
+        "create region --name=" + GROUP2_REGION + " --groups=" + TEST_GROUP2 + " --type=PARTITION")
+        .statusIsSuccess();
+    gfsh.executeAndAssertThat(
+        "create region --name=" + GROUP1_GROUP2_REGION + " --groups=" + TEST_GROUP1 + ","
+            + TEST_GROUP2 + " --type=PARTITION")
+        .statusIsSuccess();
   }
 
   private void setupAsyncMapping() {
@@ -93,6 +115,16 @@ public class DestroyMappingCommandDunitTest implements Serializable {
     gfsh.executeAndAssertThat(csb.toString()).statusIsSuccess();
   }
 
+  private void setupMappingWithServerGroup(String groups, String regionName, boolean isSync) {
+    CommandStringBuilder csb = new CommandStringBuilder(CREATE_MAPPING + " --groups=" + groups);
+    csb.addOption(REGION_NAME, regionName);
+    csb.addOption(DATA_SOURCE_NAME, "myDataSource");
+    csb.addOption(PDX_NAME, "myPdxClass");
+    csb.addOption(SYNCHRONOUS_NAME, Boolean.toString(isSync));
+
+    gfsh.executeAndAssertThat(csb.toString()).statusIsSuccess();
+  }
+
   @Test
   public void destroyRegionThatHasSynchronousMappingFails() {
     setupSynchronousMapping();
@@ -127,11 +159,11 @@ public class DestroyMappingCommandDunitTest implements Serializable {
       validateRegionAlteredInClusterConfig(false);
     });
 
-    server.invoke(() -> {
+    server1.invoke(() -> {
       InternalCache cache = ClusterStartupRule.getCache();
-      verifyMappingRemovedFromService(cache);
-      verifyRegionAltered(cache);
-      verifyQueueRemoved(cache);
+      assertThat(mappingRemovedFromService(cache, TEST_REGION)).isTrue();
+      verifyRegionAltered(cache, TEST_REGION, false);
+      assertThat(queueRemoved(cache, TEST_REGION)).isTrue();
     });
   }
 
@@ -149,11 +181,11 @@ public class DestroyMappingCommandDunitTest implements Serializable {
       validateRegionAlteredInClusterConfig(false);
     });
 
-    server.invoke(() -> {
+    server1.invoke(() -> {
       InternalCache cache = ClusterStartupRule.getCache();
-      verifyMappingRemovedFromService(cache);
-      verifyRegionAltered(cache);
-      verifyQueueRemoved(cache);
+      assertThat(mappingRemovedFromService(cache, TEST_REGION)).isTrue();
+      verifyRegionAltered(cache, TEST_REGION, false);
+      assertThat(queueRemoved(cache, TEST_REGION)).isTrue();
     });
   }
 
@@ -171,11 +203,80 @@ public class DestroyMappingCommandDunitTest implements Serializable {
       validateRegionAlteredInClusterConfig(true);
     });
 
-    server.invoke(() -> {
+    server1.invoke(() -> {
+      InternalCache cache = ClusterStartupRule.getCache();
+      assertThat(mappingRemovedFromService(cache, TEST_REGION)).isTrue();
+      verifyRegionAltered(cache, TEST_REGION, false);
+      assertThat(queueRemoved(cache, TEST_REGION)).isTrue();
+    });
+  }
+
+  @Test
+  public void destroysMappingForServerGroup() throws Exception {
+    setupMappingWithServerGroup(TEST_GROUP1, GROUP1_REGION, true);
+    CommandStringBuilder csb =
+        new CommandStringBuilder(DESTROY_MAPPING + " --groups=" + TEST_GROUP1);
+    csb.addOption(REGION_NAME, GROUP1_REGION);
+
+    gfsh.executeAndAssertThat(csb.toString()).statusIsSuccess();
+
+    locator.invoke(() -> {
+      assertThat(getRegionMappingFromClusterConfig()).isNull();
+      validateAsyncEventQueueRemovedFromClusterConfig();
+      validateRegionAlteredInClusterConfig(true);
+    });
+
+    // we have this region on server2 only
+    server2.invoke(() -> {
       InternalCache cache = ClusterStartupRule.getCache();
-      verifyMappingRemovedFromService(cache);
-      verifyRegionAltered(cache);
-      verifyQueueRemoved(cache);
+      assertThat(mappingRemovedFromService(cache, GROUP1_REGION)).isTrue();
+      verifyRegionAltered(cache, GROUP1_REGION, false);
+      assertThat(queueRemoved(cache, GROUP1_REGION)).isTrue();
+    });
+  }
+
+  @Test
+  public void destroysMappingForMultiServerGroup() throws Exception {
+    setupMappingWithServerGroup(TEST_GROUP1 + "," + TEST_GROUP2, GROUP1_GROUP2_REGION, true);
+    // Purposely destroy the mapping on one group only
+    CommandStringBuilder csb =
+        new CommandStringBuilder(DESTROY_MAPPING + " --groups=" + TEST_GROUP1);
+    csb.addOption(REGION_NAME, GROUP1_GROUP2_REGION);
+
+    gfsh.executeAndAssertThat(csb.toString()).statusIsSuccess();
+
+    locator.invoke(() -> {
+      assertThat(getRegionMappingFromClusterConfig()).isNull();
+      validateAsyncEventQueueRemovedFromClusterConfig();
+      validateRegionAlteredInClusterConfig(true);
+    });
+
+    // server1 never has the mapping
+    server1.invoke(() -> {
+      InternalCache cache = ClusterStartupRule.getCache();
+      assertThat(mappingRemovedFromService(cache, GROUP1_GROUP2_REGION)).isTrue();
+      verifyRegionAltered(cache, GROUP1_GROUP2_REGION, false);
+      assertThat(queueRemoved(cache, GROUP1_GROUP2_REGION)).isTrue();
+    });
+    // server2 and server4's mapping are destroyed
+    server2.invoke(() -> {
+      InternalCache cache = ClusterStartupRule.getCache();
+      assertThat(mappingRemovedFromService(cache, GROUP1_GROUP2_REGION)).isTrue();
+      verifyRegionAltered(cache, GROUP1_GROUP2_REGION, false);
+      assertThat(queueRemoved(cache, GROUP1_GROUP2_REGION)).isTrue();
+    });
+    server4.invoke(() -> {
+      InternalCache cache = ClusterStartupRule.getCache();
+      assertThat(mappingRemovedFromService(cache, GROUP1_GROUP2_REGION)).isTrue();
+      verifyRegionAltered(cache, GROUP1_GROUP2_REGION, false);
+      assertThat(queueRemoved(cache, GROUP1_GROUP2_REGION)).isTrue();
+    });
+    // server3 should still have the mapping
+    server3.invoke(() -> {
+      InternalCache cache = ClusterStartupRule.getCache();
+      assertThat(mappingRemovedFromService(cache, GROUP1_GROUP2_REGION)).isFalse();
+      verifyRegionAltered(cache, GROUP1_GROUP2_REGION, false);
+      assertThat(queueRemoved(cache, GROUP1_GROUP2_REGION)).isTrue();
     });
   }
 
@@ -193,11 +294,11 @@ public class DestroyMappingCommandDunitTest implements Serializable {
       validateRegionAlteredInClusterConfig(true);
     });
 
-    server.invoke(() -> {
+    server1.invoke(() -> {
       InternalCache cache = ClusterStartupRule.getCache();
-      verifyMappingRemovedFromService(cache);
-      verifyRegionAltered(cache);
-      verifyQueueRemoved(cache);
+      assertThat(mappingRemovedFromService(cache, TEST_REGION)).isTrue();
+      verifyRegionAltered(cache, TEST_REGION, false);
+      assertThat(queueRemoved(cache, TEST_REGION)).isTrue();
     });
   }
 
@@ -231,22 +332,28 @@ public class DestroyMappingCommandDunitTest implements Serializable {
     }
   }
 
-  private void verifyQueueRemoved(InternalCache cache) {
-    String queueName = CreateMappingCommand.createAsyncEventQueueName(TEST_REGION);
-    assertThat(cache.getAsyncEventQueue(queueName)).isNull();
+  private boolean queueRemoved(InternalCache cache, String regionName) {
+    String queueName = MappingCommandUtils.createAsyncEventQueueName(regionName);
+    return cache.getAsyncEventQueue(queueName) == null;
   }
 
-  private void verifyRegionAltered(InternalCache cache) {
+  private void verifyRegionAltered(InternalCache cache, String regionName, boolean exists) {
     Region<?, ?> region = cache.getRegion(TEST_REGION);
-    assertThat(region.getAttributes().getCacheLoader()).isNull();
-    assertThat(region.getAttributes().getCacheWriter()).isNull();
-    String queueName = CreateMappingCommand.createAsyncEventQueueName(TEST_REGION);
-    assertThat(region.getAttributes().getAsyncEventQueueIds()).doesNotContain(queueName);
+    String queueName = MappingCommandUtils.createAsyncEventQueueName(regionName);
+    if (exists) {
+      assertThat(region.getAttributes().getCacheLoader()).isNotNull();
+      assertThat(region.getAttributes().getCacheWriter()).isNotNull();
+      assertThat(region.getAttributes().getAsyncEventQueueIds()).contains(queueName);
+    } else {
+      assertThat(region.getAttributes().getCacheLoader()).isNull();
+      assertThat(region.getAttributes().getCacheWriter()).isNull();
+      assertThat(region.getAttributes().getAsyncEventQueueIds()).doesNotContain(queueName);
+    }
   }
 
-  private void verifyMappingRemovedFromService(InternalCache cache) {
+  private boolean mappingRemovedFromService(InternalCache cache, String regionName) {
     RegionMapping mapping =
-        cache.getService(JdbcConnectorService.class).getMappingForRegion(TEST_REGION);
-    assertThat(mapping).isNull();
+        cache.getService(JdbcConnectorService.class).getMappingForRegion(regionName);
+    return (mapping == null);
   }
 }
diff --git a/geode-connectors/src/distributedTest/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingCommandDUnitTest.java b/geode-connectors/src/distributedTest/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingCommandDUnitTest.java
index bc4ce9e..8b9564d 100644
--- a/geode-connectors/src/distributedTest/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingCommandDUnitTest.java
+++ b/geode-connectors/src/distributedTest/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingCommandDUnitTest.java
@@ -19,7 +19,6 @@ import static org.apache.geode.connectors.jdbc.internal.cli.ListMappingCommand.L
 import static org.assertj.core.api.Assertions.assertThat;
 
 import java.io.Serializable;
-import java.util.Properties;
 
 import org.junit.Rule;
 import org.junit.Test;
@@ -27,7 +26,6 @@ import org.junit.Test;
 import org.apache.geode.connectors.jdbc.internal.JdbcConnectorService;
 import org.apache.geode.connectors.jdbc.internal.RegionMappingExistsException;
 import org.apache.geode.connectors.jdbc.internal.configuration.RegionMapping;
-import org.apache.geode.distributed.internal.DistributionConfig;
 import org.apache.geode.internal.cache.InternalCache;
 import org.apache.geode.management.internal.cli.util.CommandStringBuilder;
 import org.apache.geode.test.dunit.rules.ClusterStartupRule;
@@ -49,19 +47,28 @@ public class ListMappingCommandDUnitTest implements Serializable {
   public SerializableTestName testName = new SerializableTestName();
 
   private MemberVM locator;
-  private MemberVM server;
+  private MemberVM server1;
+  private MemberVM server2;
+  private MemberVM server3;
+  private MemberVM server4;
 
   private String regionName = "testRegion";
+  private static final String GROUP1_REGION = "group1Region";
+  private static final String GROUP2_REGION = "group2Region";
+  private static final String GROUP1_GROUP2_REGION = "group1Group2Region";
+  private static final String TEST_GROUP1 = "testGroup1";
+  private static final String TEST_GROUP2 = "testGroup2";
 
   @Test
-  public void listsRegionMappingFromClusterConfiguration() throws Exception {
+  public void listsRegionMapping() throws Exception {
     locator = startupRule.startLocatorVM(0);
-    server = startupRule.startServerVM(1, locator.getPort());
+    server1 = startupRule.startServerVM(1, locator.getPort());
+
     gfsh.connectAndVerify(locator);
     gfsh.executeAndAssertThat("create region --name=" + regionName + " --type=REPLICATE")
         .statusIsSuccess();
 
-    String mapping = "create jdbc-mapping --region=testRegion --data-source=connection "
+    String mapping = "create jdbc-mapping --region=" + regionName + " --data-source=connection "
         + "--table=myTable --pdx-name=myPdxClass";
     gfsh.executeAndAssertThat(mapping).statusIsSuccess();
 
@@ -74,31 +81,157 @@ public class ListMappingCommandDUnitTest implements Serializable {
   }
 
   @Test
-  public void listsRegionMappingsFromMember() throws Exception {
-    Properties properties = new Properties();
-    properties.put(DistributionConfig.ENABLE_CLUSTER_CONFIGURATION_NAME, "false");
-
-    locator = startupRule.startLocatorVM(0, properties);
-    server = startupRule.startServerVM(1, locator.getPort());
+  public void reportsNoRegionMappingsFoundForServerGroup() throws Exception {
+    locator = startupRule.startLocatorVM(0);
+    server1 = startupRule.startServerVM(1, TEST_GROUP1, locator.getPort());
     gfsh.connectAndVerify(locator);
     gfsh.executeAndAssertThat("create region --name=" + regionName + " --type=REPLICATE")
         .statusIsSuccess();
 
-    server.invoke(() -> createNRegionMappings(3));
+    String mapping = "create jdbc-mapping --region=" + regionName + " --data-source=connection "
+        + "--table=myTable --pdx-name=myPdxClass";
+    gfsh.executeAndAssertThat(mapping).statusIsSuccess();
+
+    CommandStringBuilder csb = new CommandStringBuilder(LIST_MAPPING + " --groups=" + TEST_GROUP1);
+    CommandResultAssert commandResultAssert = gfsh.executeAndAssertThat(csb.toString());
+
+    commandResultAssert.statusIsError();
+    commandResultAssert.tableHasRowCount(LIST_OF_MAPPINGS, 0);
+
+    csb = new CommandStringBuilder(LIST_MAPPING);
+    commandResultAssert = gfsh.executeAndAssertThat(csb.toString());
+
+    commandResultAssert.statusIsSuccess();
+    commandResultAssert.tableHasRowCount(LIST_OF_MAPPINGS, 1);
+    commandResultAssert.tableHasColumnOnlyWithValues(LIST_OF_MAPPINGS, regionName);
+  }
+
+
+  @Test
+  public void listsRegionMappingForServerGroup() throws Exception {
+    locator = startupRule.startLocatorVM(0);
+    server1 = startupRule.startServerVM(1, TEST_GROUP1, locator.getPort());
+    gfsh.connectAndVerify(locator);
+    gfsh.executeAndAssertThat(
+        "create region --name=" + regionName + " --groups=" + TEST_GROUP1 + " --type=REPLICATE")
+        .statusIsSuccess();
+
+    String mapping =
+        "create jdbc-mapping --region=" + regionName + " --groups=" + TEST_GROUP1
+            + " --data-source=connection " + "--table=myTable --pdx-name=myPdxClass";
+    gfsh.executeAndAssertThat(mapping).statusIsSuccess();
+
+    CommandStringBuilder csbd = new CommandStringBuilder(
+        "describe jdbc-mapping --region=" + regionName + " --groups=" + TEST_GROUP1);
+    gfsh.executeAndAssertThat(csbd.toString());
 
-    CommandResultAssert commandResultAssert =
-        gfsh.executeAndAssertThat(LIST_MAPPING).statusIsSuccess();
+    CommandStringBuilder csb = new CommandStringBuilder(LIST_MAPPING + " --groups=" + TEST_GROUP1);
+    CommandResultAssert commandResultAssert = gfsh.executeAndAssertThat(csb.toString());
 
     commandResultAssert.statusIsSuccess();
-    commandResultAssert.tableHasRowCount(LIST_OF_MAPPINGS, 3);
-    commandResultAssert.tableHasColumnOnlyWithValues(LIST_OF_MAPPINGS, regionName + "-1",
-        regionName + "-2", regionName + "-3");
+    commandResultAssert.tableHasRowCount(LIST_OF_MAPPINGS, 1);
+    commandResultAssert.tableHasColumnOnlyWithValues(LIST_OF_MAPPINGS, regionName);
+
+    csb = new CommandStringBuilder(LIST_MAPPING);
+    commandResultAssert = gfsh.executeAndAssertThat(csb.toString());
+    commandResultAssert.statusIsError();
+    commandResultAssert.tableHasRowCount(LIST_OF_MAPPINGS, 0);
+
+
+  }
+
+  @Test
+  public void listsRegionMappingForMultiServerGroup() throws Exception {
+    locator = startupRule.startLocatorVM(0);
+    server1 = startupRule.startServerVM(1, locator.getPort());
+    server2 = startupRule.startServerVM(2, TEST_GROUP1, locator.getPort());
+    server3 = startupRule.startServerVM(3, TEST_GROUP2, locator.getPort());
+    server4 = startupRule.startServerVM(4, TEST_GROUP1 + "," + TEST_GROUP2, locator.getPort());
+
+    gfsh.connectAndVerify(locator);
+    // create 4 regions
+    gfsh.executeAndAssertThat(
+        "create region --name=" + regionName + " --type=REPLICATE")
+        .statusIsSuccess();
+    gfsh.executeAndAssertThat(
+        "create region --name=" + GROUP1_REGION + " --groups=" + TEST_GROUP1 + " --type=REPLICATE")
+        .statusIsSuccess();
+    gfsh.executeAndAssertThat(
+        "create region --name=" + GROUP2_REGION + " --groups=" + TEST_GROUP2 + " --type=REPLICATE")
+        .statusIsSuccess();
+    gfsh.executeAndAssertThat(
+        "create region --name=" + GROUP1_GROUP2_REGION + " --groups=" + TEST_GROUP1 + ","
+            + TEST_GROUP2 + " --type=REPLICATE")
+        .statusIsSuccess();
+
+    // create 4 mappings
+    String mapping =
+        "create jdbc-mapping --region=" + regionName + " --data-source=connection "
+            + "--table=myTable --pdx-name=myPdxClass";
+    gfsh.executeAndAssertThat(mapping).statusIsSuccess();
+    mapping =
+        "create jdbc-mapping --region=" + GROUP1_REGION + " --groups=" + TEST_GROUP1
+            + " --data-source=connection " + "--table=myTable --pdx-name=myPdxClass";
+    gfsh.executeAndAssertThat(mapping).statusIsSuccess();
+    mapping =
+        "create jdbc-mapping --region=" + GROUP2_REGION + " --groups=" + TEST_GROUP2
+            + " --data-source=connection " + "--table=myTable --pdx-name=myPdxClass";
+    gfsh.executeAndAssertThat(mapping).statusIsSuccess();
+    mapping =
+        "create jdbc-mapping --region=" + GROUP1_GROUP2_REGION + " --groups=" + TEST_GROUP1 + ","
+            + TEST_GROUP2 + " --data-source=connection " + "--table=myTable --pdx-name=myPdxClass";
+    gfsh.executeAndAssertThat(mapping).statusIsSuccess();
+
+    {
+      CommandStringBuilder csb =
+          new CommandStringBuilder(LIST_MAPPING);
+      CommandResultAssert commandResultAssert = gfsh.executeAndAssertThat(csb.toString());
+
+      commandResultAssert.statusIsSuccess();
+      commandResultAssert.tableHasRowCount(LIST_OF_MAPPINGS, 1);
+      commandResultAssert.tableHasColumnOnlyWithValues(LIST_OF_MAPPINGS, regionName);
+    }
+
+    {
+      CommandStringBuilder csb =
+          new CommandStringBuilder(LIST_MAPPING + " --groups=" + TEST_GROUP1);
+      CommandResultAssert commandResultAssert = gfsh.executeAndAssertThat(csb.toString());
+
+      commandResultAssert.statusIsSuccess();
+      commandResultAssert.tableHasRowCount(LIST_OF_MAPPINGS, 2);
+      commandResultAssert
+          .tableHasColumnOnlyWithValues(LIST_OF_MAPPINGS, GROUP1_REGION, GROUP1_GROUP2_REGION);
+    }
+
+    {
+      CommandStringBuilder csb =
+          new CommandStringBuilder(LIST_MAPPING + " --groups=" + TEST_GROUP2);
+      CommandResultAssert commandResultAssert = gfsh.executeAndAssertThat(csb.toString());
+
+      commandResultAssert.statusIsSuccess();
+      commandResultAssert.tableHasRowCount(LIST_OF_MAPPINGS, 2);
+      commandResultAssert
+          .tableHasColumnOnlyWithValues(LIST_OF_MAPPINGS, GROUP2_REGION, GROUP1_GROUP2_REGION);
+    }
+
+    {
+      CommandStringBuilder csb =
+          new CommandStringBuilder(LIST_MAPPING + " --groups=" + TEST_GROUP1 + "," + TEST_GROUP2);
+      CommandResultAssert commandResultAssert = gfsh.executeAndAssertThat(csb.toString());
+      commandResultAssert.statusIsSuccess();
+      // There will be 4 items: testRegion1 for testGroup1, testRegion2 for testGroup2,
+      // group1Group2Region for testGroup1, group1Group2Region for testGroup2
+      commandResultAssert.tableHasRowCount(LIST_OF_MAPPINGS, 4);
+      commandResultAssert
+          .tableHasColumnOnlyWithValues(LIST_OF_MAPPINGS, GROUP1_REGION, GROUP2_REGION,
+              GROUP1_GROUP2_REGION);
+    }
   }
 
   @Test
   public void reportsNoRegionMappingsFound() throws Exception {
     locator = startupRule.startLocatorVM(0);
-    server = startupRule.startServerVM(1, locator.getPort());
+    server1 = startupRule.startServerVM(1, locator.getPort());
     gfsh.connectAndVerify(locator);
     gfsh.executeAndAssertThat("create region --name=" + regionName + " --type=REPLICATE")
         .statusIsSuccess();
diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingCommand.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingCommand.java
index e6e1f8c..e68697f 100644
--- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingCommand.java
+++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingCommand.java
@@ -32,6 +32,7 @@ import org.apache.geode.connectors.jdbc.JdbcAsyncWriter;
 import org.apache.geode.connectors.jdbc.JdbcLoader;
 import org.apache.geode.connectors.jdbc.JdbcWriter;
 import org.apache.geode.connectors.jdbc.internal.configuration.RegionMapping;
+import org.apache.geode.connectors.util.internal.MappingCommandUtils;
 import org.apache.geode.connectors.util.internal.MappingConstants;
 import org.apache.geode.distributed.ConfigurationPersistenceService;
 import org.apache.geode.distributed.DistributedMember;
@@ -77,13 +78,6 @@ public class CreateMappingCommand extends SingleGfshCommand {
   private static final String CREATE_MAPPING__GROUPS_NAME__HELP =
       "The names of the server groups on which this mapping should be created.";
 
-  public static String createAsyncEventQueueName(String regionPath) {
-    if (regionPath.startsWith("/")) {
-      regionPath = regionPath.substring(1);
-    }
-    return "JDBC#" + regionPath.replace('/', '_');
-  }
-
   @CliCommand(value = CREATE_MAPPING, help = CREATE_MAPPING__HELP)
   @CliMetaData(relatedTopic = CliStrings.DEFAULT_TOPIC_GEODE)
   @ResourceOperation(resource = ResourcePermission.Resource.CLUSTER,
@@ -123,8 +117,9 @@ public class CreateMappingCommand extends SingleGfshCommand {
         groups = new String[] {ConfigurationPersistenceService.CLUSTER_CONFIG};
       }
       for (String group : groups) {
-        CacheConfig cacheConfig = configurationPersistenceService.getCacheConfig(group);
-        RegionConfig regionConfig = checkForRegion(regionName, cacheConfig);
+        CacheConfig cacheConfig =
+            MappingCommandUtils.getCacheConfig(configurationPersistenceService, group);
+        RegionConfig regionConfig = checkForRegion(regionName, cacheConfig, group);
         checkForExistingMapping(regionName, regionConfig);
         checkForCacheLoader(regionName, regionConfig);
         checkForCacheWriter(regionName, synchronous, regionConfig);
@@ -154,13 +149,9 @@ public class CreateMappingCommand extends SingleGfshCommand {
     return result;
   }
 
-  private RegionConfig checkForRegion(String regionName, CacheConfig cacheConfig)
+  private RegionConfig checkForRegion(String regionName, CacheConfig cacheConfig, String groupName)
       throws PreconditionException {
-    RegionConfig regionConfig = findRegionConfig(cacheConfig, regionName);
-    if (regionConfig == null) {
-      throw new PreconditionException("A region named " + regionName + " must already exist.");
-    }
-    return regionConfig;
+    return MappingCommandUtils.checkForRegion(regionName, cacheConfig, groupName);
   }
 
   private void checkForExistingMapping(String regionName, RegionConfig regionConfig)
@@ -202,7 +193,7 @@ public class CreateMappingCommand extends SingleGfshCommand {
   private void checkForAsyncQueue(String regionName, boolean synchronous, CacheConfig cacheConfig)
       throws PreconditionException {
     if (!synchronous) {
-      String queueName = createAsyncEventQueueName(regionName);
+      String queueName = MappingCommandUtils.createAsyncEventQueueName(regionName);
       AsyncEventQueue asyncEventQueue = cacheConfig.getAsyncEventQueues().stream()
           .filter(queue -> queue.getId().equals(queueName)).findFirst().orElse(null);
       if (asyncEventQueue != null) {
@@ -218,7 +209,7 @@ public class CreateMappingCommand extends SingleGfshCommand {
     RegionMapping regionMapping = (RegionMapping) arguments[0];
     boolean synchronous = (Boolean) arguments[1];
     String regionName = regionMapping.getRegionName();
-    String queueName = createAsyncEventQueueName(regionName);
+    String queueName = MappingCommandUtils.createAsyncEventQueueName(regionName);
     RegionConfig regionConfig = findRegionConfig(cacheConfig, regionName);
     if (regionConfig == null) {
       return false;
diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingFunction.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingFunction.java
index 3d2e2ed..6536a4e 100644
--- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingFunction.java
+++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingFunction.java
@@ -25,6 +25,7 @@ import org.apache.geode.connectors.jdbc.JdbcWriter;
 import org.apache.geode.connectors.jdbc.internal.JdbcConnectorService;
 import org.apache.geode.connectors.jdbc.internal.RegionMappingExistsException;
 import org.apache.geode.connectors.jdbc.internal.configuration.RegionMapping;
+import org.apache.geode.connectors.util.internal.MappingCommandUtils;
 import org.apache.geode.management.cli.CliFunction;
 import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
 
@@ -53,7 +54,7 @@ public class CreateMappingFunction extends CliFunction<Object[]> {
     Region<?, ?> region = verifyRegionExists(context.getCache(), regionName);
 
     // action
-    String queueName = CreateMappingCommand.createAsyncEventQueueName(regionName);
+    String queueName = MappingCommandUtils.createAsyncEventQueueName(regionName);
     if (!synchronous) {
       createAsyncEventQueue(context.getCache(), queueName,
           region.getAttributes().getDataPolicy().withPartitioning());
diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeMappingCommand.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeMappingCommand.java
index 62d071f..b4316d3 100644
--- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeMappingCommand.java
+++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeMappingCommand.java
@@ -32,10 +32,10 @@ import org.springframework.shell.core.annotation.CliOption;
 
 import org.apache.geode.annotations.Experimental;
 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.connectors.jdbc.internal.configuration.RegionMapping;
 import org.apache.geode.connectors.util.internal.DescribeMappingResult;
+import org.apache.geode.connectors.util.internal.MappingCommandUtils;
 import org.apache.geode.distributed.ConfigurationPersistenceService;
 import org.apache.geode.management.cli.CliMetaData;
 import org.apache.geode.management.cli.ConverterHint;
@@ -55,7 +55,7 @@ public class DescribeMappingCommand extends GfshCommand {
   private static final String DESCRIBE_MAPPING__REGION_NAME = REGION_NAME;
   private static final String DESCRIBE_MAPPING__REGION_NAME__HELP =
       "Region name of the JDBC mapping to be described.";
-  private static final String CREATE_MAPPING__GROUPS_NAME__HELP =
+  private static final String DESCRIBE_MAPPING__GROUPS_NAME__HELP =
       "Server Group(s) of the JDBC mapping to be described.";
 
   public static final String RESULT_SECTION_NAME = "MappingDescription";
@@ -68,7 +68,7 @@ public class DescribeMappingCommand extends GfshCommand {
       mandatory = true, help = DESCRIBE_MAPPING__REGION_NAME__HELP) String regionName,
       @CliOption(key = {CliStrings.GROUP, CliStrings.GROUPS},
           optionContext = ConverterHint.MEMBERGROUP,
-          help = CREATE_MAPPING__GROUPS_NAME__HELP) String[] groups) {
+          help = DESCRIBE_MAPPING__GROUPS_NAME__HELP) String[] groups) {
     if (regionName.startsWith("/")) {
       regionName = regionName.substring(1);
     }
@@ -102,38 +102,7 @@ public class DescribeMappingCommand extends GfshCommand {
 
   private CacheConfig getCacheConfig(ConfigurationPersistenceService configService, String group)
       throws PreconditionException {
-    CacheConfig result = configService.getCacheConfig(group);
-    if (result == null) {
-      throw new PreconditionException(
-          "Cache Configuration not found"
-              + ((group.equals(ConfigurationPersistenceService.CLUSTER_CONFIG)) ? "."
-                  : " for group " + group + "."));
-    }
-    return result;
-  }
-
-  private ArrayList<DescribeMappingResult> getMappingsFromRegionConfig(CacheConfig cacheConfig,
-      RegionConfig regionConfig, String group) {
-    CacheConfig.AsyncEventQueue asyncEventQueue = findAsyncEventQueue(cacheConfig, regionConfig);
-    ArrayList<DescribeMappingResult> results = new ArrayList<>();
-    for (CacheElement element : regionConfig.getCustomRegionElements()) {
-      if (element instanceof RegionMapping) {
-        results.add(buildDescribeMappingResult((RegionMapping) element, regionConfig.getName(),
-            asyncEventQueue == null, group));
-      }
-    }
-    return results;
-  }
-
-  private CacheConfig.AsyncEventQueue findAsyncEventQueue(CacheConfig cacheConfig,
-      RegionConfig regionConfig) {
-    for (CacheConfig.AsyncEventQueue queue : cacheConfig.getAsyncEventQueues()) {
-      if (queue.getId()
-          .equals(CreateMappingCommand.createAsyncEventQueueName(regionConfig.getName()))) {
-        return queue;
-      }
-    }
-    return null;
+    return MappingCommandUtils.getCacheConfig(configService, group);
   }
 
   private DescribeMappingResult buildDescribeMappingResult(RegionMapping regionMapping,
@@ -169,7 +138,19 @@ public class DescribeMappingCommand extends GfshCommand {
     return resultModel;
   }
 
-  public ConfigurationPersistenceService checkForClusterConfiguration()
+  private ArrayList<DescribeMappingResult> getMappingsFromRegionConfig(CacheConfig cacheConfig,
+      RegionConfig regionConfig, String group) {
+    ArrayList<DescribeMappingResult> results = new ArrayList<>();
+    for (RegionMapping mapping : MappingCommandUtils.getMappingsFromRegionConfig(cacheConfig,
+        regionConfig,
+        group)) {
+      results.add(buildDescribeMappingResult(mapping, regionConfig.getName(),
+          MappingCommandUtils.isMappingSynchronous(cacheConfig, regionConfig), group));
+    }
+    return results;
+  }
+
+  private ConfigurationPersistenceService checkForClusterConfiguration()
       throws PreconditionException {
     ConfigurationPersistenceService result = getConfigurationPersistenceService();
     if (result == null) {
@@ -180,19 +161,8 @@ public class DescribeMappingCommand extends GfshCommand {
 
   private RegionConfig checkForRegion(String regionName, CacheConfig cacheConfig, String groupName)
       throws PreconditionException {
-    RegionConfig regionConfig = findRegionConfig(cacheConfig, regionName);
-    if (regionConfig == null) {
-      String groupClause = "A region named " + regionName + " must already exist"
-          + (!groupName.equals(ConfigurationPersistenceService.CLUSTER_CONFIG)
-              ? " for group " + groupName + "." : ".");
-      throw new PreconditionException(groupClause);
-    }
-    return regionConfig;
-  }
 
-  private RegionConfig findRegionConfig(CacheConfig cacheConfig, String regionName) {
-    return cacheConfig.getRegions().stream()
-        .filter(region -> region.getName().equals(regionName)).findFirst().orElse(null);
+    return MappingCommandUtils.checkForRegion(regionName, cacheConfig, groupName);
   }
 
   @CliAvailabilityIndicator({DESCRIBE_MAPPING})
diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyMappingCommand.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyMappingCommand.java
index b44a3fd..ce098f8 100644
--- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyMappingCommand.java
+++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyMappingCommand.java
@@ -36,8 +36,10 @@ import org.apache.geode.cache.configuration.RegionConfig;
 import org.apache.geode.connectors.jdbc.JdbcLoader;
 import org.apache.geode.connectors.jdbc.JdbcWriter;
 import org.apache.geode.connectors.jdbc.internal.configuration.RegionMapping;
+import org.apache.geode.connectors.util.internal.MappingCommandUtils;
 import org.apache.geode.distributed.DistributedMember;
 import org.apache.geode.management.cli.CliMetaData;
+import org.apache.geode.management.cli.ConverterHint;
 import org.apache.geode.management.cli.SingleGfshCommand;
 import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
 import org.apache.geode.management.internal.cli.i18n.CliStrings;
@@ -53,19 +55,24 @@ public class DestroyMappingCommand extends SingleGfshCommand {
   private static final String DESTROY_MAPPING__REGION_NAME = REGION_NAME;
   private static final String DESTROY_MAPPING__REGION_NAME__HELP =
       "Name of the region whose JDBC mapping will be destroyed.";
+  private static final String DESTROY_MAPPING__GROUPS_NAME__HELP =
+      "Server Group(s) of the JDBC mapping to be destroyed.";
 
   @CliCommand(value = DESTROY_MAPPING, help = DESTROY_MAPPING__HELP)
   @CliMetaData(relatedTopic = CliStrings.DEFAULT_TOPIC_GEODE)
   @ResourceOperation(resource = ResourcePermission.Resource.CLUSTER,
       operation = ResourcePermission.Operation.MANAGE)
   public ResultModel destroyMapping(@CliOption(key = DESTROY_MAPPING__REGION_NAME, mandatory = true,
-      help = DESTROY_MAPPING__REGION_NAME__HELP) String regionName) {
+      help = DESTROY_MAPPING__REGION_NAME__HELP) String regionName,
+      @CliOption(key = {CliStrings.GROUP, CliStrings.GROUPS},
+          optionContext = ConverterHint.MEMBERGROUP,
+          help = DESTROY_MAPPING__GROUPS_NAME__HELP) String[] groups) {
     if (regionName.startsWith("/")) {
       regionName = regionName.substring(1);
     }
 
     // input
-    Set<DistributedMember> targetMembers = findMembersForRegion(regionName);
+    Set<DistributedMember> targetMembers = findMembers(groups, null);
 
     // action
     List<CliFunctionResult> results =
@@ -125,7 +132,7 @@ public class DestroyMappingCommand extends SingleGfshCommand {
   }
 
   private boolean removeJdbcAsyncEventQueueId(RegionAttributesType attributes, String regionName) {
-    String queueName = CreateMappingCommand.createAsyncEventQueueName(regionName);
+    String queueName = MappingCommandUtils.createAsyncEventQueueName(regionName);
     String queueIds = attributes.getAsyncEventQueueIds();
     if (queueIds == null) {
       return false;
@@ -141,7 +148,7 @@ public class DestroyMappingCommand extends SingleGfshCommand {
   }
 
   private boolean removeJdbcQueueFromCache(CacheConfig cacheConfig, String regionName) {
-    String queueName = CreateMappingCommand.createAsyncEventQueueName(regionName);
+    String queueName = MappingCommandUtils.createAsyncEventQueueName(regionName);
     Iterator<AsyncEventQueue> iterator = cacheConfig.getAsyncEventQueues().iterator();
     while (iterator.hasNext()) {
       AsyncEventQueue queue = iterator.next();
diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyMappingFunction.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyMappingFunction.java
index 8d6b63c..8f9a738 100644
--- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyMappingFunction.java
+++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyMappingFunction.java
@@ -27,6 +27,7 @@ import org.apache.geode.connectors.jdbc.JdbcLoader;
 import org.apache.geode.connectors.jdbc.JdbcWriter;
 import org.apache.geode.connectors.jdbc.internal.JdbcConnectorService;
 import org.apache.geode.connectors.jdbc.internal.configuration.RegionMapping;
+import org.apache.geode.connectors.util.internal.MappingCommandUtils;
 import org.apache.geode.management.cli.CliFunction;
 import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
 import org.apache.geode.management.internal.cli.functions.CliFunctionResult.StatusState;
@@ -54,7 +55,7 @@ public class DestroyMappingFunction extends CliFunction<String> {
   }
 
   private void cleanupRegionAndQueue(Cache cache, String regionName) {
-    String queueName = CreateMappingCommand.createAsyncEventQueueName(regionName);
+    String queueName = MappingCommandUtils.createAsyncEventQueueName(regionName);
 
     Region<?, ?> region = cache.getRegion(regionName);
     if (region != null) {
diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingCommand.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingCommand.java
index 437b8a4..80d1c1c 100644
--- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingCommand.java
+++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingCommand.java
@@ -15,18 +15,21 @@
 package org.apache.geode.connectors.jdbc.internal.cli;
 
 
-import java.util.Collection;
-import java.util.Set;
+import java.util.ArrayList;
 
 import org.springframework.shell.core.annotation.CliAvailabilityIndicator;
 import org.springframework.shell.core.annotation.CliCommand;
+import org.springframework.shell.core.annotation.CliOption;
 
 import org.apache.geode.annotations.Experimental;
+import org.apache.geode.cache.configuration.CacheConfig;
+import org.apache.geode.cache.configuration.RegionConfig;
 import org.apache.geode.connectors.jdbc.internal.configuration.RegionMapping;
-import org.apache.geode.distributed.DistributedMember;
+import org.apache.geode.connectors.util.internal.MappingCommandUtils;
+import org.apache.geode.distributed.ConfigurationPersistenceService;
 import org.apache.geode.management.cli.CliMetaData;
+import org.apache.geode.management.cli.ConverterHint;
 import org.apache.geode.management.cli.GfshCommand;
-import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
 import org.apache.geode.management.internal.cli.i18n.CliStrings;
 import org.apache.geode.management.internal.cli.result.model.ResultModel;
 import org.apache.geode.management.internal.cli.result.model.TabularResultModel;
@@ -41,23 +44,32 @@ public class ListMappingCommand extends GfshCommand {
   static final String LIST_OF_MAPPINGS = "List of JDBC mappings";
   static final String NO_MAPPINGS_FOUND = "No JDBC mappings found";
 
+  private static final String LIST_MAPPING__GROUPS_NAME__HELP =
+      "Server Group(s) of the JDBC mappings to list.";
+
   @CliCommand(value = LIST_MAPPING, help = LIST_MAPPING__HELP)
   @CliMetaData(relatedTopic = CliStrings.DEFAULT_TOPIC_GEODE)
   @ResourceOperation(resource = ResourcePermission.Resource.CLUSTER,
       operation = ResourcePermission.Operation.MANAGE)
-  public ResultModel listMapping() {
-    Collection<RegionMapping> mappings = null;
+  public ResultModel listMapping(@CliOption(key = {CliStrings.GROUP, CliStrings.GROUPS},
+      optionContext = ConverterHint.MEMBERGROUP,
+      help = LIST_MAPPING__GROUPS_NAME__HELP) String[] groups) {
+    ArrayList<RegionMapping> mappings = new ArrayList<>();
 
-    Set<DistributedMember> members = findMembers(null, null);
-    if (members.size() > 0) {
-      DistributedMember targetMember = members.iterator().next();
-      CliFunctionResult result =
-          executeFunctionAndGetFunctionResult(new ListMappingFunction(), null, targetMember);
-      if (result != null) {
-        mappings = (Collection<RegionMapping>) result.getResultObject();
+    try {
+      ConfigurationPersistenceService configService = checkForClusterConfiguration();
+      if (groups == null) {
+        groups = new String[] {ConfigurationPersistenceService.CLUSTER_CONFIG};
       }
-    } else {
-      return ResultModel.createError(CliStrings.NO_MEMBERS_FOUND_MESSAGE);
+      for (String group : groups) {
+        CacheConfig cacheConfig = getCacheConfig(configService, group);
+        for (RegionConfig regionConfig : cacheConfig.getRegions()) {
+          mappings.addAll(
+              MappingCommandUtils.getMappingsFromRegionConfig(cacheConfig, regionConfig, group));
+        }
+      }
+    } catch (PreconditionException ex) {
+      return ResultModel.createError(ex.getMessage());
     }
 
     // output
@@ -75,7 +87,7 @@ public class ListMappingCommand extends GfshCommand {
   /**
    * Returns true if any connections exist
    */
-  private boolean fillTabularResultData(Collection<RegionMapping> mappings,
+  private boolean fillTabularResultData(ArrayList<RegionMapping> mappings,
       TabularResultModel tableModel) {
     if (mappings == null) {
       return false;
@@ -86,6 +98,27 @@ public class ListMappingCommand extends GfshCommand {
     return !mappings.isEmpty();
   }
 
+  private CacheConfig getCacheConfig(ConfigurationPersistenceService configService, String group)
+      throws PreconditionException {
+    CacheConfig result = configService.getCacheConfig(group);
+    if (result == null) {
+      throw new PreconditionException(
+          "Cache Configuration not found"
+              + ((group.equals(ConfigurationPersistenceService.CLUSTER_CONFIG)) ? "."
+                  : " for group " + group + "."));
+    }
+    return result;
+  }
+
+  private ConfigurationPersistenceService checkForClusterConfiguration()
+      throws PreconditionException {
+    ConfigurationPersistenceService result = getConfigurationPersistenceService();
+    if (result == null) {
+      throw new PreconditionException("Cluster Configuration must be enabled.");
+    }
+    return result;
+  }
+
   @CliAvailabilityIndicator({LIST_MAPPING})
   public boolean commandAvailable() {
     return isOnlineCommandAvailable();
diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingFunction.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingFunction.java
deleted file mode 100644
index 5c39d9d..0000000
--- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingFunction.java
+++ /dev/null
@@ -1,29 +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.connectors.jdbc.internal.cli;
-
-import org.apache.geode.cache.execute.FunctionContext;
-import org.apache.geode.connectors.jdbc.internal.JdbcConnectorService;
-import org.apache.geode.management.cli.CliFunction;
-import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
-
-public class ListMappingFunction extends CliFunction<Void> {
-
-  @Override
-  public CliFunctionResult executeFunction(FunctionContext<Void> context) {
-    JdbcConnectorService service = FunctionContextArgumentProvider.getJdbcConnectorService(context);
-    return new CliFunctionResult(context.getMemberName(), service.getRegionMappings());
-  }
-}
diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/util/internal/MappingCommandUtils.java b/geode-connectors/src/main/java/org/apache/geode/connectors/util/internal/MappingCommandUtils.java
new file mode 100644
index 0000000..11fc468
--- /dev/null
+++ b/geode-connectors/src/main/java/org/apache/geode/connectors/util/internal/MappingCommandUtils.java
@@ -0,0 +1,94 @@
+/*
+ * 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.connectors.util.internal;
+
+import java.util.ArrayList;
+
+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.connectors.jdbc.internal.cli.PreconditionException;
+import org.apache.geode.connectors.jdbc.internal.configuration.RegionMapping;
+import org.apache.geode.distributed.ConfigurationPersistenceService;
+
+public class MappingCommandUtils {
+
+  public static CacheConfig getCacheConfig(ConfigurationPersistenceService configService,
+      String group)
+      throws PreconditionException {
+    CacheConfig result = configService.getCacheConfig(group);
+    if (result == null) {
+      throw new PreconditionException(
+          "Cache Configuration not found"
+              + ((group.equals(ConfigurationPersistenceService.CLUSTER_CONFIG)) ? "."
+                  : " for group " + group + "."));
+    }
+    return result;
+  }
+
+  public static RegionConfig checkForRegion(String regionName, CacheConfig cacheConfig,
+      String groupName)
+      throws PreconditionException {
+    RegionConfig regionConfig = findRegionConfig(cacheConfig, regionName);
+    if (regionConfig == null) {
+      String groupClause = "A region named " + regionName + " must already exist"
+          + (!groupName.equals(ConfigurationPersistenceService.CLUSTER_CONFIG)
+              ? " for group " + groupName + "." : ".");
+      throw new PreconditionException(groupClause);
+    }
+    return regionConfig;
+  }
+
+  private static RegionConfig findRegionConfig(CacheConfig cacheConfig, String regionName) {
+    return cacheConfig.getRegions().stream()
+        .filter(region -> region.getName().equals(regionName)).findFirst().orElse(null);
+  }
+
+  public static ArrayList<RegionMapping> getMappingsFromRegionConfig(CacheConfig cacheConfig,
+      RegionConfig regionConfig, String group) {
+    ArrayList<RegionMapping> results = new ArrayList<>();
+    for (CacheElement element : regionConfig.getCustomRegionElements()) {
+      if (element instanceof RegionMapping) {
+        ((RegionMapping) element).setRegionName(regionConfig.getName());
+        results.add((RegionMapping) element);
+      }
+    }
+    return results;
+  }
+
+  public static boolean isMappingSynchronous(CacheConfig cacheConfig, RegionConfig regionConfig) {
+    return findAsyncEventQueue(cacheConfig, regionConfig) == null;
+  }
+
+  public static CacheConfig.AsyncEventQueue findAsyncEventQueue(CacheConfig cacheConfig,
+      RegionConfig regionConfig) {
+    for (CacheConfig.AsyncEventQueue queue : cacheConfig.getAsyncEventQueues()) {
+      if (queue.getId()
+          .equals(createAsyncEventQueueName(regionConfig.getName()))) {
+        return queue;
+      }
+    }
+    return null;
+  }
+
+  public static String createAsyncEventQueueName(String regionPath) {
+    if (regionPath.startsWith("/")) {
+      regionPath = regionPath.substring(1);
+    }
+    return "JDBC#" + regionPath.replace('/', '_');
+  }
+
+}
diff --git a/geode-connectors/src/main/resources/org/apache/geode/internal/sanctioned-geode-connectors-serializables.txt b/geode-connectors/src/main/resources/org/apache/geode/internal/sanctioned-geode-connectors-serializables.txt
index ffe660c..22c4cf1 100755
--- a/geode-connectors/src/main/resources/org/apache/geode/internal/sanctioned-geode-connectors-serializables.txt
+++ b/geode-connectors/src/main/resources/org/apache/geode/internal/sanctioned-geode-connectors-serializables.txt
@@ -3,5 +3,4 @@ org/apache/geode/connectors/jdbc/internal/RegionMappingExistsException,false
 org/apache/geode/connectors/jdbc/internal/RegionMappingNotFoundException,false
 org/apache/geode/connectors/jdbc/internal/cli/CreateMappingFunction,false
 org/apache/geode/connectors/jdbc/internal/cli/DestroyMappingFunction,false
-org/apache/geode/connectors/jdbc/internal/cli/ListMappingFunction,false
 org/apache/geode/connectors/jdbc/internal/configuration/RegionMapping,false,catalog:java/lang/String,dataSourceName:java/lang/String,ids:java/lang/String,pdxName:java/lang/String,regionName:java/lang/String,schema:java/lang/String,tableName:java/lang/String
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingCommandTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingCommandTest.java
index d765a8e..4cf173b 100644
--- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingCommandTest.java
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingCommandTest.java
@@ -42,6 +42,7 @@ import org.apache.geode.cache.configuration.RegionAttributesType;
 import org.apache.geode.cache.configuration.RegionConfig;
 import org.apache.geode.connectors.jdbc.JdbcAsyncWriter;
 import org.apache.geode.connectors.jdbc.internal.configuration.RegionMapping;
+import org.apache.geode.connectors.util.internal.MappingCommandUtils;
 import org.apache.geode.distributed.ConfigurationPersistenceService;
 import org.apache.geode.distributed.internal.DistributionManager;
 import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
@@ -340,7 +341,7 @@ public class CreateMappingCommandTest {
     when(matchingRegion.getRegionAttributes()).thenReturn(loaderAttribute);
     List<AsyncEventQueue> asyncEventQueues = new ArrayList<>();
     AsyncEventQueue matchingQueue = mock(AsyncEventQueue.class);
-    String queueName = createRegionMappingCommand.createAsyncEventQueueName(regionName);
+    String queueName = MappingCommandUtils.createAsyncEventQueueName(regionName);
     when(matchingQueue.getId()).thenReturn(queueName);
     asyncEventQueues.add(matchingQueue);
     when(cacheConfig.getAsyncEventQueues()).thenReturn(asyncEventQueues);
@@ -369,7 +370,7 @@ public class CreateMappingCommandTest {
     when(matchingRegion.getRegionAttributes()).thenReturn(loaderAttribute);
     List<AsyncEventQueue> asyncEventQueues = new ArrayList<>();
     AsyncEventQueue matchingQueue = mock(AsyncEventQueue.class);
-    String queueName = createRegionMappingCommand.createAsyncEventQueueName(regionName);
+    String queueName = MappingCommandUtils.createAsyncEventQueueName(regionName);
     when(matchingQueue.getId()).thenReturn(queueName);
     asyncEventQueues.add(matchingQueue);
     when(cacheConfig.getAsyncEventQueues()).thenReturn(asyncEventQueues);
@@ -431,7 +432,7 @@ public class CreateMappingCommandTest {
     createRegionMappingCommand.updateConfigForGroup(null, cacheConfig, arguments);
 
     assertThat(queueList.size()).isEqualTo(1);
-    String queueName = CreateMappingCommand.createAsyncEventQueueName(regionName);
+    String queueName = MappingCommandUtils.createAsyncEventQueueName(regionName);
     AsyncEventQueue createdQueue = queueList.get(0);
     assertThat(createdQueue.getId()).isEqualTo(queueName);
     assertThat(createdQueue.isParallel()).isFalse();
@@ -486,7 +487,7 @@ public class CreateMappingCommandTest {
 
     ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);
     verify(matchingRegionAttributes).setAsyncEventQueueIds(argument.capture());
-    String queueName = CreateMappingCommand.createAsyncEventQueueName(regionName);
+    String queueName = MappingCommandUtils.createAsyncEventQueueName(regionName);
     assertThat(argument.getValue()).isEqualTo(queueName);
   }
 
@@ -505,7 +506,7 @@ public class CreateMappingCommandTest {
 
     ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);
     verify(matchingRegionAttributes).setAsyncEventQueueIds(argument.capture());
-    String queueName = CreateMappingCommand.createAsyncEventQueueName(regionName);
+    String queueName = MappingCommandUtils.createAsyncEventQueueName(regionName);
     assertThat(argument.getValue()).isEqualTo(queueName);
   }
 
@@ -524,7 +525,7 @@ public class CreateMappingCommandTest {
 
     ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);
     verify(matchingRegionAttributes).setAsyncEventQueueIds(argument.capture());
-    String queueName = CreateMappingCommand.createAsyncEventQueueName(regionName);
+    String queueName = MappingCommandUtils.createAsyncEventQueueName(regionName);
     assertThat(argument.getValue()).isEqualTo("q1,q2," + queueName);
   }
 
@@ -537,7 +538,7 @@ public class CreateMappingCommandTest {
     when(cacheConfig.getRegions()).thenReturn(list);
     List<CacheConfig.AsyncEventQueue> queueList = new ArrayList<>();
     when(cacheConfig.getAsyncEventQueues()).thenReturn(queueList);
-    String queueName = CreateMappingCommand.createAsyncEventQueueName(regionName);
+    String queueName = MappingCommandUtils.createAsyncEventQueueName(regionName);
     String existingQueues = "q1," + queueName + ",q2";
     when(matchingRegionAttributes.getAsyncEventQueueIds()).thenReturn(existingQueues);
 
@@ -595,20 +596,20 @@ public class CreateMappingCommandTest {
 
   @Test
   public void createAsyncEventQueueNameWithRegionPathReturnsQueueNameThatIsTheSameAsRegionWithNoSlash() {
-    String queueName1 = CreateMappingCommand.createAsyncEventQueueName("regionName");
-    String queueName2 = CreateMappingCommand.createAsyncEventQueueName("/regionName");
+    String queueName1 = MappingCommandUtils.createAsyncEventQueueName("regionName");
+    String queueName2 = MappingCommandUtils.createAsyncEventQueueName("/regionName");
     assertThat(queueName1).isEqualTo(queueName2);
   }
 
   @Test
   public void createAsyncEventQueueNameWithEmptyStringReturnsQueueName() {
-    String queueName = CreateMappingCommand.createAsyncEventQueueName("");
+    String queueName = MappingCommandUtils.createAsyncEventQueueName("");
     assertThat(queueName).isEqualTo("JDBC#");
   }
 
   @Test
   public void createAsyncEventQueueNameWithSubregionNameReturnsQueueNameWithNoSlashes() {
-    String queueName = CreateMappingCommand.createAsyncEventQueueName("/parent/child/grandchild");
+    String queueName = MappingCommandUtils.createAsyncEventQueueName("/parent/child/grandchild");
     assertThat(queueName).isEqualTo("JDBC#parent_child_grandchild");
   }
 
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingFunctionTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingFunctionTest.java
index e14ca8d..1015d22 100644
--- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingFunctionTest.java
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateMappingFunctionTest.java
@@ -44,6 +44,7 @@ import org.apache.geode.cache.execute.ResultSender;
 import org.apache.geode.connectors.jdbc.internal.JdbcConnectorService;
 import org.apache.geode.connectors.jdbc.internal.RegionMappingExistsException;
 import org.apache.geode.connectors.jdbc.internal.configuration.RegionMapping;
+import org.apache.geode.connectors.util.internal.MappingCommandUtils;
 import org.apache.geode.distributed.DistributedMember;
 import org.apache.geode.distributed.DistributedSystem;
 import org.apache.geode.internal.cache.InternalCache;
@@ -199,7 +200,7 @@ public class CreateMappingFunctionTest {
 
   @Test
   public void executeAlterRegionAsyncEventQueue() throws Exception {
-    String queueName = CreateMappingCommand.createAsyncEventQueueName(REGION_NAME);
+    String queueName = MappingCommandUtils.createAsyncEventQueueName(REGION_NAME);
     function.executeFunction(context);
 
     verify(service, times(1)).createRegionMapping(regionMapping);
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/org/apache/geode/connectors/util/DescribeMappingCommandTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeMappingCommandTest.java
similarity index 96%
rename from geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/org/apache/geode/connectors/util/DescribeMappingCommandTest.java
rename to geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeMappingCommandTest.java
index 3eed997..50d012c 100644
--- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/org/apache/geode/connectors/util/DescribeMappingCommandTest.java
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DescribeMappingCommandTest.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.connectors.jdbc.org.apache.geode.connectors.util;
+package org.apache.geode.connectors.jdbc.internal.cli;
 
 import static org.apache.geode.connectors.util.internal.MappingConstants.CATALOG_NAME;
 import static org.apache.geode.connectors.util.internal.MappingConstants.DATA_SOURCE_NAME;
@@ -36,9 +36,8 @@ import org.mockito.Mock;
 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.connectors.jdbc.internal.cli.CreateMappingCommand;
-import org.apache.geode.connectors.jdbc.internal.cli.DescribeMappingCommand;
 import org.apache.geode.connectors.jdbc.internal.configuration.RegionMapping;
+import org.apache.geode.connectors.util.internal.MappingCommandUtils;
 import org.apache.geode.distributed.ConfigurationPersistenceService;
 import org.apache.geode.test.junit.rules.GfshParserRule;
 
@@ -217,9 +216,9 @@ public class DescribeMappingCommandTest {
     when(regionConfig.getCustomRegionElements()).thenReturn(elements);
     when(clusterConfig.getAsyncEventQueues()).thenReturn(queueList);
     when(asyncEventQueue.getId())
-        .thenReturn(CreateMappingCommand.createAsyncEventQueueName("region2"))
-        .thenReturn(CreateMappingCommand.createAsyncEventQueueName("region1"))
-        .thenReturn(CreateMappingCommand.createAsyncEventQueueName("region3"));
+        .thenReturn(MappingCommandUtils.createAsyncEventQueueName("region2"))
+        .thenReturn(MappingCommandUtils.createAsyncEventQueueName("region1"))
+        .thenReturn(MappingCommandUtils.createAsyncEventQueueName("region3"));
 
     gfsh.executeAndAssertThat(command, COMMAND).statusIsSuccess()
         .containsOrderedOutput(DescribeMappingCommand.RESULT_SECTION_NAME + "0", REGION_NAME,
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyMappingCommandFunctionTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyMappingCommandFunctionTest.java
index a06833c..51f7616 100644
--- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyMappingCommandFunctionTest.java
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyMappingCommandFunctionTest.java
@@ -43,6 +43,7 @@ import org.apache.geode.connectors.jdbc.JdbcLoader;
 import org.apache.geode.connectors.jdbc.JdbcWriter;
 import org.apache.geode.connectors.jdbc.internal.JdbcConnectorService;
 import org.apache.geode.connectors.jdbc.internal.configuration.RegionMapping;
+import org.apache.geode.connectors.util.internal.MappingCommandUtils;
 import org.apache.geode.distributed.DistributedMember;
 import org.apache.geode.distributed.DistributedSystem;
 import org.apache.geode.internal.cache.InternalCache;
@@ -172,7 +173,7 @@ public class DestroyMappingCommandFunctionTest {
 
   @Test
   public void executeFunctionGivenARegionWithJdbcAsyncEventQueueRemovesTheQueueName() {
-    String queueName = CreateMappingCommand.createAsyncEventQueueName(regionName);
+    String queueName = MappingCommandUtils.createAsyncEventQueueName(regionName);
     when(regionAttributes.getAsyncEventQueueIds()).thenReturn(Collections.singleton(queueName));
     when(service.getMappingForRegion(eq(regionName))).thenReturn(mapping);
 
@@ -194,7 +195,7 @@ public class DestroyMappingCommandFunctionTest {
 
   @Test
   public void executeFunctionGivenAJdbcAsyncWriterQueueRemovesTheQueue() {
-    String queueName = CreateMappingCommand.createAsyncEventQueueName(regionName);
+    String queueName = MappingCommandUtils.createAsyncEventQueueName(regionName);
     InternalAsyncEventQueue myQueue = mock(InternalAsyncEventQueue.class);
     when(cache.getAsyncEventQueue(queueName)).thenReturn(myQueue);
 
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyMappingCommandTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyMappingCommandTest.java
index 59ad887..16c1771 100644
--- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyMappingCommandTest.java
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyMappingCommandTest.java
@@ -43,6 +43,7 @@ import org.apache.geode.cache.configuration.RegionAttributesType;
 import org.apache.geode.cache.configuration.RegionConfig;
 import org.apache.geode.connectors.jdbc.JdbcWriter;
 import org.apache.geode.connectors.jdbc.internal.configuration.RegionMapping;
+import org.apache.geode.connectors.util.internal.MappingCommandUtils;
 import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
 import org.apache.geode.internal.cache.InternalCache;
 import org.apache.geode.management.cli.Result;
@@ -76,7 +77,7 @@ public class DestroyMappingCommandTest {
 
     doReturn(results).when(destroyRegionMappingCommand).executeAndGetFunctionResult(any(), any(),
         any());
-    doReturn(members).when(destroyRegionMappingCommand).findMembersForRegion(regionName);
+    doReturn(members).when(destroyRegionMappingCommand).findMembers(null, null);
 
     cacheConfig = mock(CacheConfig.class);
 
@@ -88,10 +89,23 @@ public class DestroyMappingCommandTest {
   }
 
   @Test
+  public void destroyMappingGivenARegionNameForServerGroup() {
+    doReturn(members).when(destroyRegionMappingCommand).findMembers(new String[] {"testGroup1"},
+        null);
+    results.add(successFunctionResult);
+
+    ResultModel result =
+        destroyRegionMappingCommand.destroyMapping(regionName, new String[] {"testGroup1"});
+
+    assertThat(result.getStatus()).isSameAs(Result.Status.OK);
+    assertThat(result.getConfigObject()).isEqualTo(regionName);
+  }
+
+  @Test
   public void destroyMappingGivenARegionNameReturnsTheNameAsTheConfigObject() {
     results.add(successFunctionResult);
 
-    ResultModel result = destroyRegionMappingCommand.destroyMapping(regionName);
+    ResultModel result = destroyRegionMappingCommand.destroyMapping(regionName, null);
 
     assertThat(result.getStatus()).isSameAs(Result.Status.OK);
     assertThat(result.getConfigObject()).isEqualTo(regionName);
@@ -101,7 +115,7 @@ public class DestroyMappingCommandTest {
   public void destroyMappingGivenARegionPathReturnsTheNoSlashRegionNameAsTheConfigObject() {
     results.add(successFunctionResult);
 
-    ResultModel result = destroyRegionMappingCommand.destroyMapping("/" + regionName);
+    ResultModel result = destroyRegionMappingCommand.destroyMapping("/" + regionName, null);
 
     verify(destroyRegionMappingCommand, times(1)).executeAndGetFunctionResult(any(), eq(regionName),
         any());
@@ -165,7 +179,7 @@ public class DestroyMappingCommandTest {
     list.add(matchingRegion);
     when(cacheConfig.getRegions()).thenReturn(list);
     AsyncEventQueue queue = mock(AsyncEventQueue.class);
-    String queueName = CreateMappingCommand.createAsyncEventQueueName(regionName);
+    String queueName = MappingCommandUtils.createAsyncEventQueueName(regionName);
     when(queue.getId()).thenReturn(queueName);
     List<AsyncEventQueue> queueList = new ArrayList<>();
     queueList.add(queue);
@@ -207,7 +221,7 @@ public class DestroyMappingCommandTest {
     when(matchingRegion.getCustomRegionElements()).thenReturn(listCacheElements);
     list.add(matchingRegion);
     when(cacheConfig.getRegions()).thenReturn(list);
-    String queueName = CreateMappingCommand.createAsyncEventQueueName(regionName);
+    String queueName = MappingCommandUtils.createAsyncEventQueueName(regionName);
     when(matchingRegionAttributes.getAsyncEventQueueIds()).thenReturn(queueName);
 
     boolean modified =
@@ -226,7 +240,7 @@ public class DestroyMappingCommandTest {
     when(matchingRegion.getCustomRegionElements()).thenReturn(listCacheElements);
     list.add(matchingRegion);
     when(cacheConfig.getRegions()).thenReturn(list);
-    String queueName = CreateMappingCommand.createAsyncEventQueueName(regionName);
+    String queueName = MappingCommandUtils.createAsyncEventQueueName(regionName);
     when(matchingRegionAttributes.getAsyncEventQueueIds())
         .thenReturn(queueName + "1," + queueName + "," + queueName + "2");
 
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingCommandTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingCommandTest.java
index 190ccc9..6fc9507 100644
--- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingCommandTest.java
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingCommandTest.java
@@ -15,13 +15,17 @@
 package org.apache.geode.connectors.jdbc.internal.cli;
 
 import static java.util.stream.Collectors.toSet;
+import static org.apache.geode.connectors.jdbc.internal.cli.ListMappingCommand.NO_MAPPINGS_FOUND;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.List;
 import java.util.Set;
 import java.util.stream.Stream;
 
@@ -29,42 +33,79 @@ import org.junit.Before;
 import org.junit.ClassRule;
 import org.junit.Test;
 
+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.cache.execute.ResultCollector;
 import org.apache.geode.connectors.jdbc.internal.configuration.RegionMapping;
-import org.apache.geode.distributed.DistributedMember;
+import org.apache.geode.distributed.ConfigurationPersistenceService;
 import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
 import org.apache.geode.test.junit.rules.GfshParserRule;
 
 
 public class ListMappingCommandTest {
-  public static final String COMMAND = "list jdbc-mappings";
+  final String TEST_GROUP1 = "testGroup1";
+  public final String COMMAND = "list jdbc-mappings";
+  public final String COMMAND_FOR_GROUP = COMMAND + " --groups=" + TEST_GROUP1;
   private ListMappingCommand command;
+  private ConfigurationPersistenceService configService =
+      mock(ConfigurationPersistenceService.class);
+  private CacheConfig cacheConfig = mock(CacheConfig.class);
+  RegionConfig region1Config = mock(RegionConfig.class);
+  RegionConfig region2Config = mock(RegionConfig.class);
 
   @ClassRule
   public static GfshParserRule gfsh = new GfshParserRule();
 
   @Before
-  public void setUp() {
+  public void setUp() throws PreconditionException {
     command = spy(ListMappingCommand.class);
+    doReturn(configService).when(command).getConfigurationPersistenceService();
   }
 
   @Test
-  public void whenNoMemberExists() {
-    doReturn(Collections.emptySet()).when(command).findMembers(null, null);
+  public void whenNoCacheConfig() {
+    when(configService.getCacheConfig(ConfigurationPersistenceService.CLUSTER_CONFIG))
+        .thenReturn(null);
+    gfsh.executeAndAssertThat(command, COMMAND).statusIsError()
+        .containsOutput("Cache Configuration not found.");
+  }
 
+  @Test
+  public void whenClusterConfigDisabled() throws PreconditionException {
+    doReturn(null).when(command).getConfigurationPersistenceService();
     gfsh.executeAndAssertThat(command, COMMAND).statusIsError()
-        .containsOutput("No Members Found");
+        .containsOutput("Cluster Configuration must be enabled.");
   }
 
   @Test
-  public void whenMemberExists() {
-    doReturn(Collections.singleton(mock(DistributedMember.class))).when(command).findMembers(null,
-        null);
+  public void whenNoMappingExists() {
+    when(configService.getCacheConfig(eq(ConfigurationPersistenceService.CLUSTER_CONFIG)))
+        .thenReturn(cacheConfig);
+    gfsh.executeAndAssertThat(command, COMMAND).statusIsSuccess().containsOutput(NO_MAPPINGS_FOUND);
+  }
 
+  @Test
+  public void whenMappingExists() {
+    when(configService.getCacheConfig(eq(ConfigurationPersistenceService.CLUSTER_CONFIG)))
+        .thenReturn(cacheConfig);
+    List<RegionConfig> regions = new ArrayList<RegionConfig>();
+    regions.add(region1Config);
+    regions.add(region2Config);
+    when(region1Config.getName()).thenReturn("region1");
+    when(region2Config.getName()).thenReturn("region2");
+
+    when(cacheConfig.getRegions()).thenReturn(regions);
     RegionMapping mapping1 =
         new RegionMapping("region1", "class1", "table1", "name1", null, null, null);
     RegionMapping mapping2 =
         new RegionMapping("region2", "class2", "table2", "name2", null, null, null);
+    List<CacheElement> mappingList1 = new ArrayList<CacheElement>();
+    mappingList1.add(mapping1);
+    List<CacheElement> mappingList2 = new ArrayList<CacheElement>();
+    mappingList2.add(mapping2);
+    when(region1Config.getCustomRegionElements()).thenReturn(mappingList1);
+    when(region2Config.getCustomRegionElements()).thenReturn(mappingList2);
 
     ResultCollector rc = mock(ResultCollector.class);
     doReturn(rc).when(command).executeFunction(any(), any(), any(Set.class));
@@ -75,17 +116,34 @@ public class ListMappingCommandTest {
         "region2");
   }
 
-
   @Test
-  public void whenNoMappingsExist() {
-    doReturn(Collections.singleton(mock(DistributedMember.class))).when(command).findMembers(null,
-        null);
+  public void whenMappingExistsForServerGroup() {
+    when(configService.getCacheConfig(TEST_GROUP1)).thenReturn(cacheConfig);
+    List<RegionConfig> regions = new ArrayList<RegionConfig>();
+    regions.add(region1Config);
+    regions.add(region2Config);
+    when(region1Config.getName()).thenReturn("region1");
+    when(region2Config.getName()).thenReturn("region2");
+
+    when(cacheConfig.getRegions()).thenReturn(regions);
+    RegionMapping mapping1 =
+        new RegionMapping("region1", "class1", "table1", "name1", null, null, null);
+    RegionMapping mapping2 =
+        new RegionMapping("region2", "class2", "table2", "name2", null, null, null);
+    List<CacheElement> mappingList1 = new ArrayList<CacheElement>();
+    mappingList1.add(mapping1);
+    List<CacheElement> mappingList2 = new ArrayList<CacheElement>();
+    mappingList2.add(mapping2);
+    when(region1Config.getCustomRegionElements()).thenReturn(mappingList1);
+    when(region2Config.getCustomRegionElements()).thenReturn(mappingList2);
 
     ResultCollector rc = mock(ResultCollector.class);
     doReturn(rc).when(command).executeFunction(any(), any(), any(Set.class));
-    when(rc.getResult()).thenReturn(Collections.emptyList());
+    when(rc.getResult()).thenReturn(Collections.singletonList(new CliFunctionResult("server-1",
+        Stream.of(mapping1, mapping2).collect(toSet()), "success")));
 
-    gfsh.executeAndAssertThat(command, COMMAND).statusIsSuccess()
-        .containsOutput("No JDBC mappings found");
+    gfsh.executeAndAssertThat(command, COMMAND_FOR_GROUP).statusIsSuccess().containsOutput(
+        "region1",
+        "region2");
   }
 }
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingFunctionTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingFunctionTest.java
deleted file mode 100644
index 06f2da2..0000000
--- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/ListMappingFunctionTest.java
+++ /dev/null
@@ -1,166 +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.connectors.jdbc.internal.cli;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.io.Serializable;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.apache.commons.lang3.SerializationUtils;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-import org.apache.geode.cache.execute.FunctionContext;
-import org.apache.geode.cache.execute.ResultSender;
-import org.apache.geode.connectors.jdbc.internal.JdbcConnectorService;
-import org.apache.geode.connectors.jdbc.internal.configuration.RegionMapping;
-import org.apache.geode.distributed.DistributedMember;
-import org.apache.geode.distributed.DistributedSystem;
-import org.apache.geode.internal.cache.InternalCache;
-import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
-
-public class ListMappingFunctionTest {
-
-  private FunctionContext<Void> context;
-  private ResultSender<Object> resultSender;
-  private JdbcConnectorService service;
-
-  private RegionMapping regionMapping1;
-  private RegionMapping regionMapping2;
-  private RegionMapping regionMapping3;
-
-  private Set<RegionMapping> expected;
-
-  private ListMappingFunction function;
-
-  @Before
-  public void setUp() {
-    InternalCache cache = mock(InternalCache.class);
-    context = mock(FunctionContext.class);
-    DistributedMember member = mock(DistributedMember.class);
-    resultSender = mock(ResultSender.class);
-    service = mock(JdbcConnectorService.class);
-    DistributedSystem system = mock(DistributedSystem.class);
-
-    regionMapping1 = mock(RegionMapping.class);
-    regionMapping2 = mock(RegionMapping.class);
-    regionMapping3 = mock(RegionMapping.class);
-
-    expected = new HashSet<>();
-
-    when(context.getResultSender()).thenReturn(resultSender);
-    when(context.getCache()).thenReturn(cache);
-    when(cache.getDistributedSystem()).thenReturn(system);
-    when(system.getDistributedMember()).thenReturn(member);
-    when(cache.getService(eq(JdbcConnectorService.class))).thenReturn(service);
-    when(service.getRegionMappings()).thenReturn(expected);
-
-    function = new ListMappingFunction();
-  }
-
-  @Test
-  public void isHAReturnsFalse() {
-    assertThat(function.isHA()).isFalse();
-  }
-
-  @Test
-  public void getIdReturnsNameOfClass() {
-    assertThat(function.getId()).isEqualTo(function.getClass().getName());
-  }
-
-  @Test
-  public void serializes() {
-    Serializable original = function;
-
-    Object copy = SerializationUtils.clone(original);
-
-    assertThat(copy).isNotSameAs(original).isInstanceOf(ListMappingFunction.class);
-  }
-
-  @Test
-  public void getRegionMappingsReturnsMultiple() {
-    expected.add(regionMapping1);
-    expected.add(regionMapping2);
-    expected.add(regionMapping3);
-
-    Set<RegionMapping> actual =
-        (Set<RegionMapping>) function.executeFunction(context).getResultObject();
-
-    assertThat(actual).containsExactlyInAnyOrder(regionMapping1, regionMapping2, regionMapping3);
-  }
-
-  @Test
-  public void getRegionMappingsReturnsEmpty() {
-    Set<RegionMapping> actual =
-        (Set<RegionMapping>) function.executeFunction(context).getResultObject();
-
-    assertThat(actual).isEmpty();
-  }
-
-  @Test
-  public void executeReturnsResultWithAllRegionMappings() {
-    expected.add(regionMapping1);
-    expected.add(regionMapping2);
-    expected.add(regionMapping3);
-
-    function.execute(context);
-
-    ArgumentCaptor<CliFunctionResult> argument = ArgumentCaptor.forClass(CliFunctionResult.class);
-    verify(resultSender, times(1)).lastResult(argument.capture());
-    Set<RegionMapping> mappings =
-        (Set<RegionMapping>) argument.getValue().getResultObject();
-    assertThat(mappings).containsExactlyInAnyOrder(regionMapping1, regionMapping2, regionMapping3);
-  }
-
-  @Test
-  public void executeReturnsEmptyResultForNoRegionMappings() {
-    function.execute(context);
-
-    ArgumentCaptor<CliFunctionResult> argument = ArgumentCaptor.forClass(CliFunctionResult.class);
-    verify(resultSender, times(1)).lastResult(argument.capture());
-    assertThat((Set) argument.getValue().getResultObject()).isEmpty();
-  }
-
-  @Test
-  public void executeReturnsResultForExceptionWithoutMessage() {
-    when(service.getRegionMappings()).thenThrow(new NullPointerException());
-
-    function.execute(context);
-
-    ArgumentCaptor<CliFunctionResult> argument = ArgumentCaptor.forClass(CliFunctionResult.class);
-    verify(resultSender, times(1)).lastResult(argument.capture());
-    assertThat(argument.getValue().getStatusMessage())
-        .contains(NullPointerException.class.getName());
-  }
-
-  @Test
-  public void executeReturnsResultForExceptionWithMessage() {
-    when(service.getRegionMappings()).thenThrow(new IllegalArgumentException("some message"));
-
-    function.execute(context);
-
-    ArgumentCaptor<CliFunctionResult> argument = ArgumentCaptor.forClass(CliFunctionResult.class);
-    verify(resultSender, times(1)).lastResult(argument.capture());
-    assertThat(argument.getValue().getStatusMessage()).contains("some message");
-  }
-}
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/util/internal/MappingCommandUtilsTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/util/internal/MappingCommandUtilsTest.java
new file mode 100644
index 0000000..52ad042
--- /dev/null
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/util/internal/MappingCommandUtilsTest.java
@@ -0,0 +1,137 @@
+/*
+ * 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.connectors.util.internal;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.geode.cache.configuration.CacheConfig;
+import org.apache.geode.cache.configuration.CacheConfig.AsyncEventQueue;
+import org.apache.geode.cache.configuration.CacheElement;
+import org.apache.geode.cache.configuration.RegionConfig;
+import org.apache.geode.connectors.jdbc.internal.cli.PreconditionException;
+import org.apache.geode.connectors.jdbc.internal.configuration.RegionMapping;
+import org.apache.geode.distributed.ConfigurationPersistenceService;
+
+
+public class MappingCommandUtilsTest {
+
+  private final String TESTREGION = "testRegion";
+  private final String GROUPNAME = "cluster";
+
+  ConfigurationPersistenceService configurationPersistenceService;
+  CacheConfig cacheConfig;
+  RegionConfig regionConfig;
+
+  @Before
+  public void setup() {
+    configurationPersistenceService = mock(ConfigurationPersistenceService.class);
+    cacheConfig = mock(CacheConfig.class);
+    regionConfig = mock(RegionConfig.class);
+  }
+
+  @Test
+  public void getCacheConfigReturnsCorrectCacheConfig() throws PreconditionException {
+    when(configurationPersistenceService.getCacheConfig(GROUPNAME)).thenReturn(cacheConfig);
+    CacheConfig result =
+        MappingCommandUtils.getCacheConfig(configurationPersistenceService, GROUPNAME);
+
+    assertThat(result).isEqualTo(cacheConfig);
+  }
+
+  @Test
+  public void checkForRegionReturnsCorrectRegionConfig() throws PreconditionException {
+    List<RegionConfig> regionsList = new ArrayList<>();
+    regionsList.add(regionConfig);
+    when(regionConfig.getName()).thenReturn(TESTREGION);
+    when(cacheConfig.getRegions()).thenReturn(regionsList);
+
+    RegionConfig result = MappingCommandUtils.checkForRegion(TESTREGION, cacheConfig, GROUPNAME);
+
+    assertThat(result).isEqualTo(regionConfig);
+  }
+
+  @Test
+  public void getMappingsFromRegionConfigReturnsCorrectMappings() {
+
+    RegionMapping validRegionMapping = mock(RegionMapping.class);
+    CacheElement invalidRegionMapping = mock(CacheElement.class);
+    List<CacheElement> cacheElements = new ArrayList<>();
+    cacheElements.add((CacheElement) validRegionMapping);
+    cacheElements.add(invalidRegionMapping);
+
+    when(regionConfig.getCustomRegionElements()).thenReturn(cacheElements);
+
+    List<RegionMapping> results =
+        MappingCommandUtils.getMappingsFromRegionConfig(cacheConfig, regionConfig, GROUPNAME);
+
+    assertThat(results.size()).isEqualTo(1);
+    assertThat(results.get(0)).isEqualTo(validRegionMapping);
+  }
+
+  @Test
+  public void createAsyncEventQueueNameProducesCorrectName() {
+    String result = MappingCommandUtils.createAsyncEventQueueName(TESTREGION);
+
+    assertThat(result).isEqualTo("JDBC#testRegion");
+  }
+
+  @Test
+  public void testFindAsyncEventQueueReturnsCorrectObject() {
+    AsyncEventQueue asyncEventQueue = mock(AsyncEventQueue.class);
+    AsyncEventQueue wrongAsyncEventQueue = mock(AsyncEventQueue.class);
+    when(asyncEventQueue.getId())
+        .thenReturn(MappingCommandUtils.createAsyncEventQueueName(TESTREGION));
+    when(wrongAsyncEventQueue.getId()).thenReturn("Wrong Id");
+
+    List<AsyncEventQueue> asyncEventQueues = new ArrayList<>();
+    asyncEventQueues.add(asyncEventQueue);
+    asyncEventQueues.add(wrongAsyncEventQueue);
+
+    when(regionConfig.getName()).thenReturn(TESTREGION);
+    when(cacheConfig.getAsyncEventQueues()).thenReturn(asyncEventQueues);
+
+    AsyncEventQueue result = MappingCommandUtils.findAsyncEventQueue(cacheConfig, regionConfig);
+
+    assertThat(result).isEqualTo(asyncEventQueue);
+  }
+
+  @Test
+  public void testIsMappingAsyncReturnsCorrectValue() {
+    AsyncEventQueue asyncEventQueue = mock(AsyncEventQueue.class);
+    AsyncEventQueue wrongAsyncEventQueue = mock(AsyncEventQueue.class);
+    when(asyncEventQueue.getId())
+        .thenReturn(MappingCommandUtils.createAsyncEventQueueName(TESTREGION));
+    when(wrongAsyncEventQueue.getId()).thenReturn("Wrong Id");
+
+    List<AsyncEventQueue> asyncEventQueues = new ArrayList<>();
+    asyncEventQueues.add(asyncEventQueue);
+    asyncEventQueues.add(wrongAsyncEventQueue);
+
+    when(regionConfig.getName()).thenReturn(TESTREGION);
+    when(cacheConfig.getAsyncEventQueues()).thenReturn(asyncEventQueues);
+
+    boolean result = MappingCommandUtils.isMappingSynchronous(cacheConfig, regionConfig);
+
+    assertThat(result).isEqualTo(false);
+  }
+}