You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by kl...@apache.org on 2017/11/28 23:05:19 UTC

[geode] 01/02: GEODE-4018: implement destroy jdbc-connection command

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

klund pushed a commit to branch feature/GEODE-4018
in repository https://gitbox.apache.org/repos/asf/geode.git

commit 56866a184f5f4f8c499e6585eca6a4e02ec2c4b0
Author: Kirk Lund <kl...@apache.org>
AuthorDate: Tue Nov 28 12:00:34 2017 -0800

    GEODE-4018: implement destroy jdbc-connection command
---
 .../internal/InternalJdbcConnectorService.java     |  2 +
 .../jdbc/internal/JdbcConnectorService.java        |  6 ++
 .../jdbc/internal/cli/CreateConnectionCommand.java |  5 +-
 .../internal/cli/CreateConnectionFunction.java     | 32 ++++----
 .../internal/cli/DestroyConnectionCommand.java     | 88 ++++++++++++++++++++
 ...unction.java => DestroyConnectionFunction.java} | 55 +++++++------
 .../ExceptionHandler.java}                         | 27 +++---
 .../org.springframework.shell.core.CommandMarker   |  3 +-
 .../CreateConnectionCommandIntegrationTest.java    |  3 +-
 .../internal/cli/CreateConnectionFunctionTest.java | 44 +++++++---
 .../cli/DestroyConnectionCommandDUnitTest.java     | 96 ++++++++++++++++++++++
 ...> DestroyConnectionCommandIntegrationTest.java} | 43 +++++-----
 ...est.java => DestroyConnectionFunctionTest.java} | 56 +++++++++----
 13 files changed, 350 insertions(+), 110 deletions(-)

diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/InternalJdbcConnectorService.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/InternalJdbcConnectorService.java
index 882dd20..c7bdc16 100644
--- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/InternalJdbcConnectorService.java
+++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/InternalJdbcConnectorService.java
@@ -23,6 +23,8 @@ public interface InternalJdbcConnectorService extends Extension<Cache>, CacheSer
   void createConnectionConfig(ConnectionConfiguration config)
       throws ConnectionConfigExistsException;
 
+  void destroyConnectionConfig(String connectionName);
+
   void addOrUpdateRegionMapping(RegionMapping mapping);
 
   ConnectionConfiguration getConnectionConfig(String connectionName);
diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/JdbcConnectorService.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/JdbcConnectorService.java
index 222345f..de4759b 100644
--- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/JdbcConnectorService.java
+++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/JdbcConnectorService.java
@@ -53,6 +53,12 @@ public class JdbcConnectorService implements InternalJdbcConnectorService {
   }
 
   @Override
