@Override
 public void clientDisconnected(String userId, String clientId) {
   ClientConnection connection = getConnectionByClientId(userId, clientId);
   _connectionsByClientId.remove(clientId);
   _changeManager.removeChangeListener(connection);
   _masterChangeManager.removeChangeListener(connection);
   _longPollingConnectionManager.disconnect(clientId);
   connection.disconnect();
 }
 /**
  * Creates a new connection for a client and returns its client ID. The client ID should be used
  * by the client when subscribing for asynchronous updates. A connection typically corresponds to
  * a single browser tab or window. A user can have multiple simultaneous connections.
  *
  * @param userId The ID of the user creating the connection
  * @return The client ID of the new connection, must be supplied by the client when subscribing
  *     for updates
  */
 @Override
 public String clientConnected(String userId) {
   // TODO check args
   String clientId = Long.toString(_clientConnectionId.getAndIncrement());
   ConnectionTimeoutTask timeoutTask = new ConnectionTimeoutTask(this, userId, clientId, _timeout);
   LongPollingUpdateListener updateListener =
       _longPollingConnectionManager.handshake(userId, clientId, timeoutTask);
   ClientConnection connection =
       new ClientConnection(userId, clientId, updateListener, _viewportFactory, timeoutTask);
   _changeManager.addChangeListener(connection);
   _masterChangeManager.addChangeListener(connection);
   _connectionsByClientId.put(clientId, connection);
   _timer.scheduleAtFixedRate(timeoutTask, _timeoutCheckPeriod, _timeoutCheckPeriod);
   return clientId;
 }