Render a Wicket page to a string for HTML email

Something that\’s very desirable to do in Apache Wicket is create HTML emails using Wicket\’s brilliant component-oriented markup.

I\’ve been working on this problem on and off for ages — it\’s tricky because of teh way that markup rendering is so deeply tied to the requestcycle, which in turn is deeply dependent on the httpservletrequest — with good reason, too. That\’s where Wicket gets its autoconfiguring magic from!

So in order to use Wicket to create HTML emails, we need to fake the request/response cycle. I wrote this convenient method that renders a bookmarkable page (pageclass + pageparameters) to a string:

protected String renderPage(Class<? extends Page> pageClass, PageParameters pageParameters) {

        //get the servlet context
        WebApplication application = (WebApplication) WebApplication.get();

        ServletContext context = application.getServletContext();

        //fake a request/response cycle
        MockHttpSession servletSession = new MockHttpSession(context);
        servletSession.setTemporary(true);

        MockHttpServletRequest servletRequest = new MockHttpServletRequest(
                application, servletSession, context);
        MockHttpServletResponse servletResponse = new MockHttpServletResponse(
                servletRequest);

        //initialize request and response
        servletRequest.initialize();
        servletResponse.initialize();

        WebRequest webRequest = new WebRequest(servletRequest);

        BufferedWebResponse webResponse = new BufferedWebResponse(servletResponse);
        webResponse.setAjax(true);

        WebRequestCycle requestCycle = new WebRequestCycle(
                application, webRequest, webResponse);

        requestCycle.setRequestTarget(new BookmarkablePageRequestTarget(pageClass, pageParameters));

        try {
            requestCycle.request();

            log.warn("Response after request: "+webResponse.toString());

            if (requestCycle.wasHandled() == false) {
                requestCycle.setRequestTarget(new WebErrorCodeResponseTarget(
                        HttpServletResponse.SC_NOT_FOUND));
            }
            requestCycle.detach();

        } finally {
            requestCycle.getResponse().close();
        }

        return webResponse.toString();
    }

One other thing that\’s desirable to do is change all relative links in the email to absolute URLs — something that Wicket makes super-easy, if you know how. That will be the subject of my next post.