+  public void destroyConnectionConfig(String connectionName) {
+    registerAsExtension();
+    connectionsByName.remove(connectionName);
+  }
+
+  @Override
   public void addOrUpdateRegionMapping(RegionMapping mapping) {
     registerAsExtension();
     mappingsByRegion.put(mapping.getRegionName(), mapping);
diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionCommand.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionCommand.java
index a3f676f..f7f636a 100644
--- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionCommand.java
+++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionCommand.java
@@ -85,11 +85,12 @@ public class CreateConnectionCommand implements GfshCommand {
 
     Object resultCollectorResult = resultCollector.getResult();
 
-    List<CliFunctionResult> regionCreateResults = (List<CliFunctionResult>) resultCollectorResult;
+    List<CliFunctionResult> connectionCreateResults =
+        (List<CliFunctionResult>) resultCollectorResult;
 
     AtomicReference<XmlEntity> xmlEntity = new AtomicReference<>();
     TabularResultData tabularResultData = ResultBuilder.createTabularResultData();
-    for (CliFunctionResult regionCreateResult : regionCreateResults) {
+    for (CliFunctionResult regionCreateResult : connectionCreateResults) {
       boolean success = regionCreateResult.isSuccessful();
       tabularResultData.accumulate("Member", regionCreateResult.getMemberIdOrName());
       tabularResultData.accumulate("Status",
diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionFunction.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionFunction.java
index 6dd5e57..014c8ee 100644
--- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionFunction.java
+++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionFunction.java
@@ -27,16 +27,24 @@ import org.apache.geode.connectors.jdbc.internal.xml.JdbcConnectorServiceXmlPars
 import org.apache.geode.internal.InternalEntity;
 import org.apache.geode.internal.cache.InternalCache;
 import org.apache.geode.internal.cache.xmlcache.CacheXml;
-import org.apache.geode.internal.logging.LogService;
 import org.apache.geode.management.internal.cli.CliUtil;
 import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
 import org.apache.geode.management.internal.configuration.domain.XmlEntity;
 
 public class CreateConnectionFunction implements Function<ConnectionConfiguration>, InternalEntity {
-  private static final Logger logger = LogService.getLogger();
 
   private static final String ID = CreateConnectionFunction.class.getName();
 
+  private final transient ExceptionHandler exceptionHandler;
+
+  public CreateConnectionFunction() {
+    this(new ExceptionHandler());
+  }
+
+  private CreateConnectionFunction(ExceptionHandler exceptionHandler) {
+    this.exceptionHandler = exceptionHandler;
+  }
+
   @Override
   public boolean isHA() {
     return false;
@@ -55,36 +63,24 @@ public class CreateConnectionFunction implements Function<ConnectionConfiguratio
     String memberNameOrId =
         CliUtil.getMemberNameOrId(cache.getDistributedSystem().getDistributedMember());
 
-    ConnectionConfiguration configuration = context.getArguments();
+    ConnectionConfiguration connectionConfig = context.getArguments();
 
     try {
       InternalJdbcConnectorService service = cache.getService(InternalJdbcConnectorService.class);
-      service.createConnectionConfig(configuration);
+      service.createConnectionConfig(connectionConfig);
 
       XmlEntity xmlEntity = new XmlEntity(CacheXml.CACHE, JdbcConnectorServiceXmlGenerator.PREFIX,
           JdbcConnectorServiceXmlParser.NAMESPACE, ElementType.CONNECTION_SERVICE.getTypeName());
 
       resultSender.lastResult(new CliFunctionResult(memberNameOrId, xmlEntity,
-          "Created JDBC connection " + configuration.getName() + " on " + memberNameOrId));
+          "Created JDBC connection " + connectionConfig.getName() + " on " + memberNameOrId));
 
     } catch (Exception e) {
       String exceptionMsg = e.getMessage();
       if (exceptionMsg == null) {
         exceptionMsg = CliUtil.stackTraceAsString(e);
       }
-      resultSender.lastResult(handleException(memberNameOrId, exceptionMsg, e));
+      resultSender.lastResult(exceptionHandler.handleException(memberNameOrId, exceptionMsg, e));
     }
   }
-
-  private CliFunctionResult handleException(final String memberNameOrId, final String exceptionMsg,
-      final Exception e) {
-    if (e != null && logger.isDebugEnabled()) {
-      logger.debug(e.getMessage(), e);
-    }
-    if (exceptionMsg != null) {
-      return new CliFunctionResult(memberNameOrId, false, exceptionMsg);
-    }
-
-    return new CliFunctionResult(memberNameOrId);
-  }
 }
diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyConnectionCommand.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyConnectionCommand.java
new file mode 100644
index 0000000..c1ea43c
--- /dev/null
+++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyConnectionCommand.java
@@ -0,0 +1,88 @@
+/*
+ * 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 java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.springframework.shell.core.annotation.CliCommand;
+import org.springframework.shell.core.annotation.CliOption;
+
+import org.apache.geode.cache.execute.ResultCollector;
+import org.apache.geode.distributed.DistributedMember;
+import org.apache.geode.management.cli.CliMetaData;
+import org.apache.geode.management.cli.Result;
+import org.apache.geode.management.internal.cli.commands.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.ResultBuilder;
+import org.apache.geode.management.internal.cli.result.TabularResultData;
+import org.apache.geode.management.internal.configuration.domain.XmlEntity;
+import org.apache.geode.management.internal.security.ResourceOperation;
+import org.apache.geode.security.ResourcePermission;
+
+public class DestroyConnectionCommand implements GfshCommand {
+
+  static final String DESTROY_CONNECTION = "destroy jdbc-connection";
+  static final String DESTROY_CONNECTION__HELP = "Destroy JDBC connection for JDBC Connector.";
+  static final String DESTROY_CONNECTION__NAME = "name";
+  static final String DESTROY_CONNECTION__NAME__HELP =
+      "Name of the JDBC connection to be destroyed.";
+
+  private static final String ERROR_PREFIX = "ERROR: ";
+
+  @CliCommand(value = DESTROY_CONNECTION, help = DESTROY_CONNECTION__HELP)
+  @CliMetaData(relatedTopic = CliStrings.TOPIC_GEODE_REGION)
+  @ResourceOperation(resource = ResourcePermission.Resource.CLUSTER,
+      operation = ResourcePermission.Operation.MANAGE)
+  public Result destroyConnection(@CliOption(key = DESTROY_CONNECTION__NAME, mandatory = true,
+      help = DESTROY_CONNECTION__NAME__HELP) String name) {
+
+    Set<DistributedMember> membersToDestroyConnectionOn = getMembers(null, null);
+
+    ResultCollector<?, ?> resultCollector =
+        executeFunction(new DestroyConnectionFunction(), name, membersToDestroyConnectionOn);
+
+    Object resultCollectorResult = resultCollector.getResult();
+
+    List<CliFunctionResult> connectionDestroyResults =
+        (List<CliFunctionResult>) resultCollectorResult;
+
+    AtomicReference<XmlEntity> xmlEntity = new AtomicReference<>();
+    TabularResultData tabularResultData = ResultBuilder.createTabularResultData();
+    for (CliFunctionResult connectionDestroyResult : connectionDestroyResults) {
+      boolean success = connectionDestroyResult.isSuccessful();
+      tabularResultData.accumulate("Member", connectionDestroyResult.getMemberIdOrName());
+      tabularResultData.accumulate("Status",
+          (success ? "" : ERROR_PREFIX) + connectionDestroyResult.getMessage());
+
+      if (success) {
+        xmlEntity.set(connectionDestroyResult.getXmlEntity());
+      } else {
+        tabularResultData.setStatus(Result.Status.ERROR);
+      }
+    }
+
+    Result result = ResultBuilder.buildResult(tabularResultData);
+
+    if (xmlEntity.get() != null) {
+      persistClusterConfiguration(result,
+          () -> getSharedConfiguration().addXmlEntity(xmlEntity.get(), null));
+    }
+
+    return result;
+  }
+}
diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionFunction.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyConnectionFunction.java
similarity index 62%
copy from geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionFunction.java
copy to geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyConnectionFunction.java
index 6dd5e57..e0886cc 100644
--- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionFunction.java
+++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyConnectionFunction.java
@@ -14,12 +14,9 @@
  */
 package org.apache.geode.connectors.jdbc.internal.cli;
 
-import org.apache.logging.log4j.Logger;
-
 import org.apache.geode.cache.execute.Function;
 import org.apache.geode.cache.execute.FunctionContext;
 import org.apache.geode.cache.execute.ResultSender;
-import org.apache.geode.connectors.jdbc.internal.ConnectionConfiguration;
 import org.apache.geode.connectors.jdbc.internal.InternalJdbcConnectorService;
 import org.apache.geode.connectors.jdbc.internal.xml.ElementType;
 import org.apache.geode.connectors.jdbc.internal.xml.JdbcConnectorServiceXmlGenerator;
@@ -27,15 +24,24 @@ import org.apache.geode.connectors.jdbc.internal.xml.JdbcConnectorServiceXmlPars
 import org.apache.geode.internal.InternalEntity;
 import org.apache.geode.internal.cache.InternalCache;
 import org.apache.geode.internal.cache.xmlcache.CacheXml;
-import org.apache.geode.internal.logging.LogService;
 import org.apache.geode.management.internal.cli.CliUtil;
 import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
+import org.apache.geode.management.internal.cli.i18n.CliStrings;
 import org.apache.geode.management.internal.configuration.domain.XmlEntity;
 
-public class CreateConnectionFunction implements Function<ConnectionConfiguration>, InternalEntity {
-  private static final Logger logger = LogService.getLogger();
+public class DestroyConnectionFunction implements Function<String>, InternalEntity {
+
+  private static final String ID = DestroyConnectionFunction.class.getName();
 
-  private static final String ID = CreateConnectionFunction.class.getName();
+  private final transient ExceptionHandler exceptionHandler;
+
+  public DestroyConnectionFunction() {
+    this(new ExceptionHandler());
+  }
+
+  private DestroyConnectionFunction(ExceptionHandler exceptionHandler) {
+    this.exceptionHandler = exceptionHandler;
+  }
 
   @Override
   public boolean isHA() {
@@ -48,43 +54,38 @@ public class CreateConnectionFunction implements Function<ConnectionConfiguratio
   }
 
   @Override
-  public void execute(FunctionContext<ConnectionConfiguration> context) {
+  public void execute(FunctionContext<String> context) {
     ResultSender<Object> resultSender = context.getResultSender();
 
     InternalCache cache = (InternalCache) context.getCache();
     String memberNameOrId =
         CliUtil.getMemberNameOrId(cache.getDistributedSystem().getDistributedMember());
 
-    ConnectionConfiguration configuration = context.getArguments();
+    String connectionName = context.getArguments();
 
     try {
       InternalJdbcConnectorService service = cache.getService(InternalJdbcConnectorService.class);
-      service.createConnectionConfig(configuration);
 
-      XmlEntity xmlEntity = new XmlEntity(CacheXml.CACHE, JdbcConnectorServiceXmlGenerator.PREFIX,
-          JdbcConnectorServiceXmlParser.NAMESPACE, ElementType.CONNECTION_SERVICE.getTypeName());
+      if (service.getConnectionConfig(connectionName) == null) {
+        resultSender.lastResult(new CliFunctionResult(memberNameOrId, false,
+            CliStrings.format("Connection named \"{0}\" not found", connectionName)));
+
+      } else {
+        service.destroyConnectionConfig(connectionName);
 
-      resultSender.lastResult(new CliFunctionResult(memberNameOrId, xmlEntity,
-          "Created JDBC connection " + configuration.getName() + " on " + memberNameOrId));
+        XmlEntity xmlEntity = new XmlEntity(CacheXml.CACHE, JdbcConnectorServiceXmlGenerator.PREFIX,
+            JdbcConnectorServiceXmlParser.NAMESPACE, ElementType.CONNECTION_SERVICE.getTypeName());
+
+        resultSender.lastResult(new CliFunctionResult(memberNameOrId, xmlEntity,
+            "Destroyed JDBC connection " + connectionName + " on " + memberNameOrId));
+      }
 
     } catch (Exception e) {
       String exceptionMsg = e.getMessage();
       if (exceptionMsg == null) {
         exceptionMsg = CliUtil.stackTraceAsString(e);
       }
-      resultSender.lastResult(handleException(memberNameOrId, exceptionMsg, e));
+      resultSender.lastResult(exceptionHandler.handleException(memberNameOrId, exceptionMsg, e));
     }
   }
-
-  private CliFunctionResult handleException(final String memberNameOrId, final String exceptionMsg,
-      final Exception e) {
-    if (e != null && logger.isDebugEnabled()) {
-      logger.debug(e.getMessage(), e);
-    }
-    if (exceptionMsg != null) {
-      return new CliFunctionResult(memberNameOrId, false, exceptionMsg);
-    }
-
-    return new CliFunctionResult(memberNameOrId);
-  }
 }
diff --git a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/InternalJdbcConnectorService.java b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/ExceptionHandler.java
similarity index 53%
copy from geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/InternalJdbcConnectorService.java
copy to geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/ExceptionHandler.java
index 882dd20..8e44ec7 100644
--- a/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/InternalJdbcConnectorService.java
+++ b/geode-connectors/src/main/java/org/apache/geode/connectors/jdbc/internal/cli/ExceptionHandler.java
@@ -12,20 +12,25 @@
  * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
-package org.apache.geode.connectors.jdbc.internal;
+package org.apache.geode.connectors.jdbc.internal.cli;
 
-import org.apache.geode.cache.Cache;
-import org.apache.geode.internal.cache.CacheService;
-import org.apache.geode.internal.cache.extension.Extension;
+import org.apache.logging.log4j.Logger;
 
-public interface InternalJdbcConnectorService extends Extension<Cache>, CacheService {
+import org.apache.geode.internal.logging.LogService;
+import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
 
-  void createConnectionConfig(ConnectionConfiguration config)
-      throws ConnectionConfigExistsException;
+class ExceptionHandler {
+  private static final Logger logger = LogService.getLogger();
 
-  void addOrUpdateRegionMapping(RegionMapping mapping);
+  CliFunctionResult handleException(final String memberNameOrId, final String exceptionMsg,
+      final Exception e) {
+    if (e != null && logger.isDebugEnabled()) {
+      logger.debug(e.getMessage(), e);
+    }
+    if (exceptionMsg != null) {
+      return new CliFunctionResult(memberNameOrId, false, exceptionMsg);
+    }
 
-  ConnectionConfiguration getConnectionConfig(String connectionName);
-
-  RegionMapping getMappingForRegion(String regionName);
+    return new CliFunctionResult(memberNameOrId);
+  }
 }
diff --git a/geode-connectors/src/main/resources/META-INF/services/org.springframework.shell.core.CommandMarker b/geode-connectors/src/main/resources/META-INF/services/org.springframework.shell.core.CommandMarker
index 148dd48..5ec0430 100644
--- a/geode-connectors/src/main/resources/META-INF/services/org.springframework.shell.core.CommandMarker
+++ b/geode-connectors/src/main/resources/META-INF/services/org.springframework.shell.core.CommandMarker
@@ -15,4 +15,5 @@
 # limitations under the License.
 #
 # Lucene Extensions command
-org.apache.geode.connectors.jdbc.internal.cli.CreateConnectionCommand
\ No newline at end of file
+org.apache.geode.connectors.jdbc.internal.cli.CreateConnectionCommand
+org.apache.geode.connectors.jdbc.internal.cli.DestroyConnectionCommand
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionCommandIntegrationTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionCommandIntegrationTest.java
index e6ea066..3d8933f 100644
--- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionCommandIntegrationTest.java
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionCommandIntegrationTest.java
@@ -27,7 +27,6 @@ import org.apache.geode.connectors.jdbc.internal.ConnectionConfiguration;
 import org.apache.geode.connectors.jdbc.internal.InternalJdbcConnectorService;
 import org.apache.geode.internal.cache.InternalCache;
 import org.apache.geode.management.cli.Result;
-import org.apache.geode.management.internal.cli.result.CommandResult;
 import org.apache.geode.test.junit.categories.IntegrationTest;
 
 @Category(IntegrationTest.class)
@@ -85,7 +84,7 @@ public class CreateConnectionCommandIntegrationTest {
     ConnectionConfiguration connectionConfig = service.getConnectionConfig(name);
 
     Result result = createConnectionCommand.createConnection(name, url, user, password, params);
-    assertThat(((CommandResult) result).toJson()).contains("ERROR");
+    assertThat(result.getStatus()).isSameAs(Result.Status.ERROR);
 
     assertThat(service.getConnectionConfig(name)).isSameAs(connectionConfig);
   }
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionFunctionTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionFunctionTest.java
index 7452d88..e63d4ed 100644
--- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionFunctionTest.java
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionFunctionTest.java
@@ -16,23 +16,30 @@ 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.doThrow;
 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 org.apache.commons.lang.SerializationUtils;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
+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.ConnectionConfigBuilder;
+import org.apache.geode.connectors.jdbc.internal.ConnectionConfigExistsException;
 import org.apache.geode.connectors.jdbc.internal.ConnectionConfiguration;
 import org.apache.geode.connectors.jdbc.internal.InternalJdbcConnectorService;
 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;
 import org.apache.geode.test.junit.categories.UnitTest;
 
 @Category(UnitTest.class)
@@ -41,21 +48,18 @@ public class CreateConnectionFunctionTest {
   private CreateConnectionFunction function;
   private FunctionContext<ConnectionConfiguration> context;
   private ResultSender<Object> resultSender;
-  private InternalCache cache;
-  private DistributedSystem system;
-  private DistributedMember member;
   private ConnectionConfiguration configuration;
   private InternalJdbcConnectorService service;
 
   @Before
-  public void setup() {
+  public void setUp() {
     configuration = new ConnectionConfigBuilder().build();
 
     context = mock(FunctionContext.class);
     resultSender = mock(ResultSender.class);
-    cache = mock(InternalCache.class);
-    system = mock(DistributedSystem.class);
-    member = mock(DistributedMember.class);
+    InternalCache cache = mock(InternalCache.class);
+    DistributedSystem system = mock(DistributedSystem.class);
+    DistributedMember member = mock(DistributedMember.class);
     service = mock(InternalJdbcConnectorService.class);
 
     when(context.getResultSender()).thenReturn(resultSender);
@@ -69,19 +73,39 @@ public class CreateConnectionFunctionTest {
   }
 
   @Test
-  public void isHAIsFalse() throws Exception {
+  public void isHAReturnsFalse() throws Exception {
     assertThat(function.isHA()).isFalse();
   }
 
   @Test
-  public void getId() throws Exception {
+  public void getIdReturnsNameOfClass() throws Exception {
     assertThat(function.getId()).isEqualTo(function.getClass().getName());
   }
 
   @Test
-  public void execute() throws Exception {
+  public void executeCreatesConnectionIfConfigNotFound() throws Exception {
     function.execute(context);
     verify(service, times(1)).createConnectionConfig(configuration);
   }
 
+  @Test
+  public void executeReportsErrorIfConnectionConfigFound() throws Exception {
+    doThrow(ConnectionConfigExistsException.class).when(service)
+        .createConnectionConfig(eq(configuration));
+
+    function.execute(context);
+
+    ArgumentCaptor<CliFunctionResult> argument = ArgumentCaptor.forClass(CliFunctionResult.class);
+    verify(resultSender, times(1)).lastResult(argument.capture());
+    assertThat(argument.getValue().getErrorMessage())
+        .contains(ConnectionConfigExistsException.class.getName());
+  }
+
+  @Test
+  public void serializes() throws Exception {
+    Serializable original = function;
+    Object copy = SerializationUtils.clone(original);
+
+    assertThat(copy).isNotSameAs(original).isInstanceOf(CreateConnectionFunction.class);
+  }
 }
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyConnectionCommandDUnitTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyConnectionCommandDUnitTest.java
new file mode 100644
index 0000000..9c40ae3
--- /dev/null
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyConnectionCommandDUnitTest.java
@@ -0,0 +1,96 @@
+/*
+ * 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.apache.geode.connectors.jdbc.internal.cli.DestroyConnectionCommand.DESTROY_CONNECTION;
+import static org.apache.geode.connectors.jdbc.internal.cli.DestroyConnectionCommand.DESTROY_CONNECTION__NAME;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.Serializable;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.connectors.jdbc.internal.ConnectionConfigBuilder;
+import org.apache.geode.connectors.jdbc.internal.ConnectionConfiguration;
+import org.apache.geode.connectors.jdbc.internal.InternalJdbcConnectorService;
+import org.apache.geode.distributed.internal.InternalLocator;
+import org.apache.geode.internal.cache.InternalCache;
+import org.apache.geode.management.internal.cli.util.CommandStringBuilder;
+import org.apache.geode.test.dunit.rules.LocatorServerStartupRule;
+import org.apache.geode.test.dunit.rules.MemberVM;
+import org.apache.geode.test.junit.categories.DistributedTest;
+import org.apache.geode.test.junit.rules.GfshCommandRule;
+import org.apache.geode.test.junit.rules.serializable.SerializableTestName;
+
+@Category(DistributedTest.class)
+public class DestroyConnectionCommandDUnitTest implements Serializable {
+
+  @Rule
+  public transient GfshCommandRule gfsh = new GfshCommandRule();
+
+  @Rule
+  public LocatorServerStartupRule startupRule = new LocatorServerStartupRule();
+
+  @Rule
+  public SerializableTestName testName = new SerializableTestName();
+
+  private MemberVM locator;
+  private MemberVM server;
+
+  private String connectionName;
+
+  @Before
+  public void before() throws Exception {
+    connectionName = "name";
+
+    locator = startupRule.startLocatorVM(0);
+    server = startupRule.startServerVM(1, locator.getPort());
+
+    server.invoke(() -> createConnection());
+
+    gfsh.connectAndVerify(locator);
+  }
+
+  @Test
+  public void destroysConnection() throws Exception {
+    CommandStringBuilder csb = new CommandStringBuilder(DESTROY_CONNECTION);
+    csb.addOption(DESTROY_CONNECTION__NAME, "name");
+
+    gfsh.executeAndAssertThat(csb.toString()).statusIsSuccess();
+
+    locator.invoke(() -> {
+      String xml = InternalLocator.getLocator().getSharedConfiguration().getConfiguration("cluster")
+          .getCacheXmlContent();
+      assertThat(xml).contains("jdbc:connector-service");
+    });
+
+    server.invoke(() -> {
+      InternalCache cache = LocatorServerStartupRule.getCache();
+      ConnectionConfiguration config =
+          cache.getService(InternalJdbcConnectorService.class).getConnectionConfig("name");
+      assertThat(config).isNull();
+    });
+  }
+
+  private void createConnection() {
+    InternalCache cache = LocatorServerStartupRule.getCache();
+    InternalJdbcConnectorService service = cache.getService(InternalJdbcConnectorService.class);
+    service.createConnectionConfig(new ConnectionConfigBuilder().withName(connectionName).build());
+    assertThat(service.getConnectionConfig(connectionName)).isNotNull();
+  }
+}
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionCommandIntegrationTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyConnectionCommandIntegrationTest.java
similarity index 64%
copy from geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionCommandIntegrationTest.java
copy to geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyConnectionCommandIntegrationTest.java
index e6ea066..571ee8f 100644
--- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionCommandIntegrationTest.java
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyConnectionCommandIntegrationTest.java
@@ -23,18 +23,18 @@ import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
 import org.apache.geode.cache.CacheFactory;
+import org.apache.geode.connectors.jdbc.internal.ConnectionConfigBuilder;
 import org.apache.geode.connectors.jdbc.internal.ConnectionConfiguration;
 import org.apache.geode.connectors.jdbc.internal.InternalJdbcConnectorService;
 import org.apache.geode.internal.cache.InternalCache;
 import org.apache.geode.management.cli.Result;
-import org.apache.geode.management.internal.cli.result.CommandResult;
 import org.apache.geode.test.junit.categories.IntegrationTest;
 
 @Category(IntegrationTest.class)
-public class CreateConnectionCommandIntegrationTest {
+public class DestroyConnectionCommandIntegrationTest {
 
   private InternalCache cache;
-  private CreateConnectionCommand createConnectionCommand;
+  private DestroyConnectionCommand destroyConnectionCommand;
 
   private String name;
   private String url;
@@ -42,16 +42,21 @@ public class CreateConnectionCommandIntegrationTest {
   private String password;
   private String[] params;
 
+  private ConnectionConfiguration connectionConfig;
+
   @Before
   public void setup() throws Exception {
     cache = (InternalCache) new CacheFactory().set(ENABLE_CLUSTER_CONFIGURATION, "true").create();
-    createConnectionCommand = new CreateConnectionCommand();
+    destroyConnectionCommand = new DestroyConnectionCommand();
 
     name = "name";
     url = "url";
     user = "user";
     password = "password";
     params = new String[] {"param1:value1", "param2:value2"};
+
+    connectionConfig = new ConnectionConfigBuilder().withName(name).withUrl(url).withUser(user)
+        .withPassword(password).withParameters(params).build();
   }
 
   @After
@@ -60,33 +65,25 @@ public class CreateConnectionCommandIntegrationTest {
   }
 
   @Test
-  public void createsConnectionConfigurationInService() throws Exception {
-    Result result = createConnectionCommand.createConnection(name, url, user, password, params);
+  public void destroysNamedConnection() throws Exception {
+    InternalJdbcConnectorService service = cache.getService(InternalJdbcConnectorService.class);
+    service.createConnectionConfig(connectionConfig);
+    assertThat(service.getConnectionConfig(name)).isSameAs(connectionConfig);
 
+    Result result = destroyConnectionCommand.destroyConnection(name);
     assertThat(result.getStatus()).isSameAs(Result.Status.OK);
 
-    InternalJdbcConnectorService service = cache.getService(InternalJdbcConnectorService.class);
-    ConnectionConfiguration connectionConfig = service.getConnectionConfig(name);
-
-    assertThat(connectionConfig).isNotNull();
-    assertThat(connectionConfig.getName()).isEqualTo(name);
-    assertThat(connectionConfig.getUrl()).isEqualTo(url);
-    assertThat(connectionConfig.getUser()).isEqualTo(user);
-    assertThat(connectionConfig.getPassword()).isEqualTo(password);
-    assertThat(connectionConfig.getConnectionProperties()).containsEntry("param1", "value1")
-        .containsEntry("param2", "value2");
+    assertThat(service.getConnectionConfig(name)).isNull();
   }
 
   @Test
-  public void createsConnectionOnceOnly() throws Exception {
-    createConnectionCommand.createConnection(name, url, user, password, params);
+  public void returnsErrorIfNamedConnectionNotFound() throws Exception {
     InternalJdbcConnectorService service = cache.getService(InternalJdbcConnectorService.class);
+    assertThat(service.getConnectionConfig(name)).isNull();
 
-    ConnectionConfiguration connectionConfig = service.getConnectionConfig(name);
-
-    Result result = createConnectionCommand.createConnection(name, url, user, password, params);
-    assertThat(((CommandResult) result).toJson()).contains("ERROR");
+    Result result = destroyConnectionCommand.destroyConnection(name);
+    assertThat(result.getStatus()).isSameAs(Result.Status.ERROR);
 
-    assertThat(service.getConnectionConfig(name)).isSameAs(connectionConfig);
+    assertThat(service.getConnectionConfig(name)).isNull();
   }
 }
diff --git a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionFunctionTest.java b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyConnectionFunctionTest.java
similarity index 60%
copy from geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionFunctionTest.java
copy to geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyConnectionFunctionTest.java
index 7452d88..5402808 100644
--- a/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/CreateConnectionFunctionTest.java
+++ b/geode-connectors/src/test/java/org/apache/geode/connectors/jdbc/internal/cli/DestroyConnectionFunctionTest.java
@@ -21,9 +21,13 @@ import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import java.io.Serializable;
+
+import org.apache.commons.lang.SerializationUtils;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
+import org.mockito.ArgumentCaptor;
 
 import org.apache.geode.cache.execute.FunctionContext;
 import org.apache.geode.cache.execute.ResultSender;
@@ -33,55 +37,75 @@ import org.apache.geode.connectors.jdbc.internal.InternalJdbcConnectorService;
 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;
 import org.apache.geode.test.junit.categories.UnitTest;
 
 @Category(UnitTest.class)
-public class CreateConnectionFunctionTest {
+public class DestroyConnectionFunctionTest {
+
+  private static final String connectionName = "connectionName";
 
-  private CreateConnectionFunction function;
-  private FunctionContext<ConnectionConfiguration> context;
+  private DestroyConnectionFunction function;
+  private FunctionContext<String> context;
   private ResultSender<Object> resultSender;
-  private InternalCache cache;
-  private DistributedSystem system;
-  private DistributedMember member;
   private ConnectionConfiguration configuration;
   private InternalJdbcConnectorService service;
 
   @Before
-  public void setup() {
+  public void setUp() {
     configuration = new ConnectionConfigBuilder().build();
 
     context = mock(FunctionContext.class);
     resultSender = mock(ResultSender.class);
-    cache = mock(InternalCache.class);
-    system = mock(DistributedSystem.class);
-    member = mock(DistributedMember.class);
+    InternalCache cache = mock(InternalCache.class);
+    DistributedSystem system = mock(DistributedSystem.class);
+    DistributedMember member = mock(DistributedMember.class);
     service = mock(InternalJdbcConnectorService.class);
 
     when(context.getResultSender()).thenReturn(resultSender);
     when(context.getCache()).thenReturn(cache);
     when(cache.getDistributedSystem()).thenReturn(system);
     when(system.getDistributedMember()).thenReturn(member);
-    when(context.getArguments()).thenReturn(configuration);
+    when(context.getArguments()).thenReturn(connectionName);
     when(cache.getService(eq(InternalJdbcConnectorService.class))).thenReturn(service);
 
-    function = new CreateConnectionFunction();
+    function = new DestroyConnectionFunction();
   }
 
   @Test
-  public void isHAIsFalse() throws Exception {
+  public void isHAReturnsFalse() throws Exception {
     assertThat(function.isHA()).isFalse();
   }
 
   @Test
-  public void getId() throws Exception {
+  public void getIdReturnsNameOfClass() throws Exception {
     assertThat(function.getId()).isEqualTo(function.getClass().getName());
   }
 
   @Test
-  public void execute() throws Exception {
+  public void executeReportsErrorIfConnectionConfigNotFound() throws Exception {
+    function.execute(context);
+
+    ArgumentCaptor<CliFunctionResult> argument = ArgumentCaptor.forClass(CliFunctionResult.class);
+    verify(resultSender, times(1)).lastResult(argument.capture());
+    assertThat(argument.getValue().getErrorMessage())
+        .contains("Connection named \"" + connectionName + "\" not found");
+  }
+
+  @Test
+  public void executeDestroysIfConnectionConfigFound() throws Exception {
+    when(service.getConnectionConfig(eq(connectionName))).thenReturn(configuration);
+
     function.execute(context);
-    verify(service, times(1)).createConnectionConfig(configuration);
+
+    verify(service, times(1)).destroyConnectionConfig(eq(connectionName));
   }
 
+  @Test
+  public void serializes() throws Exception {
+    Serializable original = function;
+    Object copy = SerializationUtils.clone(original);
+
+    assertThat(copy).isNotSameAs(original).isInstanceOf(DestroyConnectionFunction.class);
+  }
 }

-- 
To stop receiving notification emails like this one, please contact
"commits@geode.apache.org" <co...@geode.apache.org>.