// -------------------- Jk handler implementation --------------------
  // Jk Handler mehod
  public int invoke(Msg msg, MsgContext ep) throws IOException {
    if (ep.isLogTimeEnabled()) ep.setLong(MsgContext.TIMER_PRE_REQUEST, System.currentTimeMillis());

    Request req = ep.getRequest();
    Response res = req.getResponse();

    if (log.isDebugEnabled())
      log.debug("Invoke " + req + " " + res + " " + req.requestURI().toString());

    res.setNote(epNote, ep);
    ep.setStatus(MsgContext.JK_STATUS_HEAD);
    RequestInfo rp = req.getRequestProcessor();
    rp.setStage(Constants.STAGE_SERVICE);
    try {
      adapter.service(req, res);
    } catch (Exception ex) {
      log.info("Error servicing request " + req, ex);
    }
    if (ep.getStatus() != MsgContext.JK_STATUS_CLOSED) {
      res.finish();
    }

    req.updateCounters();
    req.recycle();
    res.recycle();
    ep.recycle();
    if (ep.getStatus() == MsgContext.JK_STATUS_ERROR) {
      return ERROR;
    }
    ep.setStatus(MsgContext.JK_STATUS_NEW);
    rp.setStage(Constants.STAGE_KEEPALIVE);
    return OK;
  }
  @Override
  public void errorDispatch(org.apache.coyote.Request req, org.apache.coyote.Response res) {
    Request request = (Request) req.getNote(ADAPTER_NOTES);
    Response response = (Response) res.getNote(ADAPTER_NOTES);

    if (request != null && request.getMappingData().context != null) {
      ((Context) request.getMappingData().context)
          .logAccess(request, response, System.currentTimeMillis() - req.getStartTime(), false);
    } else {
      log(req, res, System.currentTimeMillis() - req.getStartTime());
    }

    if (request != null) {
      request.recycle();
    }

    if (response != null) {
      response.recycle();
    }

    req.recycle();
    res.recycle();
  }