You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by jb...@apache.org on 2022/04/04 17:38:07 UTC

[geode] branch develop updated: GEODE-10127: Improve consistency of marshal/unmarshal calls. (#7463)

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

jbarrett 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 e5dd4cff54 GEODE-10127: Improve consistency of marshal/unmarshal calls. (#7463)
e5dd4cff54 is described below

commit e5dd4cff5486652f90caffeacee5eabe6cfbcfe7
Author: Jacob Barrett <jb...@pivotal.io>
AuthorDate: Mon Apr 4 10:37:59 2022 -0700

    GEODE-10127: Improve consistency of marshal/unmarshal calls. (#7463)
    
    * Refactor to common constructor.
    * Add unmarshal method in place of specialized constructor.
    * Replace toString with specialized marshal for using hostname-for-clients
      or bind-address.
---
 .../annotations/internal/MakeNotSerializable.java  |  34 ++
 .../geode/distributed/HostedLocatorsDUnitTest.java | 266 ++++--------
 .../internal/pulse/TestLocatorsDUnitTest.java      |  11 +-
 .../admin/internal/AdminDistributedSystemImpl.java |   4 +-
 .../admin/internal/DistributionLocatorImpl.java    |  12 +-
 .../java/org/apache/geode/distributed/Locator.java |   1 +
 .../internal/AbstractDistributionConfig.java       |   2 +-
 .../internal/InternalDistributedSystem.java        |   8 +-
 .../distributed/internal/InternalLocator.java      |  23 +-
 .../admin/remote/DistributionLocatorId.java        | 461 +++++++++------------
 .../admin/remote/RemoteTransportConfig.java        |  62 ++-
 .../sanctioned-geode-core-serializables.txt        |   2 +-
 .../admin/remote/DistributionLocatorIdTest.java    |  38 +-
 .../geode/internal/cache/wan/WANTestBase.java      |   2 +-
 .../wan/internal/AbstractRemoteGatewaySender.java  |   4 +-
 .../wan/internal/client/locator/LocatorHelper.java |   2 +-
 .../locator/LocatorMembershipListenerImpl.java     |   2 +-
 .../client/locator/WanLocatorDiscovererImpl.java   |  31 +-
 .../internal/client/locator/LocatorHelperTest.java |  21 +-
 .../locator/LocatorMembershipListenerTest.java     |   6 +-
 20 files changed, 409 insertions(+), 583 deletions(-)

diff --git a/geode-common/src/main/java/org/apache/geode/annotations/internal/MakeNotSerializable.java b/geode-common/src/main/java/org/apache/geode/annotations/internal/MakeNotSerializable.java
new file mode 100644
index 0000000000..69e85ed26f
--- /dev/null
+++ b/geode-common/src/main/java/org/apache/geode/annotations/internal/MakeNotSerializable.java
@@ -0,0 +1,34 @@
+/*
+ * 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.annotations.internal;
+
+import java.io.Serializable;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates types that should not be {@link Serializable} and should be refactored to avoid usage
+ * of {@link Serializable} in future major release.
+ */
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.SOURCE)
+public @interface MakeNotSerializable {
+
+  /** Optional description */
+  String value() default "";
+}
diff --git a/geode-core/src/distributedTest/java/org/apache/geode/distributed/HostedLocatorsDUnitTest.java b/geode-core/src/distributedTest/java/org/apache/geode/distributed/HostedLocatorsDUnitTest.java
index 2501c12863..c4abb4f83b 100644
--- a/geode-core/src/distributedTest/java/org/apache/geode/distributed/HostedLocatorsDUnitTest.java
+++ b/geode-core/src/distributedTest/java/org/apache/geode/distributed/HostedLocatorsDUnitTest.java
@@ -14,15 +14,14 @@
  */
 package org.apache.geode.distributed;
 
+import static java.util.concurrent.TimeUnit.MINUTES;
 import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS;
 import static org.apache.geode.internal.AvailablePortHelper.getRandomAvailableTCPPorts;
-import static org.apache.geode.test.dunit.Assert.assertEquals;
-import static org.apache.geode.test.dunit.Assert.assertFalse;
-import static org.apache.geode.test.dunit.Assert.assertNotNull;
-import static org.apache.geode.test.dunit.Assert.assertTrue;
 import static org.apache.geode.test.dunit.Host.getHost;
+import static org.assertj.core.api.Assertions.assertThat;
 
 import java.io.File;
+import java.net.UnknownHostException;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.Map;
@@ -38,11 +37,9 @@ import org.apache.geode.distributed.LocatorLauncher.Builder;
 import org.apache.geode.distributed.LocatorLauncher.LocatorState;
 import org.apache.geode.distributed.internal.ClusterDistributionManager;
 import org.apache.geode.distributed.internal.InternalDistributedSystem;
-import org.apache.geode.distributed.internal.InternalLocator;
 import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
 import org.apache.geode.internal.inet.LocalHostUtil;
 import org.apache.geode.internal.util.StopWatch;
-import org.apache.geode.test.dunit.Host;
 import org.apache.geode.test.dunit.SerializableCallable;
 import org.apache.geode.test.dunit.SerializableRunnable;
 import org.apache.geode.test.dunit.internal.JUnit4DistributedTestCase;
@@ -56,10 +53,9 @@ import org.apache.geode.test.junit.categories.ClientServerTest;
 @Category({ClientServerTest.class})
 public class HostedLocatorsDUnitTest extends JUnit4DistributedTestCase {
 
-  protected static final int TIMEOUT_MILLISECONDS = 5 * 60 * 1000; // 5 minutes
+  private static final int TIMEOUT_MILLISECONDS = (int) MINUTES.toMillis(5);
 
-  protected transient volatile int locatorPort;
-  protected transient volatile LocatorLauncher launcher;
+  private transient volatile LocatorLauncher launcher;
 
   @Override
   public final void postSetUp() throws Exception {
@@ -72,161 +68,46 @@ public class HostedLocatorsDUnitTest extends JUnit4DistributedTestCase {
   }
 
   private String getUniqueLocatorName() {
-    String uniqueLocatorName = Host.getHost(0).getHostName() + "_"
-        + getUniqueName();
-    return uniqueLocatorName;
+    return getHost(0).getHostName() + "_" + getUniqueName();
   }
 
   @Test
   public void testGetAllHostedLocators() throws Exception {
     final InternalDistributedSystem system = getSystem();
     final String dunitLocator = system.getConfig().getLocators();
-    assertNotNull(dunitLocator);
-    assertFalse(dunitLocator.isEmpty());
+    assertThat(dunitLocator).isNotEmpty();
 
     final int[] ports = getRandomAvailableTCPPorts(4);
 
     final String uniqueName = getUniqueLocatorName();
-    for (int i = 0; i < 4; i++) {
-      final int whichvm = i;
-      getHost(0).getVM(whichvm).invoke(new SerializableCallable() {
-        @Override
-        public Object call() throws Exception {
-          final String name = uniqueName + "-" + whichvm;
-          final File subdir = new File(name);
-          if (subdir.exists()) {
-            FileUtils.deleteRecursively(subdir);
-          }
-          subdir.mkdir();
-          assertTrue(subdir.exists() && subdir.isDirectory());
-
-          final Builder builder = new Builder().setMemberName(name).setPort(ports[whichvm])
-              .set(LOCATORS, dunitLocator)
-              .setRedirectOutput(true).setWorkingDirectory(name);
-
-          launcher = builder.build();
-          assertEquals(Status.ONLINE, launcher.start().getStatus());
-          waitForLocatorToStart(launcher, TIMEOUT_MILLISECONDS, 10, true);
-          return null;
-        }
-      });
-    }
-
-    final String host = LocalHostUtil.getLocalHost().getHostAddress();
-
-    final Set<String> locators = new HashSet<>();
-    locators.add(host + "["
-        + dunitLocator.substring(dunitLocator.indexOf("[") + 1, dunitLocator.indexOf("]")) + "]");
-    for (int port : ports) {
-      locators.add(host + "[" + port + "]");
-    }
-
-    // validation within non-locator
-    final ClusterDistributionManager dm =
-        (ClusterDistributionManager) system.getDistributionManager();
-
-    final Set<InternalDistributedMember> locatorIds = dm.getLocatorDistributionManagerIds();
-    assertEquals(5, locatorIds.size());
-
-    final Map<InternalDistributedMember, Collection<String>> hostedLocators =
-        dm.getAllHostedLocators();
-    assertTrue(!hostedLocators.isEmpty());
-    assertEquals(5, hostedLocators.size());
-
-    for (InternalDistributedMember member : hostedLocators.keySet()) {
-      assertEquals(1, hostedLocators.get(member).size());
-      final String hostedLocator = hostedLocators.get(member).iterator().next();
-      assertTrue(locators + " does not contain " + hostedLocator, locators.contains(hostedLocator));
+    for (int whichVm = 0; whichVm < 4; whichVm++) {
+      getHost(0).getVM(whichVm)
+          .invoke(new LocatorStarter(uniqueName, whichVm, ports, dunitLocator));
     }
 
-    // validate fix for #46324
-    for (int whichvm = 0; whichvm < 4; whichvm++) {
-      getHost(0).getVM(whichvm).invoke(new SerializableRunnable() {
-        @Override
-        public void run() {
-          final ClusterDistributionManager dm =
-              (ClusterDistributionManager) InternalDistributedSystem.getAnyInstance()
-                  .getDistributionManager();
-          final InternalDistributedMember self = dm.getDistributionManagerId();
-
-          final Set<InternalDistributedMember> locatorIds = dm.getLocatorDistributionManagerIds();
-          assertTrue(locatorIds.contains(self));
-
-          final Map<InternalDistributedMember, Collection<String>> hostedLocators =
-              dm.getAllHostedLocators();
-          assertTrue(
-              "hit bug #46324: " + hostedLocators + " is missing "
-                  + InternalLocator.getLocatorStrings() + " for " + self,
-              hostedLocators.containsKey(self));
-        }
-      });
-    }
-
-    // validation with locators
-    for (int whichvm = 0; whichvm < 4; whichvm++) {
-      getHost(0).getVM(whichvm).invoke(new SerializableRunnable() {
-        @Override
-        public void run() {
-          final ClusterDistributionManager dm =
-              (ClusterDistributionManager) InternalDistributedSystem.getAnyInstance()
-                  .getDistributionManager();
-
-          final Set<InternalDistributedMember> locatorIds = dm.getLocatorDistributionManagerIds();
-          assertEquals(5, locatorIds.size());
-
-          final Map<InternalDistributedMember, Collection<String>> hostedLocators =
-              dm.getAllHostedLocators();
-          assertTrue(!hostedLocators.isEmpty());
-          assertEquals(5, hostedLocators.size());
-
-          for (InternalDistributedMember member : hostedLocators.keySet()) {
-            assertEquals(1, hostedLocators.get(member).size());
-            final String hostedLocator = hostedLocators.get(member).iterator().next();
-            assertTrue(locators + " does not contain " + hostedLocator,
-                locators.contains(hostedLocator));
-          }
-        }
-      });
-    }
+    validateLocators(dunitLocator, ports, system);
   }
 
   @Test
   public void testGetAllHostedLocatorsUsingPortZero() throws Exception {
     final InternalDistributedSystem system = getSystem();
     final String dunitLocator = system.getConfig().getLocators();
-    assertNotNull(dunitLocator);
-    assertFalse(dunitLocator.isEmpty());
+    assertThat(dunitLocator).isNotEmpty();
 
     // This will eventually contain the ports used by locators
     final int[] ports = new int[] {0, 0, 0, 0};
 
     final String uniqueName = getUniqueLocatorName();
-    for (int i = 0; i < 4; i++) {
-      final int whichvm = i;
-      Integer port = (Integer) Host.getHost(0).getVM(whichvm).invoke(new SerializableCallable() {
-        @Override
-        public Object call() throws Exception {
-          final String name = uniqueName + "-" + whichvm;
-          final File subdir = new File(name);
-          if (subdir.exists()) {
-            FileUtils.deleteRecursively(subdir);
-          }
-          subdir.mkdir();
-          assertTrue(subdir.exists() && subdir.isDirectory());
-
-          final Builder builder = new Builder().setMemberName(name).setPort(ports[whichvm])
-              .set(LOCATORS, dunitLocator)
-              .setRedirectOutput(true).setWorkingDirectory(name);
-
-          launcher = builder.build();
-          assertEquals(Status.ONLINE, launcher.start().getStatus());
-          waitForLocatorToStart(launcher, TIMEOUT_MILLISECONDS, 10, true);
-          return launcher.getPort();
-        }
-      });
-      ports[i] = port;
+    for (int whichVm = 0; whichVm < 4; whichVm++) {
+      ports[whichVm] = (Integer) getHost(0).getVM(whichVm).invoke(
+          new LocatorStarter(uniqueName, whichVm, ports, dunitLocator));
     }
 
+    validateLocators(dunitLocator, ports, system);
+  }
+
+  private void validateLocators(final String dunitLocator, final int[] ports,
+      final InternalDistributedSystem system) throws UnknownHostException {
     final String host = LocalHostUtil.getLocalHost().getHostAddress();
 
     final Set<String> locators = new HashSet<>();
@@ -240,23 +121,10 @@ public class HostedLocatorsDUnitTest extends JUnit4DistributedTestCase {
     final ClusterDistributionManager dm =
         (ClusterDistributionManager) system.getDistributionManager();
 
-    final Set<InternalDistributedMember> locatorIds = dm.getLocatorDistributionManagerIds();
-    assertEquals(5, locatorIds.size());
+    validateWithLocators(dm, locators);
 
-    final Map<InternalDistributedMember, Collection<String>> hostedLocators =
-        dm.getAllHostedLocators();
-    assertTrue(!hostedLocators.isEmpty());
-    assertEquals(5, hostedLocators.size());
-
-    for (InternalDistributedMember member : hostedLocators.keySet()) {
-      assertEquals(1, hostedLocators.get(member).size());
-      final String hostedLocator = hostedLocators.get(member).iterator().next();
-      assertTrue(locators + " does not contain " + hostedLocator, locators.contains(hostedLocator));
-    }
-
-    // validate fix for #46324
-    for (int whichvm = 0; whichvm < 4; whichvm++) {
-      Host.getHost(0).getVM(whichvm).invoke(new SerializableRunnable() {
+    for (int whichVm = 0; whichVm < 4; whichVm++) {
+      getHost(0).getVM(whichVm).invoke(new SerializableRunnable() {
         @Override
         public void run() {
           final ClusterDistributionManager dm =
@@ -265,48 +133,47 @@ public class HostedLocatorsDUnitTest extends JUnit4DistributedTestCase {
           final InternalDistributedMember self = dm.getDistributionManagerId();
 
           final Set<InternalDistributedMember> locatorIds = dm.getLocatorDistributionManagerIds();
-          assertTrue(locatorIds.contains(self));
+          assertThat(locatorIds).contains(self);
 
           final Map<InternalDistributedMember, Collection<String>> hostedLocators =
               dm.getAllHostedLocators();
-          assertTrue(
-              "hit bug #46324: " + hostedLocators + " is missing "
-                  + InternalLocator.getLocatorStrings() + " for " + self,
-              hostedLocators.containsKey(self));
+          assertThat(hostedLocators).containsKey(self);
         }
       });
     }
 
-    // validation with locators
-    for (int whichvm = 0; whichvm < 4; whichvm++) {
-      Host.getHost(0).getVM(whichvm).invoke(new SerializableRunnable() {
+    for (int whichVm = 0; whichVm < 4; whichVm++) {
+      getHost(0).getVM(whichVm).invoke(new SerializableRunnable() {
         @Override
         public void run() {
-          final ClusterDistributionManager dm =
+          final ClusterDistributionManager dm1 =
               (ClusterDistributionManager) InternalDistributedSystem.getAnyInstance()
                   .getDistributionManager();
 
-          final Set<InternalDistributedMember> locatorIds = dm.getLocatorDistributionManagerIds();
-          assertEquals(5, locatorIds.size());
-
-          final Map<InternalDistributedMember, Collection<String>> hostedLocators =
-              dm.getAllHostedLocators();
-          assertTrue(!hostedLocators.isEmpty());
-          assertEquals(5, hostedLocators.size());
-
-          for (InternalDistributedMember member : hostedLocators.keySet()) {
-            assertEquals(1, hostedLocators.get(member).size());
-            final String hostedLocator = hostedLocators.get(member).iterator().next();
-            assertTrue(locators + " does not contain " + hostedLocator,
-                locators.contains(hostedLocator));
-          }
+          validateWithLocators(dm1, locators);
         }
       });
     }
   }
 
-  protected void waitForLocatorToStart(final LocatorLauncher launcher, int timeout, int interval,
-      boolean throwOnTimeout) throws Exception {
+  private void validateWithLocators(final ClusterDistributionManager dm,
+      final Set<String> locators) {
+    final Set<InternalDistributedMember> locatorIds = dm.getLocatorDistributionManagerIds();
+    assertThat(locatorIds).hasSize(5);
+
+    final Map<InternalDistributedMember, Collection<String>> hostedLocators =
+        dm.getAllHostedLocators();
+    assertThat(hostedLocators).hasSize(5);
+
+    for (InternalDistributedMember member : hostedLocators.keySet()) {
+      final Collection<String> hostedLocator = hostedLocators.get(member);
+      assertThat(hostedLocator).hasSize(1);
+      assertThat(locators).containsAll(hostedLocator);
+    }
+  }
+
+  private void waitForLocatorToStart(final LocatorLauncher launcher, int timeout, int interval)
+      throws Exception {
     assertEventuallyTrue("waiting for process to start: " + launcher.status(),
         () -> {
           try {
@@ -318,13 +185,48 @@ public class HostedLocatorsDUnitTest extends JUnit4DistributedTestCase {
         }, timeout, interval);
   }
 
-  protected static void assertEventuallyTrue(final String message, final Callable<Boolean> callable,
+  private static void assertEventuallyTrue(final String message, final Callable<Boolean> callable,
       final int timeout, final int interval) throws Exception {
     boolean done = false;
     for (StopWatch time = new StopWatch(true); !done && time.elapsedTimeMillis() < timeout; done =
         (callable.call())) {
       Thread.sleep(interval);
     }
-    assertTrue(message, done);
+    assertThat(done).as(message).isTrue();
+  }
+
+  private class LocatorStarter extends SerializableCallable<Object> {
+    private final String uniqueName;
+    private final int whichVm;
+    private final int[] ports;
+    private final String dunitLocator;
+
+    public LocatorStarter(final String uniqueName, final int whichVm, final int[] ports,
+        final String dunitLocator) {
+      this.uniqueName = uniqueName;
+      this.whichVm = whichVm;
+      this.ports = ports;
+      this.dunitLocator = dunitLocator;
+    }
+
+    @Override
+    public Object call() throws Exception {
+      final String name = uniqueName + "-" + whichVm;
+      final File directory = new File(name);
+      if (directory.exists()) {
+        FileUtils.deleteRecursively(directory);
+      }
+      directory.mkdir();
+      assertThat(directory).exists().isDirectory();
+
+      final Builder builder = new Builder().setMemberName(name).setPort(ports[whichVm])
+          .set(LOCATORS, dunitLocator)
+          .setRedirectOutput(true).setWorkingDirectory(name);
+
+      launcher = builder.build();
+      assertThat(launcher.start().getStatus()).isSameAs(Status.ONLINE);
+      waitForLocatorToStart(launcher, TIMEOUT_MILLISECONDS, 10);
+      return launcher.getPort();
+    }
   }
 }
diff --git a/geode-core/src/distributedTest/java/org/apache/geode/management/internal/pulse/TestLocatorsDUnitTest.java b/geode-core/src/distributedTest/java/org/apache/geode/management/internal/pulse/TestLocatorsDUnitTest.java
index 29d3f9ddd1..452cf3d206 100644
--- a/geode-core/src/distributedTest/java/org/apache/geode/management/internal/pulse/TestLocatorsDUnitTest.java
+++ b/geode-core/src/distributedTest/java/org/apache/geode/management/internal/pulse/TestLocatorsDUnitTest.java
@@ -65,7 +65,7 @@ public class TestLocatorsDUnitTest extends ManagementTestBase {
   }
 
   @Test
-  public void testLocatorsDUnitTest() throws Exception {
+  public void testLocatorsDUnitTest() {
     initManagement(false);
     int locatorCount =
         ((Number) managingNode.invoke(TestLocatorsDUnitTest::getNumOfLocatorFromMBean))
@@ -74,13 +74,4 @@ public class TestLocatorsDUnitTest extends ManagementTestBase {
     assertEquals(1, locatorCount);
 
   }
-
-  public void verifyStatistics() {
-
-  }
-
-  public void invokeOperations() {
-
-  }
-
 }
diff --git a/geode-core/src/main/java/org/apache/geode/admin/internal/AdminDistributedSystemImpl.java b/geode-core/src/main/java/org/apache/geode/admin/internal/AdminDistributedSystemImpl.java
index 7b9872faa6..6ea477d5ee 100755
--- a/geode-core/src/main/java/org/apache/geode/admin/internal/AdminDistributedSystemImpl.java
+++ b/geode-core/src/main/java/org/apache/geode/admin/internal/AdminDistributedSystemImpl.java
@@ -1321,11 +1321,11 @@ public class AdminDistributedSystemImpl implements org.apache.geode.admin.AdminD
     if (isMcastEnabled()) {
       String mcastId = getMcastAddress() + "["
           + getMcastPort() + "]";
-      locatorIds.add(new DistributionLocatorId(mcastId));
+      locatorIds.add(DistributionLocatorId.unmarshal(mcastId));
     }
     StringTokenizer st = new StringTokenizer(getLocators(), ",");
     while (st.hasMoreTokens()) {
-      locatorIds.add(new DistributionLocatorId(st.nextToken()));
+      locatorIds.add(DistributionLocatorId.unmarshal(st.nextToken()));
     }
 
     if (logger.isDebugEnabled()) {
diff --git a/geode-core/src/main/java/org/apache/geode/admin/internal/DistributionLocatorImpl.java b/geode-core/src/main/java/org/apache/geode/admin/internal/DistributionLocatorImpl.java
index 536af87357..b3d5e8eccd 100755
--- a/geode-core/src/main/java/org/apache/geode/admin/internal/DistributionLocatorImpl.java
+++ b/geode-core/src/main/java/org/apache/geode/admin/internal/DistributionLocatorImpl.java
@@ -15,6 +15,8 @@
 
 package org.apache.geode.admin.internal;
 
+import static org.apache.commons.lang3.StringUtils.isEmpty;
+
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.Collection;
@@ -206,7 +208,7 @@ public class DistributionLocatorImpl implements DistributionLocator, InternalMan
     for (Iterator<InternalDistributedMember> memberIter =
         hostedLocators.keySet().iterator(); memberIter.hasNext();) {
       for (final String s : hostedLocators.get(memberIter.next())) {
-        DistributionLocatorId locator = new DistributionLocatorId(s);
+        DistributionLocatorId locator = DistributionLocatorId.unmarshal(s);
         found = found || locator.getHostName().equals(host);
         if (!found && !host.contains(".")) {
           try {
@@ -221,8 +223,7 @@ public class DistributionLocatorImpl implements DistributionLocator, InternalMan
             // try config host as if it is an IP address instead of host name
           }
         }
-        if (locator.getBindAddress() != null && !locator.getBindAddress().isEmpty()
-            && bindAddress != null && !bindAddress.isEmpty()) {
+        if (!isEmpty(locator.getBindAddress()) && !isEmpty(bindAddress)) {
           found = found && locator.getBindAddress().equals(bindAddress);
         }
         found = found && locator.getPort() == port;
@@ -284,10 +285,11 @@ public class DistributionLocatorImpl implements DistributionLocator, InternalMan
     sb.append(" -port=");
     sb.append(getConfig().getPort());
     Properties props = config.getDistributedSystemProperties();
-    Enumeration en = props.propertyNames();
+    Enumeration<?> en = props.propertyNames();
     while (en.hasMoreElements()) {
       String pn = (String) en.nextElement();
-      sb.append(" -D" + GeodeGlossary.GEMFIRE_PREFIX + "" + pn + "=" + props.getProperty(pn));
+      sb.append(" -D" + GeodeGlossary.GEMFIRE_PREFIX + "").append(pn).append("=")
+          .append(props.getProperty(pn));
     }
 
     String bindAddress = getConfig().getBindAddress();
diff --git a/geode-core/src/main/java/org/apache/geode/distributed/Locator.java b/geode-core/src/main/java/org/apache/geode/distributed/Locator.java
index 0fc71fad1b..cab9ec64ea 100644
--- a/geode-core/src/main/java/org/apache/geode/distributed/Locator.java
+++ b/geode-core/src/main/java/org/apache/geode/distributed/Locator.java
@@ -279,6 +279,7 @@ public abstract class Locator {
    *
    * @deprecated as of 7.0 use {@link #getLocator} instead
    */
+  @Deprecated
   public static List<Locator> getLocators() {
     Locator result = getLocator();
     if (result == null) {
diff --git a/geode-core/src/main/java/org/apache/geode/distributed/internal/AbstractDistributionConfig.java b/geode-core/src/main/java/org/apache/geode/distributed/internal/AbstractDistributionConfig.java
index 1ae2005940..5a90772afa 100644
--- a/geode-core/src/main/java/org/apache/geode/distributed/internal/AbstractDistributionConfig.java
+++ b/geode-core/src/main/java/org/apache/geode/distributed/internal/AbstractDistributionConfig.java
@@ -294,7 +294,7 @@ public abstract class AbstractDistributionConfig extends AbstractConfig
   protected String checkStartLocator(String value) {
     if (value != null && value.trim().length() > 0) {
       // throws IllegalArgumentException if string is malformed
-      new DistributionLocatorId(value);
+      DistributionLocatorId.unmarshal(value);
     }
     return value;
   }
diff --git a/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalDistributedSystem.java b/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalDistributedSystem.java
index e75d6300be..f2c4c5df1d 100644
--- a/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalDistributedSystem.java
+++ b/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalDistributedSystem.java
@@ -874,9 +874,7 @@ public class InternalDistributedSystem extends DistributedSystem
       throws InterruptedException {
 
     final String locatorString = originalConfig.getStartLocator();
-    final boolean shouldStartLocator = locatorString.length() > 0;
-
-    if (!shouldStartLocator) {
+    if (locatorString.isEmpty()) {
       membershipLocator = membershipLocatorArg;
       return;
     }
@@ -893,7 +891,7 @@ public class InternalDistributedSystem extends DistributedSystem
         logger.info("Quorum check passed - allowing location services to start early");
       }
     }
-    DistributionLocatorId locId = new DistributionLocatorId(locatorString);
+    DistributionLocatorId locId = DistributionLocatorId.unmarshal(locatorString);
     try {
       startedLocator =
           InternalLocator.createLocator(locId.getPort(), NullLoggingSession.create(), null,
@@ -1755,7 +1753,7 @@ public class InternalDistributedSystem extends DistributedSystem
     while (st.hasMoreTokens()) {
       String l = st.nextToken();
       StringBuilder canonical = new StringBuilder();
-      DistributionLocatorId locId = new DistributionLocatorId(l);
+      DistributionLocatorId locId = DistributionLocatorId.unmarshal(l);
       String addr = locId.getBindAddress();
       if (addr != null && addr.trim().length() > 0) {
         canonical.append(addr);
diff --git a/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalLocator.java b/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalLocator.java
index 2f7ea53f51..201d3cbc70 100644
--- a/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalLocator.java
+++ b/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalLocator.java
@@ -14,12 +14,12 @@
  */
 package org.apache.geode.distributed.internal;
 
+import static java.util.Collections.singleton;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace;
 import static org.apache.geode.distributed.ConfigurationProperties.BIND_ADDRESS;
 import static org.apache.geode.distributed.ConfigurationProperties.CACHE_XML_FILE;
 import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS;
-import static org.apache.geode.internal.admin.remote.DistributionLocatorId.asDistributionLocatorIds;
 import static org.apache.geode.util.internal.GeodeGlossary.GEMFIRE_PREFIX;
 
 import java.io.File;
@@ -44,6 +44,7 @@ import java.util.function.Supplier;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.logging.log4j.Logger;
+import org.jetbrains.annotations.Nullable;
 
 import org.apache.geode.CancelException;
 import org.apache.geode.GemFireConfigException;
@@ -214,7 +215,7 @@ public class InternalLocator extends Locator implements ConnectListener, LogConf
   // restart at a time
   private final Object servicesRestartLock = new Object();
 
-  public static InternalLocator getLocator() {
+  public static @Nullable InternalLocator getLocator() {
     synchronized (locatorLock) {
       return locator;
     }
@@ -1342,20 +1343,18 @@ public class InternalLocator extends Locator implements ConnectListener, LogConf
    * Returns collection of locator strings representing every locator instance hosted by this
    * member.
    *
-   * @see #getLocators()
+   * @see #getLocator()
    */
-  public static Collection<String> getLocatorStrings() {
-    Collection<String> locatorStrings;
+  public static @Nullable Collection<String> getLocatorStrings() {
     try {
-      Collection<DistributionLocatorId> locatorIds = asDistributionLocatorIds(getLocators());
-      locatorStrings = DistributionLocatorId.asStrings(locatorIds);
+      final InternalLocator locator = getLocator();
+      if (null != locator) {
+        return singleton(
+            new DistributionLocatorId(LocalHostUtil.getLocalHost(), locator).marshal());
+      }
     } catch (UnknownHostException ignored) {
-      locatorStrings = null;
-    }
-    if (locatorStrings == null || locatorStrings.isEmpty()) {
-      return null;
     }
-    return locatorStrings;
+    return null;
   }
 
   private void startConfigurationPersistenceService() throws IOException {
diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/remote/DistributionLocatorId.java b/geode-core/src/main/java/org/apache/geode/internal/admin/remote/DistributionLocatorId.java
index b16fbcad73..84b5cbe978 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/admin/remote/DistributionLocatorId.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/admin/remote/DistributionLocatorId.java
@@ -15,17 +15,23 @@
 
 package org.apache.geode.internal.admin.remote;
 
+import static java.lang.String.format;
+import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
+import static org.apache.commons.lang3.ObjectUtils.getIfNull;
+import static org.apache.commons.lang3.StringUtils.isEmpty;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
 import java.util.Objects;
 
 import org.apache.commons.lang3.StringUtils;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import org.apache.geode.InternalGemFireException;
-import org.apache.geode.distributed.Locator;
+import org.apache.geode.annotations.internal.MakeNotSerializable;
 import org.apache.geode.distributed.internal.DistributionConfig;
 import org.apache.geode.distributed.internal.InternalLocator;
 import org.apache.geode.distributed.internal.tcpserver.HostAndPort;
@@ -38,109 +44,85 @@ import org.apache.geode.internal.net.SocketCreator;
  * Also identifies member name of the distribution locator. This is used to improve
  * locator discovery logic.
  * If member name is set to null, then design base logic will be used.
- *
+ * Serializable for RemoteLocatorJoinRequest and ServerLocationRequest.
  */
+@MakeNotSerializable
 public class DistributionLocatorId implements java.io.Serializable {
   private static final long serialVersionUID = 6587390186971937865L;
 
-  private InetAddress host;
+  private final InetAddress host;
   private final int port;
-  private final String bindAddress;
-  private transient SSLConfig sslConfig;
-  // the following two fields are not used but are retained for backward compatibility
-  // as this class is Serializable and is used in WAN locator information exchange
-  private final boolean peerLocator = true;
-  private final boolean serverLocator = true;
-  private String hostnameForClients;
+  private final @NotNull String bindAddress;
+  /**
+   * Serialization: Since this is {@code transient} it must be initialized after deserialization,
+   * thus it can't be {@code final}.
+   */
+  private transient @NotNull SSLConfig sslConfig;
+  private final String hostnameForClients;
   private String hostname;
-  // added due to improvement for cloud native environment
-  private String membername;
+  /**
+   * Serialization: Not include in some older versions and may be {@code null} abd must be
+   * initialized after deserialization, thus it can't be {@code final}.
+   */
+  private @NotNull String memberName;
   private final long timestamp;
 
-
   /**
    * Constructs a DistributionLocatorId with the given host and port.
    * This constructor is used for design base behavior.
-   *
    */
-  public DistributionLocatorId(InetAddress host, int port, String bindAddress,
-      SSLConfig sslConfig) {
-    this.host = host;
-    this.port = port;
-    this.bindAddress = validateBindAddress(bindAddress);
-    this.sslConfig = validateSSLConfig(sslConfig);
-    membername = DistributionConfig.DEFAULT_NAME;
-    timestamp = 0;
-
-  }
-
-  public DistributionLocatorId(int port, String bindAddress) {
-    this(port, bindAddress, null);
-  }
-
-  public DistributionLocatorId(int port, String bindAddress, String hostnameForClients) {
-    this(port, bindAddress, hostnameForClients, DistributionConfig.DEFAULT_NAME);
+  public DistributionLocatorId(final @NotNull InetAddress host, final int port,
+      final @Nullable String bindAddress, final @Nullable SSLConfig sslConfig) {
+    this(host, null, port, bindAddress, sslConfig, null, null);
   }
 
   /**
    * Constructs a DistributionLocatorId with the given port and member name.
    * The host will be set to the local host.
-   *
    */
-  public DistributionLocatorId(int port, String bindAddress, String hostnameForClients,
-      String membername) {
-    try {
-      host = LocalHostUtil.getLocalHost();
-    } catch (UnknownHostException ex) {
-      throw new InternalGemFireException(
-          "Failed getting local host", ex);
-    }
-    this.port = port;
-    this.bindAddress = validateBindAddress(bindAddress);
-    sslConfig = validateSSLConfig(null);
-    this.hostnameForClients = hostnameForClients;
-    if (membername == null) {
-      this.membername = DistributionConfig.DEFAULT_NAME;
-    } else {
-      this.membername = membername;
-    }
-    timestamp = System.currentTimeMillis();
+  public DistributionLocatorId(final int port, final @Nullable String bindAddress,
+      final @Nullable String hostnameForClients, final @Nullable String memberName) {
+    this(getLocalHostOrThrow(), null, port, bindAddress, null, hostnameForClients, memberName);
+  }
+
+  public DistributionLocatorId(final @NotNull InetAddress address,
+      final @NotNull InternalLocator locator) {
+    this(address, null, locator.getPort(),
+        (locator.getBindAddressString() != null
+            ? locator.getBindAddressString()
+            : (locator.getBindAddress() != null ? locator.getBindAddress().getHostAddress()
+                : null)),
+        null,
+        locator.getHostnameForClients(), null);
   }
 
-  public DistributionLocatorId(InetAddress host, int port, String bindAddress, SSLConfig sslConfig,
-      String hostnameForClients) {
+  private DistributionLocatorId(final @Nullable InetAddress host, @Nullable String hostname,
+      final int port,
+      final @Nullable String bindAddress, final @Nullable SSLConfig sslConfig,
+      final @Nullable String hostnameForClients, final @Nullable String memberName) {
     this.host = host;
+    this.hostname = hostname;
     this.port = port;
-    this.bindAddress = validateBindAddress(bindAddress);
-    this.sslConfig = validateSSLConfig(sslConfig);
+    this.bindAddress = bindAddressOrDefault(bindAddress);
+    this.sslConfig = sslConfigOrDefault(sslConfig);
     this.hostnameForClients = hostnameForClients;
-    membername = DistributionConfig.DEFAULT_NAME;
-    timestamp = 0;
-
+    this.memberName = memberNameOrDefault(memberName);
+    timestamp = System.currentTimeMillis();
   }
 
-
   /**
-   * Constructs a DistributionLocatorId with a String of the form: hostname[port] or
-   * hostname:bindaddress[port] or hostname@bindaddress[port]
-   * <p>
-   * The :bindaddress portion is optional. hostname[port] is the more common form.
-   * <p>
-   * Example: merry.gemstone.com[7056]<br>
-   * Example w/ bind address: merry.gemstone.com:81.240.0.1[7056], or
-   * merry.gemstone.com@fdf0:76cf:a0ed:9449::16[7056]
-   * <p>
-   * Use bindaddress[port] or hostname[port]. This object doesn't need to differentiate between the
-   * two.
+   * Unmarshall using default memberName.
+   *
+   * @see DistributionLocatorId#unmarshal(String, String)
    */
-  public DistributionLocatorId(String marshalled) {
-    this(marshalled, DistributionConfig.DEFAULT_NAME);
+  public static @NotNull DistributionLocatorId unmarshal(final @NotNull String marshalled) {
+    return unmarshal(marshalled, null);
   }
 
   /**
    * Constructs a DistributionLocatorId with a String of the form: hostname[port] or
    * hostname:bindaddress[port] or hostname@bindaddress[port]
-   * and membername
+   * and memberName
    * <p>
    * The :bindaddress portion is optional. hostname[port] is the more common form.
    * <p>
@@ -151,99 +133,83 @@ public class DistributionLocatorId implements java.io.Serializable {
    * Use bindaddress[port] or hostname[port]. This object doesn't need to differentiate between the
    * two.
    * <p>
-   * Membername example: locator1 or locator-ny1.
+   * memberName example: locator1 or locator-ny1.
    * <p>
    */
-  public DistributionLocatorId(String marshalled, String membername) {
-    if (membername == null) {
-      this.membername = DistributionConfig.DEFAULT_NAME;
-    } else {
-      this.membername = membername;
-    }
-    timestamp = System.currentTimeMillis();
+  public static @NotNull DistributionLocatorId unmarshal(final @NotNull String marshalled,
+      final @Nullable String memberName) {
 
-    final int portStartIdx = marshalled.indexOf('[');
-    final int portEndIdx = marshalled.indexOf(']');
+    final int portStartIndex = marshalled.indexOf('[');
+    final int portEndIndex = marshalled.indexOf(']');
 
-    if (portStartIdx < 0 || portEndIdx < portStartIdx) {
+    if (portStartIndex < 0 || portEndIndex < portStartIndex) {
       throw new IllegalArgumentException(
-          String.format("%s is not in the form hostname[port].",
-              marshalled));
+          format("%s is not in the form hostname[port].", marshalled));
     }
 
-    int bindIdx = marshalled.lastIndexOf('@');
-    if (bindIdx < 0) {
-      bindIdx = marshalled.lastIndexOf(':');
+    int bindAddressIndex = marshalled.lastIndexOf('@');
+    if (bindAddressIndex < 0) {
+      bindAddressIndex = marshalled.lastIndexOf(':');
     }
 
-    hostname = marshalled.substring(0, bindIdx > -1 ? bindIdx : portStartIdx);
+    String hostname =
+        marshalled.substring(0, bindAddressIndex > -1 ? bindAddressIndex : portStartIndex);
 
     if (hostname.indexOf(':') >= 0) {
-      bindIdx = marshalled.lastIndexOf('@');
-      hostname = marshalled.substring(0, bindIdx > -1 ? bindIdx : portStartIdx);
+      bindAddressIndex = marshalled.lastIndexOf('@');
+      hostname = marshalled.substring(0, bindAddressIndex > -1 ? bindAddressIndex : portStartIndex);
     }
 
+    InetAddress host = getInetAddressOrNull(hostname);
 
+    final int port;
     try {
-      host = InetAddress.getByName(hostname);
-    } catch (UnknownHostException ex) {
-      host = null;
-    }
-
-    try {
-      port = Integer.parseInt(marshalled.substring(portStartIdx + 1, portEndIdx));
+      port = Integer.parseInt(marshalled.substring(portStartIndex + 1, portEndIndex));
     } catch (NumberFormatException nfe) {
       throw new IllegalArgumentException(
-          String.format("%s does not contain a valid port number",
-              marshalled));
+          format("%s does not contain a valid port number", marshalled));
     }
 
-    if (bindIdx > -1) {
-      // found a bindaddress
-      bindAddress = validateBindAddress(marshalled.substring(bindIdx + 1, portStartIdx));
-    } else {
-      bindAddress = validateBindAddress(DistributionConfig.DEFAULT_BIND_ADDRESS);
-    }
-    sslConfig = validateSSLConfig(null);
+    final String bindAddress =
+        substringAfterFoundOrNull(marshalled, bindAddressIndex, portStartIndex);
+    final String hostnameForClients = parseHostnameForClients(marshalled);
 
-    int optionsIndex = marshalled.indexOf(',');
+    return new DistributionLocatorId(host, hostname, port, bindAddress, null, hostnameForClients,
+        memberName);
+  }
+
+  private static @Nullable String parseHostnameForClients(final @NotNull String marshalled) {
+    final int optionsIndex = marshalled.indexOf(',');
     if (optionsIndex > 0) {
-      String[] options = marshalled.substring(optionsIndex).split(",");
+      final String[] options = marshalled.substring(optionsIndex).split(",");
       for (final String option : options) {
-        String[] optionFields = option.split("=");
+        final String[] optionFields = option.split("=");
         if (optionFields.length == 2) {
-          if (optionFields[0].equalsIgnoreCase("peer")) {
-            // this setting is deprecated
-            // this.peerLocator = Boolean.valueOf(optionFields[1]).booleanValue();
-          } else if (optionFields[0].equalsIgnoreCase("server")) {
-            // this setting is deprecated
-            // this.serverLocator = Boolean.valueOf(optionFields[1]).booleanValue();
-          } else if (optionFields[0].equalsIgnoreCase("hostname-for-clients")) {
-            hostnameForClients = optionFields[1];
-          } else {
-            throw new IllegalArgumentException(marshalled + " invalid option " + optionFields[0]
-                + ". valid options are \"peer\", \"server\" and \"hostname-for-clients\"");
+          final String fieldName = optionFields[0].toLowerCase();
+          switch (fieldName) {
+            case "hostname-for-clients":
+              return optionFields[1];
+            case "peer":
+            case "server":
+              // these settings are deprecated
+              break;
+            default:
+              throw new IllegalArgumentException(marshalled + " invalid option " + fieldName
+                  + ". valid options are \"peer\", \"server\" and \"hostname-for-clients\"");
           }
         }
       }
     }
-  }
-
-  public DistributionLocatorId(InetAddress address, Locator locator) {
-    this(address, locator.getPort(),
-        (((InternalLocator) locator).getBindAddressString() != null
-            ? ((InternalLocator) locator).getBindAddressString()
-            : (locator.getBindAddress() != null ? locator.getBindAddress().getHostAddress()
-                : null)),
-        null,
-        locator.getHostnameForClients());
+    return null;
   }
 
   /**
-   * Returns marshaled string that is compatible as input for
-   * {@link #DistributionLocatorId(String)}.
+   * Returns marshaled string that is compatible as input for unmarshal.
+   *
+   * @see #unmarshal(String)
+   * @see #unmarshal(String, String)
    */
-  public String marshal() {
+  public @NotNull String marshal() {
     StringBuilder sb = new StringBuilder();
     sb.append(host.getHostAddress());
     if (!bindAddress.isEmpty()) {
@@ -258,19 +224,34 @@ public class DistributionLocatorId implements java.io.Serializable {
     return sb.toString();
   }
 
-  private SSLConfig validateSSLConfig(SSLConfig sslConfig) {
-    if (sslConfig == null) {
-      return new SSLConfig.Builder().build(); // uses defaults
+  /**
+   * Returns marshaled string that is compatible as input for unmarshal preferring the
+   * hostnameForClients or bindAddress values before the host value.
+   *
+   * @see #unmarshal(String)
+   * @see #unmarshal(String, String)
+   */
+  public @NotNull String marshalForClients() {
+    StringBuilder sb = new StringBuilder();
+
+    if (!isEmpty(hostnameForClients)) {
+      sb.append(hostnameForClients);
+    } else if (!isEmpty(bindAddress)) {
+      sb.append(bindAddress);
+    } else {
+      if (isMcastId()) {
+        sb.append(host.getHostAddress());
+      } else {
+        sb.append(SocketCreator.getHostName(host));
+      }
     }
-    return sslConfig;
-  }
 
-  public SSLConfig getSSLConfig() {
-    return sslConfig;
+    sb.append("[").append(port).append("]");
+    return sb.toString();
   }
 
-  public void setSSLConfig(SSLConfig sslConfig) {
-    this.sslConfig = validateSSLConfig(sslConfig);
+  public @NotNull SSLConfig getSSLConfig() {
+    return sslConfig;
   }
 
   /** Returns the communication port. */
@@ -283,19 +264,15 @@ public class DistributionLocatorId implements java.io.Serializable {
    * ipString Otherwise we create InetAddress each time.
    *
    **/
-  public HostAndPort getHost() throws UnknownHostException {
+  public @NotNull HostAndPort getHost() throws UnknownHostException {
     if (host == null && hostname == null) {
       throw new UnknownHostException("locator ID has no hostname or resolved inet address");
     }
-    String addr = hostname;
-    if (host != null) {
-      addr = host.getHostName();
-    }
-    return new HostAndPort(addr, port);
+    return new HostAndPort(null == host ? hostname : host.getHostName(), port);
   }
 
   /** returns the host name */
-  public String getHostName() {
+  public @NotNull String getHostName() {
     if (hostname == null) {
       hostname = host.getHostName();
     }
@@ -310,98 +287,62 @@ public class DistributionLocatorId implements java.io.Serializable {
   /**
    * Returns the bindAddress; value is "" unless host has multiple network interfaces.
    */
-  public String getBindAddress() {
+  public @NotNull String getBindAddress() {
     return bindAddress;
   }
 
   /**
    * @since GemFire 5.7
    */
-  public String getHostnameForClients() {
+  public @NotNull String getHostnameForClients() {
     return hostnameForClients;
   }
 
-  public String getMemberName() {
-    if (membername == null) {
-      membername = DistributionConfig.DEFAULT_NAME;
-    }
-    return membername;
+  public @NotNull String getMemberName() {
+    return memberName;
   }
 
   public long getTimeStamp() {
     return timestamp;
   }
 
-  // private String hostNameToString() {
-  // if (this.host.isMulticastAddress()) {
-  // return this.host.getHostAddress();
-  // } else {
-  // return this.host.getHostName();
-  // }
-  // }
-
-  /** Returns the default bindAddress if bindAddress is null. */
-  private String validateBindAddress(String bindAddress) {
-    if (bindAddress == null) {
-      return DistributionConfig.DEFAULT_BIND_ADDRESS;
-    }
-    return bindAddress;
-  }
-
-  /**
-   * Returns a string representation of the object.
-   *
-   * @return a string representation of the object
-   */
   @Override
   public String toString() {
-    StringBuilder sb = new StringBuilder();
-
-    // If hostnameForClients is set, use that
-    if (hostnameForClients != null && hostnameForClients.length() > 0) {
-      sb.append(hostnameForClients);
-    } else if (bindAddress != null && bindAddress.length() > 0) {
-      // if bindAddress then use that instead of host...
-      sb.append(bindAddress);
-    } else {
-      if (isMcastId()) {
-        sb.append(host.getHostAddress());
-      } else {
-        sb.append(SocketCreator.getHostName(host));
-      }
-    }
-
-    sb.append("[").append(port).append("]");
-    return sb.toString();
+    return "DistributionLocatorId{" +
+        "host=" + host +
+        ", port=" + port +
+        ", bindAddress='" + bindAddress + '\'' +
+        ", sslConfig=" + sslConfig +
+        ", hostnameForClients='" + hostnameForClients + '\'' +
+        ", hostname='" + hostname + '\'' +
+        ", memberName='" + memberName + '\'' +
+        ", timestamp=" + timestamp +
+        '}';
   }
 
-  /**
-   * Indicates whether some other object is "equal to" this one.
-   *
-   * @param other the reference object with which to compare.
-   * @return true if this object is the same as the obj argument; false otherwise.
-   *
-   */
   @Override
-  public boolean equals(Object other) {
-    if (other == this) {
+  public boolean equals(final Object o) {
+    if (this == o) {
       return true;
     }
-    if (other == null) {
+    if (!(o instanceof DistributionLocatorId)) {
       return false;
     }
-    if (!(other instanceof DistributionLocatorId)) {
-      return false;
-    }
-    final DistributionLocatorId that = (DistributionLocatorId) other;
+    final DistributionLocatorId that = (DistributionLocatorId) o;
+    return port == that.port && Objects.equals(host, that.host) && bindAddress.equals(
+        that.bindAddress);
+  }
 
-    if (!Objects.equals(host, that.host)) {
-      return false;
-    }
-    if (port != that.port) {
-      return false;
-    }
-    return StringUtils.equals(bindAddress, that.bindAddress);
+  @Override
+  public int hashCode() {
+    int result = 17;
+    final int mult = 37;
+
+    result = mult * result + host.hashCode();
+    result = mult * result + port;
+    result = mult * result + bindAddress.hashCode();
+
+    return result;
   }
 
   /**
@@ -436,64 +377,46 @@ public class DistributionLocatorId implements java.io.Serializable {
   }
 
   /**
-   * Returns a hash code for the object. This method is supported for the benefit of hashtables such
-   * as those provided by java.util.Hashtable.
-   *
-   * @return the integer 0 if description is null; otherwise a unique integer.
+   * Required to initialize non-null values for transient or missing fields.
    */
-  @Override
-  public int hashCode() {
-    int result = 17;
-    final int mult = 37;
+  private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException {
+    in.defaultReadObject();
 
-    result = mult * result + (host == null ? 0 : host.hashCode());
-    result = mult * result + port;
-    result = mult * result + (bindAddress == null ? 0 : bindAddress.hashCode());
+    sslConfig = sslConfigOrDefault(null);
+    memberName = memberNameOrDefault(memberName);
+  }
 
-    return result;
+  private static @NotNull String bindAddressOrDefault(final @Nullable String bindAddress) {
+    return defaultIfNull(bindAddress, DistributionConfig.DEFAULT_BIND_ADDRESS);
   }
 
-  /**
-   * Converts a collection of {@link Locator} instances to a collection of DistributionLocatorId
-   * instances. Note this will use {@link LocalHostUtil#getLocalHost()} as the host for
-   * DistributionLocatorId. This is because all instances of Locator are local only.
-   *
-   * @param locators collection of Locator instances
-   * @return collection of DistributionLocatorId instances
-   * @see Locator
-   */
-  public static Collection<DistributionLocatorId> asDistributionLocatorIds(
-      Collection<Locator> locators) throws UnknownHostException {
-    if (locators.isEmpty()) {
-      return Collections.emptyList();
-    }
-    Collection<DistributionLocatorId> locatorIds = new ArrayList<>();
-    for (Locator locator : locators) {
-      DistributionLocatorId locatorId =
-          new DistributionLocatorId(LocalHostUtil.getLocalHost(), locator);
-      locatorIds.add(locatorId);
-    }
-    return locatorIds;
+  private static @NotNull SSLConfig sslConfigOrDefault(final @Nullable SSLConfig sslConfig) {
+    return getIfNull(sslConfig, () -> SSLConfig.builder().build());
   }
 
-  /**
-   * Marshals a collection of {@link Locator} instances to a collection of DistributionLocatorId
-   * instances. Note this will use {@link LocalHostUtil#getLocalHost()} as the host for
-   * DistributionLocatorId. This is because all instances of Locator are local only.
-   *
-   * @param locatorIds collection of DistributionLocatorId instances
-   * @return collection of String instances
-   * @see #marshal()
-   */
-  public static Collection<String> asStrings(Collection<DistributionLocatorId> locatorIds) {
-    if (locatorIds.isEmpty()) {
-      return Collections.emptyList();
+  private static @NotNull String memberNameOrDefault(final @Nullable String memberName) {
+    return defaultIfNull(memberName, DistributionConfig.DEFAULT_NAME);
+  }
+
+  private static @NotNull InetAddress getLocalHostOrThrow() {
+    try {
+      return LocalHostUtil.getLocalHost();
+    } catch (UnknownHostException e) {
+      throw new InternalGemFireException("Failed getting local host", e);
     }
-    Collection<String> strings = new ArrayList<>();
-    for (DistributionLocatorId locatorId : locatorIds) {
-      strings.add(locatorId.marshal());
+  }
+
+  private static @Nullable InetAddress getInetAddressOrNull(@NotNull String hostname) {
+    try {
+      return InetAddress.getByName(hostname);
+    } catch (UnknownHostException ignore) {
     }
-    return strings;
+    return null;
+  }
+
+  private static @Nullable String substringAfterFoundOrNull(final @NotNull String value,
+      final int found, final int end) {
+    return found < 0 ? null : value.substring(found + 1, end);
   }
 
 }
diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/remote/RemoteTransportConfig.java b/geode-core/src/main/java/org/apache/geode/internal/admin/remote/RemoteTransportConfig.java
index 8a933de13e..a2fed40d62 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/admin/remote/RemoteTransportConfig.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/admin/remote/RemoteTransportConfig.java
@@ -14,6 +14,8 @@
  */
 package org.apache.geode.internal.admin.remote;
 
+import static java.util.Collections.emptySet;
+import static org.apache.commons.lang3.StringUtils.isBlank;
 import static org.apache.geode.distributed.ConfigurationProperties.BIND_ADDRESS;
 import static org.apache.geode.distributed.ConfigurationProperties.DISABLE_AUTO_RECONNECT;
 import static org.apache.geode.distributed.ConfigurationProperties.DISABLE_TCP;
@@ -48,14 +50,14 @@ public class RemoteTransportConfig implements TransportConfig {
   private final boolean tcpDisabled;
   private final boolean disableAutoReconnect;
   private final DistributionLocatorId mcastId;
-  private final Set ids;
+  private final Set<DistributionLocatorId> ids;
   private final String bindAddress;
   private final SSLConfig sslConfig;
   private final String membershipPortRange;
   private final int tcpPort;
   private boolean isReconnectingDS;
   private MembershipInformation oldDSMembershipInfo;
-  private int vmKind = -1;
+  private final int vmKind;
 
   // -------------------------------------------------------------------------
   // Constructor(s)
@@ -100,15 +102,14 @@ public class RemoteTransportConfig implements TransportConfig {
     // See what type of discovery is being used
     if (initialHosts.length() == 0) {
       // loner system
-      ids = Collections.EMPTY_SET;
-      return;
+      ids = emptySet();
     } else {
-      HashSet locators = new HashSet();
+      Set<DistributionLocatorId> locators = new HashSet<>();
       StringTokenizer stringTokenizer = new StringTokenizer(initialHosts, ",");
       while (stringTokenizer.hasMoreTokens()) {
         String locator = stringTokenizer.nextToken();
         if (StringUtils.isNotEmpty(locator)) {
-          locators.add(new DistributionLocatorId(locator));
+          locators.add(DistributionLocatorId.unmarshal(locator));
         }
       }
 
@@ -116,9 +117,6 @@ public class RemoteTransportConfig implements TransportConfig {
         locators.add(mcastId);
       }
       ids = Collections.unmodifiableSet(locators);
-      if (mcastEnabled) {
-        Assert.assertTrue(mcastId != null);
-      }
     }
   }
 
@@ -126,9 +124,9 @@ public class RemoteTransportConfig implements TransportConfig {
    * Constructs a transport config given a collection of {@link DistributionLocatorId} instances.
    */
   public RemoteTransportConfig(boolean isMcastEnabled, boolean isTcpDisabled,
-      boolean isAutoReconnectDisabled, String bindAddress, SSLConfig sslConfig, Collection ids,
+      boolean isAutoReconnectDisabled, String bindAddress, SSLConfig sslConfig,
+      Collection<DistributionLocatorId> ids,
       String membershipPortRange, int tcpPort, int vmKind) {
-    DistributionLocatorId mid = null;
 
     if (bindAddress == null) {
       this.bindAddress = DistributionConfig.DEFAULT_BIND_ADDRESS;
@@ -141,23 +139,20 @@ public class RemoteTransportConfig implements TransportConfig {
     mcastEnabled = isMcastEnabled;
     tcpDisabled = isTcpDisabled;
     disableAutoReconnect = isAutoReconnectDisabled;
+
+    DistributionLocatorId mid = null;
     if (isMcastEnabled) {
-      if (ids.size() < 1) {
-        throw new IllegalArgumentException(
-            "expected at least one host/port id");
+      if (ids.isEmpty()) {
+        throw new IllegalArgumentException("expected at least one host/port id");
       }
-      Iterator it = ids.iterator();
-      while (it.hasNext() && mid == null) {
-        DistributionLocatorId id = (DistributionLocatorId) it.next();
+      for (final DistributionLocatorId id : ids) {
         if (id.isMcastId()) {
           mid = id;
-          // System.out.println("mcast id: " + id);
-        } else {
-          // System.out.println("non-mcast id: " + id);
+          break;
         }
       }
     }
-    this.ids = Collections.unmodifiableSet(new HashSet(ids));
+    this.ids = Collections.unmodifiableSet(new HashSet<>(ids));
     mcastId = mid;
     if (mcastEnabled) {
       Assert.assertTrue(mcastId != null);
@@ -185,7 +180,7 @@ public class RemoteTransportConfig implements TransportConfig {
    * Returns the set of DistributionLocatorId instances that define this transport. The set is
    * unmodifiable.
    */
-  public Set getIds() {
+  public Set<DistributionLocatorId> getIds() {
     return ids;
   }
 
@@ -267,11 +262,11 @@ public class RemoteTransportConfig implements TransportConfig {
     }
     // Create locator string
     StringBuilder locators = new StringBuilder();
-    for (Iterator iter = ids.iterator(); iter.hasNext();) {
-      DistributionLocatorId locator = (DistributionLocatorId) iter.next();
+    for (Iterator<DistributionLocatorId> iter = ids.iterator(); iter.hasNext();) {
+      DistributionLocatorId locator = iter.next();
       if (!locator.isMcastId()) {
         String baddr = locator.getBindAddress();
-        if (baddr != null && baddr.trim().length() > 0) {
+        if (!isBlank(baddr)) {
           locators.append(baddr);
         } else {
           locators.append(locator.getHostName());
@@ -304,9 +299,8 @@ public class RemoteTransportConfig implements TransportConfig {
   private String toString(boolean noMcast) {
     StringBuilder result = new StringBuilder();
     boolean first = true;
-    for (final Object id : ids) {
-      DistributionLocatorId dli = (DistributionLocatorId) id;
-      if (noMcast && dli.isMcastId()) {
+    for (final DistributionLocatorId id : ids) {
+      if (noMcast && id.isMcastId()) {
         continue;
       }
       if (!first) {
@@ -314,19 +308,11 @@ public class RemoteTransportConfig implements TransportConfig {
       } else {
         first = false;
       }
-      result.append(dli.toString());
+      result.append(id.toString());
     }
     return result.toString();
   }
 
-  /**
-   * returns a locators string suitable for use in locators= in gemfire.properties
-   */
-  public String locatorsString() {
-    return toString(true);
-  }
-
-
   // -------------------------------------------------------------------------
   // Methods overridden from java.lang.Object
   // -------------------------------------------------------------------------
@@ -338,7 +324,7 @@ public class RemoteTransportConfig implements TransportConfig {
 
   @Override
   public boolean equals(Object o) {
-    if (o != null && o instanceof RemoteTransportConfig) {
+    if (o instanceof RemoteTransportConfig) {
       RemoteTransportConfig other = (RemoteTransportConfig) o;
       return (mcastEnabled == other.mcastEnabled) && ids.equals(other.ids);
     }
diff --git a/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt b/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt
index 5211eb50cc..db221f6f86 100644
--- a/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt
+++ b/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt
@@ -268,7 +268,7 @@ org/apache/geode/internal/SystemAdmin$CombinedResources,false
 org/apache/geode/internal/admin/CompoundEntrySnapshot,true,5776382582897895718,allUserAttributes:java/util/Set,allValues:java/util/Set,hitRatio:float,hitRatioSum:double,hitResponders:long,lastAccessTime:long,lastModifiedTime:long,name:java/lang/Object,numHits:long,numMisses:long
 org/apache/geode/internal/admin/CompoundRegionSnapshot,true,6295026394298398004,allCacheLoaders:java/util/Set,allCacheWriters:java/util/Set,allCapControllers:java/util/Set,allConcLevels:java/util/Set,allCustomIdle:java/util/HashSet,allCustomTtl:java/util/HashSet,allDataPolicies:java/util/Set,allEntryIdleTimeout:java/util/Set,allEntryTtl:java/util/Set,allInitialCaps:java/util/Set,allKeyConstraints:java/util/Set,allListeners:java/util/Set,allLoadFactors:java/util/Set,allRegionIdleTimeout:j [...]
 org/apache/geode/internal/admin/StatAlert,true,5725457607122449170,definitionId:int,time:java/util/Date,values:java/lang/Number[]
-org/apache/geode/internal/admin/remote/DistributionLocatorId,true,6587390186971937865,bindAddress:java/lang/String,host:java/net/InetAddress,hostname:java/lang/String,hostnameForClients:java/lang/String,membername:java/lang/String,peerLocator:boolean,port:int,serverLocator:boolean,timestamp:long
+org/apache/geode/internal/admin/remote/DistributionLocatorId,true,6587390186971937865,bindAddress:java/lang/String,host:java/net/InetAddress,hostname:java/lang/String,hostnameForClients:java/lang/String,memberName:java/lang/String,port:int,timestamp:long
 org/apache/geode/internal/admin/remote/EntryValueNodeImpl,false,fields:org/apache/geode/internal/admin/remote/EntryValueNodeImpl[],name:java/lang/String,primitive:boolean,primitiveVal:java/lang/Object,type:java/lang/String
 org/apache/geode/internal/cache/BucketAdvisor$SetFromMap,true,2454657854757543876,m:java/util/Map
 org/apache/geode/internal/cache/BucketNotFoundException,true,2898657229184289911
diff --git a/geode-core/src/test/java/org/apache/geode/internal/admin/remote/DistributionLocatorIdTest.java b/geode-core/src/test/java/org/apache/geode/internal/admin/remote/DistributionLocatorIdTest.java
index cbb3116a57..8ba7d5dc27 100644
--- a/geode-core/src/test/java/org/apache/geode/internal/admin/remote/DistributionLocatorIdTest.java
+++ b/geode-core/src/test/java/org/apache/geode/internal/admin/remote/DistributionLocatorIdTest.java
@@ -24,7 +24,6 @@ import java.net.UnknownHostException;
 
 import org.junit.jupiter.api.Test;
 
-import org.apache.geode.distributed.Locator;
 import org.apache.geode.distributed.internal.DistributionConfig;
 import org.apache.geode.distributed.internal.InternalLocator;
 import org.apache.geode.internal.inet.LocalHostUtil;
@@ -50,13 +49,13 @@ class DistributionLocatorIdTest {
   @Test
   void testEquals_and_DetailCompare() {
     DistributionLocatorId distributionLocatorId1 =
-        new DistributionLocatorId(40404, "127.0.0.1", null);
+        new DistributionLocatorId(40404, "127.0.0.1", null, null);
     DistributionLocatorId distributionLocatorId2 =
         new DistributionLocatorId(40404, "127.0.0.1", "127.0.1.0", "member2");
     DistributionLocatorId distributionLocatorId3 =
         new DistributionLocatorId(40404, "127.0.0.1", null, "member3");
     DistributionLocatorId distributionLocatorId4 =
-        new DistributionLocatorId(distributionLocatorId3.marshal());
+        DistributionLocatorId.unmarshal(distributionLocatorId3.marshal());
 
     assertThat(distributionLocatorId1).isEqualTo(distributionLocatorId2);
     assertThat(distributionLocatorId1).isEqualTo(distributionLocatorId3);
@@ -74,44 +73,45 @@ class DistributionLocatorIdTest {
   }
 
   @Test
-  void toStringReturnsMarshaledAddressWhenConstructedWithMarshaledAddress() {
-    final DistributionLocatorId locatorId = new DistributionLocatorId("localhost[1234]");
+  void marshalForClientsMarshaledAddressWhenConstructedWithMarshaledAddress() {
+    final DistributionLocatorId locatorId = DistributionLocatorId.unmarshal("localhost[1234]");
 
-    assertThat(locatorId).hasToString("localhost[1234]");
+    assertThat(locatorId.marshalForClients()).isEqualTo("localhost[1234]");
   }
 
   @Test
-  void toStringReturnsHostnameForClientsWhenConstructedWithHostnameForClients() {
+  void marshalForClientsHostnameForClientsWhenConstructedWithHostnameForClients() {
     final DistributionLocatorId locatorId =
         new DistributionLocatorId(1234, "bind-address.example.com",
-            "hostname-for-clients.example.com");
+            "hostname-for-clients.example.com", null);
 
-    assertThat(locatorId).hasToString("hostname-for-clients.example.com[1234]");
+    assertThat(locatorId.marshalForClients()).isEqualTo("hostname-for-clients.example.com[1234]");
   }
 
   @Test
-  void toStringReturnsBindAddressWhenConstructedWithBindAddress() {
+  void marshalForClientsBindAddressWhenConstructedWithBindAddress() {
     final DistributionLocatorId locatorId =
-        new DistributionLocatorId(1234, "bind-address.example.com");
+        new DistributionLocatorId(1234, "bind-address.example.com", null, null);
 
-    assertThat(locatorId).hasToString("bind-address.example.com[1234]");
+    assertThat(locatorId.marshalForClients()).isEqualTo("bind-address.example.com[1234]");
   }
 
   @Test
-  void toStringReturnsLocalHostNameWhenLocatorBindAddressAndHostnameForClientNotSet()
+  void marshalForClientsLocalHostNameWhenLocatorBindAddressAndHostnameForClientNotSet()
       throws UnknownHostException {
     final InetAddress localHost = LocalHostUtil.getLocalHost();
 
-    final Locator locator = mock(InternalLocator.class);
+    final InternalLocator locator = mock(InternalLocator.class);
     when(locator.getPort()).thenReturn(1234);
 
     final DistributionLocatorId locatorId = new DistributionLocatorId(localHost, locator);
 
-    assertThat(locatorId).hasToString(localHost.getCanonicalHostName() + "[1234]");
+    assertThat(locatorId.marshalForClients())
+        .isEqualTo(localHost.getCanonicalHostName() + "[1234]");
   }
 
   @Test
-  void toStringReturnsBindAddressWhenLocatorBindAddressSetAndHostnameForClientNotSet()
+  void marshalForClientsBindAddressWhenLocatorBindAddressSetAndHostnameForClientNotSet()
       throws UnknownHostException {
     final InetAddress localHost = LocalHostUtil.getLocalHost();
 
@@ -121,11 +121,11 @@ class DistributionLocatorIdTest {
 
     final DistributionLocatorId locatorId = new DistributionLocatorId(localHost, locator);
 
-    assertThat(locatorId).hasToString("bind-address.example.com[1234]");
+    assertThat(locatorId.marshalForClients()).isEqualTo("bind-address.example.com[1234]");
   }
 
   @Test
-  void toStringReturnsBindAddressWhenLocatorBindAddressAndHostnameForClientSet()
+  void marshalForClientsBindAddressWhenLocatorBindAddressAndHostnameForClientSet()
       throws UnknownHostException {
     final InetAddress localHost = LocalHostUtil.getLocalHost();
 
@@ -136,6 +136,6 @@ class DistributionLocatorIdTest {
 
     final DistributionLocatorId locatorId = new DistributionLocatorId(localHost, locator);
 
-    assertThat(locatorId).hasToString("hostname-for-clients.example.com[1234]");
+    assertThat(locatorId.marshalForClients()).isEqualTo("hostname-for-clients.example.com[1234]");
   }
 }
diff --git a/geode-wan/src/distributedTest/java/org/apache/geode/internal/cache/wan/WANTestBase.java b/geode-wan/src/distributedTest/java/org/apache/geode/internal/cache/wan/WANTestBase.java
index 43a1e6577e..850287581b 100644
--- a/geode-wan/src/distributedTest/java/org/apache/geode/internal/cache/wan/WANTestBase.java
+++ b/geode-wan/src/distributedTest/java/org/apache/geode/internal/cache/wan/WANTestBase.java
@@ -3236,7 +3236,7 @@ public class WANTestBase extends DistributedTestCase {
       for (Map.Entry<Integer, Set<String>> entry : dsVsPort.entrySet()) {
         Set<DistributionLocatorId> locators = allSiteMetaData.get(entry.getKey());
         for (String locatorInMetaData : entry.getValue()) {
-          DistributionLocatorId locatorId = new DistributionLocatorId(locatorInMetaData);
+          DistributionLocatorId locatorId = DistributionLocatorId.unmarshal(locatorInMetaData);
           if (!locators.contains(locatorId)) {
             completeFlag = false;
             break;
diff --git a/geode-wan/src/main/java/org/apache/geode/cache/wan/internal/AbstractRemoteGatewaySender.java b/geode-wan/src/main/java/org/apache/geode/cache/wan/internal/AbstractRemoteGatewaySender.java
index d81e531117..319f933634 100644
--- a/geode-wan/src/main/java/org/apache/geode/cache/wan/internal/AbstractRemoteGatewaySender.java
+++ b/geode-wan/src/main/java/org/apache/geode/cache/wan/internal/AbstractRemoteGatewaySender.java
@@ -81,7 +81,7 @@ public abstract class AbstractRemoteGatewaySender extends AbstractGatewaySender
     StringTokenizer locatorsOnThisVM = new StringTokenizer(locators, ",");
     while (locatorsOnThisVM.hasMoreTokens()) {
       String localLocator = locatorsOnThisVM.nextToken();
-      DistributionLocatorId locatorID = new DistributionLocatorId(localLocator);
+      DistributionLocatorId locatorID = DistributionLocatorId.unmarshal(localLocator);
       try {
         final RemoteLocatorResponse response =
             (RemoteLocatorResponse) new TcpClient(SocketCreatorFactory
@@ -107,7 +107,7 @@ public abstract class AbstractRemoteGatewaySender extends AbstractGatewaySender
           }
           for (final String remoteLocator : response.getLocators()) {
             try {
-              DistributionLocatorId locatorId = new DistributionLocatorId(remoteLocator);
+              DistributionLocatorId locatorId = DistributionLocatorId.unmarshal(remoteLocator);
               pf.addLocator(locatorId.getHost().getHostName(), locatorId.getPort());
               locatorCount++;
             } catch (Exception e) {
diff --git a/geode-wan/src/main/java/org/apache/geode/cache/wan/internal/client/locator/LocatorHelper.java b/geode-wan/src/main/java/org/apache/geode/cache/wan/internal/client/locator/LocatorHelper.java
index 0ced5d054d..c7ee2ebb11 100644
--- a/geode-wan/src/main/java/org/apache/geode/cache/wan/internal/client/locator/LocatorHelper.java
+++ b/geode-wan/src/main/java/org/apache/geode/cache/wan/internal/client/locator/LocatorHelper.java
@@ -121,7 +121,7 @@ public class LocatorHelper {
       final @NotNull LocatorMembershipListener locatorListener,
       final @NotNull DistributionLocatorId locator) {
     computeIfAbsent(locatorListener.getAllServerLocatorsInfo(), distributedSystemId,
-        k -> new CopyOnWriteHashSet<>()).add(locator.toString());
+        k -> new CopyOnWriteHashSet<>()).add(locator.marshalForClients());
   }
 
   /**
diff --git a/geode-wan/src/main/java/org/apache/geode/cache/wan/internal/client/locator/LocatorMembershipListenerImpl.java b/geode-wan/src/main/java/org/apache/geode/cache/wan/internal/client/locator/LocatorMembershipListenerImpl.java
index ed6ecb3c2e..5102c29aa7 100644
--- a/geode-wan/src/main/java/org/apache/geode/cache/wan/internal/client/locator/LocatorMembershipListenerImpl.java
+++ b/geode-wan/src/main/java/org/apache/geode/cache/wan/internal/client/locator/LocatorMembershipListenerImpl.java
@@ -161,7 +161,7 @@ public class LocatorMembershipListenerImpl implements LocatorMembershipListener
       localLocatorId =
           new DistributionLocatorId(port, config.getBindAddress(), null, memberName);
     } else {
-      localLocatorId = new DistributionLocatorId(localLocator, memberName);
+      localLocatorId = DistributionLocatorId.unmarshal(localLocator, memberName);
     }
 
     // Make a local copy of the current list of known locators.
diff --git a/geode-wan/src/main/java/org/apache/geode/cache/wan/internal/client/locator/WanLocatorDiscovererImpl.java b/geode-wan/src/main/java/org/apache/geode/cache/wan/internal/client/locator/WanLocatorDiscovererImpl.java
index 14e2558b3c..055f09eb87 100644
--- a/geode-wan/src/main/java/org/apache/geode/cache/wan/internal/client/locator/WanLocatorDiscovererImpl.java
+++ b/geode-wan/src/main/java/org/apache/geode/cache/wan/internal/client/locator/WanLocatorDiscovererImpl.java
@@ -17,8 +17,6 @@ package org.apache.geode.cache.wan.internal.client.locator;
 import java.util.StringTokenizer;
 import java.util.concurrent.ExecutorService;
 
-import org.apache.logging.log4j.Logger;
-
 import org.apache.geode.cache.client.internal.locator.wan.LocatorMembershipListener;
 import org.apache.geode.cache.client.internal.locator.wan.RemoteLocatorJoinRequest;
 import org.apache.geode.distributed.internal.DistributionConfig;
@@ -26,12 +24,9 @@ import org.apache.geode.distributed.internal.DistributionConfigImpl;
 import org.apache.geode.distributed.internal.WanLocatorDiscoverer;
 import org.apache.geode.internal.admin.remote.DistributionLocatorId;
 import org.apache.geode.logging.internal.executors.LoggingExecutors;
-import org.apache.geode.logging.internal.log4j.api.LogService;
 
 public class WanLocatorDiscovererImpl implements WanLocatorDiscoverer {
 
-  private static final Logger logger = LogService.getLogger();
-
   private volatile boolean stopped = false;
 
   private ExecutorService _executor;
@@ -65,16 +60,15 @@ public class WanLocatorDiscovererImpl implements WanLocatorDiscoverer {
    */
   private void exchangeLocalLocators(int port, DistributionConfigImpl config,
       LocatorMembershipListener locatorListener, final String hostnameForClients) {
-    String localLocator = config.getStartLocator();
-    DistributionLocatorId locatorId = null;
-
-    String memberName = config.getName();
+    final String localLocator = config.getStartLocator();
+    final String memberName = config.getName();
 
+    final DistributionLocatorId locatorId;
     if (localLocator.equals(DistributionConfig.DEFAULT_START_LOCATOR)) {
       locatorId = new DistributionLocatorId(port, config.getBindAddress(), hostnameForClients,
           memberName);
     } else {
-      locatorId = new DistributionLocatorId(localLocator, memberName);
+      locatorId = DistributionLocatorId.unmarshal(localLocator, memberName);
     }
 
     LocatorHelper.addLocator(config.getDistributedSystemId(), locatorId, locatorListener, null);
@@ -83,7 +77,7 @@ public class WanLocatorDiscovererImpl implements WanLocatorDiscoverer {
     StringTokenizer locatorsOnThisVM = new StringTokenizer(config.getLocators(), ",");
     while (locatorsOnThisVM.hasMoreTokens()) {
       DistributionLocatorId localLocatorId =
-          new DistributionLocatorId(locatorsOnThisVM.nextToken());
+          DistributionLocatorId.unmarshal(locatorsOnThisVM.nextToken());
       if (!locatorId.equals(localLocatorId)) {
         LocatorDiscovery localDiscovery =
             new LocatorDiscovery(this, localLocatorId, request, locatorListener);
@@ -106,7 +100,7 @@ public class WanLocatorDiscovererImpl implements WanLocatorDiscoverer {
       StringTokenizer remoteLocators = new StringTokenizer(remoteDistributedSystems, ",");
       while (remoteLocators.hasMoreTokens()) {
         DistributionLocatorId remoteLocatorId =
-            new DistributionLocatorId(remoteLocators.nextToken());
+            DistributionLocatorId.unmarshal(remoteLocators.nextToken());
         LocatorDiscovery localDiscovery =
             new LocatorDiscovery(this, remoteLocatorId, request, locatorListener);
         LocatorDiscovery.RemoteLocatorDiscovery remoteLocatorDiscovery =
@@ -118,20 +112,17 @@ public class WanLocatorDiscovererImpl implements WanLocatorDiscoverer {
 
   private RemoteLocatorJoinRequest buildRemoteDSJoinRequest(int port, DistributionConfigImpl config,
       final String hostnameForClients) {
-    String localLocator = config.getStartLocator();
-    DistributionLocatorId locatorId = null;
-
-    String memberName = config.getName();
+    final String localLocator = config.getStartLocator();
+    final String memberName = config.getName();
 
+    final DistributionLocatorId locatorId;
     if (localLocator.equals(DistributionConfig.DEFAULT_START_LOCATOR)) {
       locatorId = new DistributionLocatorId(port, config.getBindAddress(), hostnameForClients,
           memberName);
     } else {
-      locatorId = new DistributionLocatorId(localLocator, memberName);
+      locatorId = DistributionLocatorId.unmarshal(localLocator, memberName);
     }
-    RemoteLocatorJoinRequest request =
-        new RemoteLocatorJoinRequest(config.getDistributedSystemId(), locatorId, "");
-    return request;
+    return new RemoteLocatorJoinRequest(config.getDistributedSystemId(), locatorId, "");
   }
 
 }
diff --git a/geode-wan/src/test/java/org/apache/geode/cache/wan/internal/client/locator/LocatorHelperTest.java b/geode-wan/src/test/java/org/apache/geode/cache/wan/internal/client/locator/LocatorHelperTest.java
index aa2aff8a9f..b7f1b3a00c 100644
--- a/geode-wan/src/test/java/org/apache/geode/cache/wan/internal/client/locator/LocatorHelperTest.java
+++ b/geode-wan/src/test/java/org/apache/geode/cache/wan/internal/client/locator/LocatorHelperTest.java
@@ -31,7 +31,6 @@ import java.util.concurrent.ConcurrentMap;
 import org.junit.jupiter.api.Test;
 
 import org.apache.geode.cache.client.internal.locator.wan.LocatorMembershipListener;
-import org.apache.geode.distributed.Locator;
 import org.apache.geode.distributed.internal.InternalLocator;
 import org.apache.geode.internal.admin.remote.DistributionLocatorId;
 import org.apache.geode.internal.inet.LocalHostUtil;
@@ -48,7 +47,7 @@ class LocatorHelperTest {
 
   @Test
   void addServerLocatorDoesNotAddSameLocatorWithSameDistributedSystemId() {
-    final DistributionLocatorId locator = new DistributionLocatorId("localhost[1234]");
+    final DistributionLocatorId locator = DistributionLocatorId.unmarshal("localhost[1234]");
 
     addServerLocator(1, locatorMembershipListener, locator);
     assertThat(locators).containsExactly(entry(1, singleton("localhost[1234]")));
@@ -59,8 +58,8 @@ class LocatorHelperTest {
 
   @Test
   void addServerLocatorDoesNotAddEqualLocatorWithSameDistributedSystemId() {
-    final DistributionLocatorId locator1 = new DistributionLocatorId("localhost[1234]");
-    final DistributionLocatorId locator2 = new DistributionLocatorId("localhost[1234]");
+    final DistributionLocatorId locator1 = DistributionLocatorId.unmarshal("localhost[1234]");
+    final DistributionLocatorId locator2 = DistributionLocatorId.unmarshal("localhost[1234]");
 
     addServerLocator(1, locatorMembershipListener, locator1);
     assertThat(locators).containsExactly(entry(1, singleton("localhost[1234]")));
@@ -71,8 +70,8 @@ class LocatorHelperTest {
 
   @Test
   void addServerLocatorAddsUniqueLocatorWithSameDistributedSystemId() {
-    final DistributionLocatorId locator1 = new DistributionLocatorId("localhost[1234]");
-    final DistributionLocatorId locator2 = new DistributionLocatorId("localhost[1235]");
+    final DistributionLocatorId locator1 = DistributionLocatorId.unmarshal("localhost[1234]");
+    final DistributionLocatorId locator2 = DistributionLocatorId.unmarshal("localhost[1235]");
 
     addServerLocator(1, locatorMembershipListener, locator1);
     addServerLocator(1, locatorMembershipListener, locator2);
@@ -83,8 +82,8 @@ class LocatorHelperTest {
 
   @Test
   void addServerLocatorDoesNotAddsLocatorWithDifferentDistributedSystemId() {
-    final DistributionLocatorId locator1 = new DistributionLocatorId("localhost[1234]");
-    final DistributionLocatorId locator2 = new DistributionLocatorId("localhost[1235]");
+    final DistributionLocatorId locator1 = DistributionLocatorId.unmarshal("localhost[1234]");
+    final DistributionLocatorId locator2 = DistributionLocatorId.unmarshal("localhost[1235]");
 
     addServerLocator(1, locatorMembershipListener, locator1);
     addServerLocator(2, locatorMembershipListener, locator2);
@@ -98,7 +97,7 @@ class LocatorHelperTest {
   void addServerLocatorUsesHostnameForClients() {
     final DistributionLocatorId locator =
         new DistributionLocatorId(1234, "bind-address.example.com",
-            "hostname-for-clients.example.com");
+            "hostname-for-clients.example.com", null);
 
     addServerLocator(1, locatorMembershipListener, locator);
     assertThat(locators)
@@ -108,7 +107,7 @@ class LocatorHelperTest {
   @Test
   void addServerLocatorUsesBindAddress() {
     final DistributionLocatorId locator =
-        new DistributionLocatorId(1234, "bind-address.example.com");
+        new DistributionLocatorId(1234, "bind-address.example.com", null, null);
 
     addServerLocator(1, locatorMembershipListener, locator);
     assertThat(locators).containsExactly(entry(1, singleton("bind-address.example.com[1234]")));
@@ -119,7 +118,7 @@ class LocatorHelperTest {
       throws UnknownHostException {
     final InetAddress localHost = LocalHostUtil.getLocalHost();
 
-    final Locator locator = mock(InternalLocator.class);
+    final InternalLocator locator = mock(InternalLocator.class);
     when(locator.getPort()).thenReturn(1234);
 
     final DistributionLocatorId locatorId = new DistributionLocatorId(localHost, locator);
diff --git a/geode-wan/src/test/java/org/apache/geode/cache/wan/internal/client/locator/LocatorMembershipListenerTest.java b/geode-wan/src/test/java/org/apache/geode/cache/wan/internal/client/locator/LocatorMembershipListenerTest.java
index 53f0e3fe22..fe322e2188 100644
--- a/geode-wan/src/test/java/org/apache/geode/cache/wan/internal/client/locator/LocatorMembershipListenerTest.java
+++ b/geode-wan/src/test/java/org/apache/geode/cache/wan/internal/client/locator/LocatorMembershipListenerTest.java
@@ -71,7 +71,7 @@ public class LocatorMembershipListenerTest {
   public SystemOutRule systemOutRule = new SystemOutRule();
 
   private DistributionLocatorId buildDistributionLocatorId(int port) {
-    return new DistributionLocatorId("localhost[" + port + "]");
+    return DistributionLocatorId.unmarshal("localhost[" + port + "]");
   }
 
   private List<LocatorJoinMessage> buildPermutationsForClusterId(int dsId, int locatorsAmount) {
@@ -204,7 +204,7 @@ public class LocatorMembershipListenerTest {
 
     ExecutorService executorService = Executors.newFixedThreadPool(allJoinMessages.size());
     List<Future<Object>> futures = executorService.invokeAll(requests);
-    for (Future future : futures) {
+    for (Future<Object> future : futures) {
       Object response = future.get();
       assertThat(response).isNull();
     }
@@ -234,7 +234,7 @@ public class LocatorMembershipListenerTest {
 
     ExecutorService executorService = Executors.newFixedThreadPool(allJoinMessages.size());
     List<Future<Object>> futures = executorService.invokeAll(requests);
-    for (Future future : futures) {
+    for (Future<Object> future : futures) {
       Object response = future.get();
       assertThat(response).isNull();
     }