public void releaseConnection(NHttpClientConnection conn) {
   if (conn == null) {
     return;
   }
   if (this.shutdown) {
     return;
   }
   synchronized (this.lock) {
     if (this.allConns.contains(conn)) {
       if (conn.isOpen()) {
         conn.setSocketTimeout(0);
         AsyncConnectionRequest request = this.pendingRequests.poll();
         if (request != null) {
           System.out.println("Re-using persistent connection");
           request.setConnection(conn);
         } else {
           this.availableConns.add(conn);
         }
       } else {
         this.allConns.remove(conn);
         processRequests();
       }
     }
   }
 }
  /**
   * Send the request message asynchronously to the given EPR
   *
   * @param epr the destination EPR for the message
   * @param msgContext the message being sent
   * @throws AxisFault on error
   */
  private void sendAsyncRequest(EndpointReference epr, MessageContext msgContext) throws AxisFault {
    try {
      URL url = new URL(epr.getAddress());
      String scheme = url.getProtocol() != null ? url.getProtocol() : "http";
      String hostname = url.getHost();
      int port = url.getPort();
      if (port == -1) {
        // use default
        if ("http".equals(scheme)) {
          port = 80;
        } else if ("https".equals(scheme)) {
          port = 443;
        }
      }
      HttpHost target = new HttpHost(hostname, port, scheme);
      boolean secure = "https".equalsIgnoreCase(target.getSchemeName());

      HttpHost proxy = proxyConfig.selectProxy(target);

      HttpRoute route;
      if (proxy != null) {
        route = new HttpRoute(target, null, proxy, secure);
      } else {
        route = new HttpRoute(target, null, secure);
      }
      Axis2HttpRequest axis2Req = new Axis2HttpRequest(epr, route, msgContext);
      Object timeout = msgContext.getProperty(NhttpConstants.SEND_TIMEOUT);
      if (timeout != null && timeout instanceof Long) {
        axis2Req.setTimeout((int) ((Long) timeout).longValue());
      }

      NHttpClientConnection conn = connpool.getConnection(route);

      // Ensure MessageContext has a ClientConnectionDebug attached before we start streaming
      ServerConnectionDebug scd =
          (ServerConnectionDebug) msgContext.getProperty(ServerHandler.SERVER_CONNECTION_DEBUG);

      ClientConnectionDebug ccd;
      if (scd != null) {
        ccd = scd.getClientConnectionDebug();
        if (ccd == null) {
          ccd = new ClientConnectionDebug(scd);
          scd.setClientConnectionDebug(ccd);
        }
        ccd.recordRequestStartTime(conn, axis2Req);
        msgContext.setProperty(ClientHandler.CLIENT_CONNECTION_DEBUG, ccd);
      }

      if (conn == null) {
        HttpHost host = route.getProxyHost() != null ? route.getProxyHost() : route.getTargetHost();
        ioReactor.connect(
            new InetSocketAddress(host.getHostName(), host.getPort()),
            null,
            axis2Req,
            sessionRequestCallback);
        if (log.isDebugEnabled()) {
          log.debug("A new connection established to : " + route);
        }
      } else {
        conn.setSocketTimeout(socketTimeout); // reinitialize timeouts for the pooled connection
        try {
          handler.submitRequest(conn, axis2Req);
          if (log.isDebugEnabled()) {
            log.debug("An existing connection reused to : " + hostname + ":" + port);
          }
        } catch (ConnectionClosedException e) {
          ioReactor.connect(
              new InetSocketAddress(hostname, port), null, axis2Req, sessionRequestCallback);
          if (log.isDebugEnabled()) {
            log.debug("A new connection established to : " + hostname + ":" + port);
          }
        }
      }
      try {
        axis2Req.streamMessageContents();
      } catch (AxisFault af) {
        throw af;
      }

    } catch (MalformedURLException e) {
      handleException("Malformed destination EPR : " + epr.getAddress(), e);
    }
  }