code: public final Runnable watch(final GroupChangeListener groupChangeListener)
        throws WatchException, InterruptedException {
      Objects.requireNonNull(groupChangeListener);
  
      try {
        ensurePersistentGroupPath();
      } catch (JoinException e) {
        throw new WatchException("Failed to create group path: " + path, e);
      }
  
      final GroupMonitor groupMonitor = new GroupMonitor(groupChangeListener);
      backoffHelper.doUntilSuccess(new ExceptionalSupplier<Boolean, WatchException>() {
        @Override public Boolean get() throws WatchException {
          try {
            groupMonitor.watchGroup();
            return true;
          } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new WatchException("Interrupted trying to watch group at path: " + path, e);
          } catch (ZooKeeperConnectionException e) {
            LOG.log(Level.WARNING, "Temporary error trying to watch group at path: " + path, e);
            return null;
          } catch (KeeperException e) {
            if (zkClient.shouldRetry(e)) {
              LOG.log(Level.WARNING, "Temporary error trying to watch group at path: " + path, e);
              return null;
            } else {
              throw new WatchException("Problem trying to watch group at path: " + path, e);
            }
          }
        }
      });
      return new Runnable() {
        @Override public void run() {
          groupMonitor.stopWatching();
        }
      };
    }
docs: Watches this group for the lifetime of this jvm process.  This method will block until the
  current group members are available, notify the {@code groupChangeListener} and then return.
  All further changes to the group membership will cause notifications on a background thread.
  
  @param groupChangeListener the listener to notify of group membership change events
  @return A command which, when executed, will stop watching the group.
  @throws WatchException if there is a problem generating the 1st group membership list
  @throws InterruptedException if interrupted waiting to gather the 1st group membership list