protected void doEchoResponse(HttpServletRequest req, HttpServletResponse resp, boolean withBody) throws IOException {
        String acceptHeader = req.getHeader("Accept");
        String errorCode = req.getHeader("X-Echo-ErrorCode");
        if (errorCode != null) {
            int ec = Integer.parseInt(errorCode);
            String errorMsg = req.getHeader("X-Echo-ErrorMessage");
            resp.sendError(ec, errorMsg);
            return;
        }

        String queryString = req.getQueryString();
        if (queryString != null && queryString.startsWith("redirectTo=")) {
            String redirectTo = queryString.substring(11);
            resp.sendRedirect(redirectTo);
            return;
        }

        boolean isXml = acceptHeader != null && acceptHeader.contains("application/xml");

        EchoResponse response = response(req, withBody);
        response.setCounter(++servletCounter);
        resp.setHeader("Response-Counter", response.getCounter().toString());

        if (isXml) {
            resp.setContentType("application/xml");
            try {
                Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
                jaxbMarshaller.marshal(response, resp.getOutputStream());
                IOUtils.closeQuietly(resp.getOutputStream());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        } else {
            resp.setContentType("application/json");
            try {
                mapper.writeValue(resp.getOutputStream(), response);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
Responds with a comprehensive echo.  This means bundling up all the
information about the inbound request into a java bean and responding
with that data as a JSON response.
@param req
@param resp
@param withBody
test/common/src/main/java/io/apiman/test/common/mock/EchoServlet.java