private void handleClientMessage(ClientMessage clientMessage)
        throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException,
            InvocationTargetException, InstantiationException {
      int correlationId = clientMessage.getCorrelationId();

      final ClientInvocation future = deRegisterCallId(correlationId);
      if (future == null) {
        logger.warning("No call for callId: " + correlationId + ", response: " + clientMessage);
        return;
      }

      if (ErrorCodec.TYPE == clientMessage.getMessageType()) {
        ErrorCodec exParameters = ErrorCodec.decode(clientMessage);
        Throwable exception =
            clientExceptionFactory.createException(
                exParameters.errorCode,
                exParameters.className,
                exParameters.message,
                exParameters.stackTrace,
                exParameters.causeErrorCode,
                exParameters.causeClassName);
        future.notifyException(exception);
      } else {
        future.notify(clientMessage);
      }
    }
 private ClientMessage createExceptionMessage(Throwable throwable) {
   ClientExceptionFactory clientExceptionFactory = clientEngine.getClientExceptionFactory();
   int errorCode = clientExceptionFactory.getErrorCode(throwable);
   String message = throwable.getMessage();
   StackTraceElement[] stackTrace = throwable.getStackTrace();
   Throwable cause = throwable.getCause();
   boolean hasCause = cause != null;
   String className = throwable.getClass().getName();
   if (hasCause) {
     int causeErrorCode = clientExceptionFactory.getErrorCode(cause);
     String causeClassName = cause.getClass().getName();
     return ErrorCodec.encode(
         errorCode, className, message, stackTrace, causeErrorCode, causeClassName);
   } else {
     return ErrorCodec.encode(
         errorCode, className, message, stackTrace, ClientProtocolErrorCodes.UNDEFINED, null);
   }
 }