Is there a way to get the generated HTML as a String from a UIComponent object?
Asked Answered
R

2

10

I have a UIComponent object. I would like to get the HTML code generated by this component at runtime so I can analyze it.

Is there a way to achieve this?

I am trying to use JsfUnit to create automated tests. I can get ahold of the UICompoment objects from within the test methods. However, I couldn't find a way to check the Html generated by the component.

Rinna answered 6/6, 2013 at 14:48 Comment(2)
Do you want to analyze it manually? If so then just inspect the html from your browser using for example Firebug; If not, then - what are you really trying to do?Orling
@dratewka, I have improved my question so you can understand what I am trying to achieve.Rinna
S
11

Just do the same what JSF does under the covers: invoke UIComponent#encodeAll(). To capture the output, set the response writer to a local buffer by FacesContext#setResponseWriter().

E.g. (assuming that you're sitting in invoke application phase; when sitting in render response phase, this needs to be done differently):

FacesContext context = FacesContext.getCurrentInstance();
ResponseWriter originalWriter = context.getResponseWriter();
StringWriter writer = new StringWriter();

try {
    context.setResponseWriter(context.getRenderKit().createResponseWriter(writer, "text/html", "UTF-8"));
    component.encodeAll(context);
} finally {
    if (originalWriter != null) {
        context.setResponseWriter(originalWriter);
    }
}

String output = writer.toString();
// ...
Sinistrodextral answered 8/6, 2013 at 17:11 Comment(2)
perfect BalusC! I have used this code on the test environment and it works! Thanks a lot.Rinna
great answer, as usual, thanks. Could you please elaborate on "when sitting in render response phase, this needs to be done differently"?Umiak
U
2

Solution by BalusC to invoke UIComponent#encodeAll()generally works, but I had a problem with unicode characters when using utf-8 encoding. All non-ascii characters in ajax response were damaged after I modified current context's response writer.

Instead of modifying response writer on current context retrieved by FacesContext.getCurrentInstance(), I created a wrapper over current context by extending FacesContextWrapper, so that original context is left unmodified:

StringWriter writer = new StringWriter();
FacesContext context = new FacesContextWrapper() {
    private ResponseWriter internalWriter = getWrapped()
        .getRenderKit().createResponseWriter(writer, "text/html", "UTF-8");

    @Override
    public FacesContext getWrapped() {
        return FacesContext.getCurrentInstance();
    }

    @Override
    public ResponseWriter getResponseWriter() {
        return internalWriter;
    }

};

component.encodeAll(context);
String output = writer.toString();
Urba answered 15/4, 2014 at 13:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.