public void invoke(HttpServletRequest req, HttpServletResponse resp) throws IOException {
      //            L.trace("begin invoke");
      QueryParams qp = QueryParams.create(req);
      //        	L.trace("end query params create");
      try {
        Class[] pts = method.getParameterTypes();
        Object[] ps = new Object[pts.length];
        for (int i = 0; i < pts.length; i++) {
          Class pt = pts[i];
          if (pt.isAssignableFrom(QueryParams.class)) {
            ps[i] = qp;
          } else if (pt.isAssignableFrom(HttpServletRequest.class)) {
            ps[i] = req;
          } else if (pt.isAssignableFrom(HttpServletResponse.class)) {
            ps[i] = resp;
          }
        }

        Throwable err = null;
        Object r = null;
        try {
          method.setAccessible(true);
          //                    L.trace("begin invoke method");
          r = method.invoke(obj, ps);
          //                    L.trace("end invoke method");
        } catch (InvocationTargetException e) {
          err = e.getTargetException();
        } catch (Throwable t) {
          err = t;
        }

        if (err != null) {
          writeError(err, qp, req, resp, printErrorDetails);
        } else {
          if (r instanceof NoResponse) {
            // do nothing
          } else if (r instanceof DirectResponse) {
            DirectResponse dr = (DirectResponse) r;
            output(qp, req, resp, dr.content, 200, dr.contentType);
          } else {
            String json = JsonUtils.toJson(wrapSingleton(r), true);
            //                        output(resp, json, 200, "application/json");
            output(qp, req, resp, json, 200, "text/plain");
          }
        }
      } finally {
        if (qp != null) qp.close();
      }
      //            L.trace("end invoke");
    }