Usually the javax.faces.context.ResponseWriter is used in
renderers of JSF components. When we write a custom component, typically we
render the HTML markup by using the ResponseWriter in encodeXxx() methods. The main methods
that are able to render markup code are startElement(), writeText(), writeAttribute(), writeURIAttribute
() and endElement()
methods. Per example, if we check the OmniFaces 2.0 code of GraphicImage
component, you can see that encodeBegin() and encodeEnd() uses these
methods:
@Override
public void
encodeBegin(FacesContext context) throws IOException {
ResponseWriter writer =
context.getResponseWriter();
writer.startElement("img", this);
writer.writeURIAttribute("src",
getSrc(context), "value");
writeAttributes(writer, this,
GraphicImage.ATTRIBUTE_NAMES);
}
@Override
public void
encodeEnd(FacesContext context) throws IOException {
ResponseWriter writer =
context.getResponseWriter();
writer.endElement("img");
}
Nothing fancy here! But, sometimes, when we write custom
components that extends existent components, we need to capture (or supress) a chunk
of markup rendered for the extended component. OmniFaces uses a three steps
technique:
·
at first step, it clones the existing ResponseWriter,
by using the ResponseWriter.cloneWithWriter()
method. In order to accomplish this, it needs the "original" ResponseWriter,
and a new ResponseWriter
(e.g. StringWriter)
FacesContext context;
ResponseWriter
originalResponseWriter = context.getResponseWriter();
StringWriter
output = new StringWriter();
context.setResponseWriter(originalResponseWriter.cloneWithWriter(output));
...
·
further, OmniFaces calls a method that produce
direct (or indirect) the markup that should be captured and/or suppressed (e.g.
encodeBegin(),
encodeChildren(),
encodeEnd()).
Any of these methods will write the markup in the OmniFaces response writer,
instead of the "original" one.
·
at final step, OmniFaces
"releases" the "original" ResponseWriter and process
the captured content (the content of the output writer).
...
context.setResponseWriter(originalResponseWriter);
In the below figure you can see this technique used in the
OmniFaces, Param
component - I just cropped the code to reveal the technique, so don't try to
understand the Param
component itself from here:
This is a very cool technique that allows us to manipulate
exitent markup in many ways. Is nice to have it in your arsenal!
Niciun comentariu :
Trimiteți un comentariu