public void close() {

    try {
      if (sessionKey != RexProMessage.EMPTY_SESSION) {
        SessionRequestMessage sessionKillMessageToSend = new SessionRequestMessage();
        sessionKillMessageToSend.metaSetKillSession(true);
        sessionKillMessageToSend.setRequestAsUUID(UUID.randomUUID());

        // need to set the session here so that the server knows which one to delete.
        sessionKillMessageToSend.setSessionAsUUID(this.sessionKey);
        final RexProMessage rcvMessage = sendRequest(sessionKillMessageToSend, 3);

        // response message will have an EMPTY_SESSION
        if (rcvMessage instanceof SessionResponseMessage) {
          this.sessionKey = rcvMessage.sessionAsUUID();
        }

        rexProConnection.close();
        rexProConnection = null;
      }
    } catch (Exception ex) {
      // likely fail is a null pointer on the session
    } finally {
      this.sessionKey = RexProMessage.EMPTY_SESSION;
    }
  }
  public void open() {
    if (sessionKey == RexProMessage.EMPTY_SESSION) {
      SessionRequestMessage sessionRequestMessageToSend = new SessionRequestMessage();
      sessionRequestMessageToSend.Username = this.username;
      sessionRequestMessageToSend.Password = this.password;
      sessionRequestMessageToSend.setSessionAsUUID(SessionRequestMessage.EMPTY_SESSION);
      sessionRequestMessageToSend.setRequestAsUUID(UUID.randomUUID());

      try {
        sessionRequestMessageToSend.validateMetaData();
      } catch (RexProException e) {
        e.printStackTrace();
      }

      // if close() gets called then have to recreate the the connection here.  need to factor out
      // this
      // RexPro class.
      if (this.rexProConnection == null) {
        this.rexProConnection = new RexProClientConnection(rexProHost, rexProPort);
      }

      final RexProMessage rcvMessage = sendRequest(sessionRequestMessageToSend, 3);

      if (rcvMessage != null && rcvMessage instanceof SessionResponseMessage) {
        final SessionResponseMessage sessionResponseMessage = (SessionResponseMessage) rcvMessage;
        this.availableLanguages = new ArrayList<String>();
        for (String lang : sessionResponseMessage.Languages) {
          this.availableLanguages.add(lang);
        }

        this.sessionKey = rcvMessage.sessionAsUUID();
      }
    }
  }
  public RexProMessage sendRequest(
      RexProMessage request, int maxRetries, int waitMsBetweenTries, int timeoutSeconds) {
    int tries = 0;
    RexProMessage rcvMessage = null;

    // set the session for all incoming messages.
    request.setSessionAsUUID(this.getSessionKey());

    while (rcvMessage == null && tries < maxRetries) {
      tries++;

      try {
        rcvMessage = rexProConnection.sendMessage(request, timeoutSeconds);
      } catch (Exception ex) {
        String logMessage =
            "Failure sending message via RexPro. Attempt [" + tries + "] of [" + maxRetries + "].";

        if (tries < maxRetries) {
          logMessage = logMessage + " Trying again in " + waitMsBetweenTries + " (ms)";
        }

        logger.error(logMessage);

        rcvMessage = null;

        // wait
        try {
          Thread.sleep(waitMsBetweenTries);
        } catch (InterruptedException ie) {
          // carry on
        }
      }
    }

    return rcvMessage;
  }