protected void service(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
    Writer output = new OutputStreamWriter(resp.getOutputStream(), "utf-8");
    Reader input = new InputStreamReader(req.getInputStream(), "utf-8");
    resp.setContentType("application/json; charset=utf-8");

    try {
      String path = req.getPathInfo();
      String search = req.getParameter("search");
      if (path.startsWith("/customers")) {
        String id =
            path.length() >= 11
                ? URLDecoder.decode(path.substring("/customers/".length()), "utf-8")
                : "";
        if (!id.isEmpty() && "GET".equals(req.getMethod())) {
          StoredCustomer customer = getXmlStore().findCustomerById(id);
          if (customer != null) {
            JsonHelper.instance().toJson(customer, output);
          } else {
            resp.setStatus(404);
          }
        } else if ("POST".equals(req.getMethod())) {
          Customer customer = JsonHelper.instance().fromJson(input);
          StoredCustomer stored = getXmlStore().addCustomer(customer);
          JsonHelper.instance().toJson(stored, output);
        } else if (!id.isEmpty() && "PUT".equals(req.getMethod())) {
          Customer customer = JsonHelper.instance().fromJson(input);
          if (!getXmlStore().updateCustomerById(id, customer)) {
            resp.setStatus(404);
          } else {
            JsonHelper.instance().toJson(customer, output);
          }
        } else if (!id.isEmpty() && "DELETE".equals(req.getMethod())) {
          if (!getXmlStore().deleteCustomerById(id)) resp.setStatus(404);
        } else if (search != null) {
          Collection<StoredCustomer> customers = getXmlStore().findCustomersByText(search);
          JsonHelper.instance().toJson(customers, output);
        } else {
          Collection<StoredCustomer> customers = getXmlStore().findAllCustomers();
          JsonHelper.instance().toJson(customers, output);
        }
      } else if ("/types".equals(path)) {
        JsonHelper.instance().toJsonTypes(output);
      } else {
        resp.setStatus(404);
      }

    } catch (Throwable e) {
      resp.setStatus(500);
      error(output, "Exception: " + e);
    }

    output.flush();
  }
 private void error(Writer output, String error) {
   JsonHelper.instance().errorJson(error, output);
 }