Download
FAQ History |
![]() ![]() ![]() |
API
Search Feedback |
Delegating Rendering to a Renderer
For the purpose of illustrating delegated rendering, the image map example includes an
AreaRenderer
, which performs the rendering for theUIArea
component.To delegate rendering, you need to perform these tasks:
Create the Renderer Class
When delegating rendering to a renderer, you can delegate all encoding and decoding to the renderer, or you can choose to do part of it in the component class. The
UIArea
component class only requires encoding.To delegate the encoding to
AreaRenderer
, the AreaRenderer needs to implement anencodeEnd
method.The encoding methods in a
Renderer
are just like those in aUIComponent
class except that they accept aUIComponent
argument as well as aFacesContext
argument, whereas theencodeEnd
method defined byUIComponentBase
only takes aFacesContext
. TheUIComponent
argument is the component that needs to be rendered. In the case of non-delegated rendering, the component is rendering itself. In the case of delegated rendering, the renderer needs to be told what component it is rendering. So you need to pass the component to theencodeEnd
method ofAreaRenderer
:The
encodeEnd
method ofAreaRenderer
must retrieve the shape, coordinates, and alt values stored in theImageArea
model object that is bound to theUIArea
component. Suppose that thearea
tag currently being rendered has avalueRef
attribute value of"fraA"
. The following line fromencodeEnd
gets thevalueRef
value of"fraA"
and uses it to get the value of the attribute"fraA"
from the FacesContext.The attribute value is the
ImageArea
model object instance, which contains the shape, coordinates, and alt values associated with thefraA
UIArea
component instance.Simplifying the JSP Page describes how the application stores these values.
After retrieving the
ImageArea
object, you render the values forshape
,coords
, andalt
by simply calling the associated accessor methods and passing the returned values to theResponseWriter
, as shown by these lines of code, which write out the shape and coordinates:writer.write("<area shape=\""); writer.write(ia.getShape()); writer.write("\"" ); writer.write(" coords=\""); writer.write(ia.getCoords());The
encodeEnd
method also renders the JavaScript for theonmouseout
,onmouseover
, andonclick
attributes. The page author only needs to provide the path to the images that are to be loaded during anonmouseover
oronmouseout
action:<d:area id="France" valueRef="fraA" onmouseover="/cardemo/world_france.jpg" onmouseout="/cardemo/world.jpg" />The
AreaRenderer
class takes care of generating the JavaScript for these actions, as shown in this code fromencodeEnd
:writer.write(" onmouseover=\""); writer.write("document.forms[0].mapImage.src='"); imagePath = (String) component.getAttribute("onmouseover"); if ('/' == imagePath.charAt(0)) { writer.write(imagePath); } else { writer.write(contextPath + imagePath); } writer.write("';\""); writer.write(" onmouseout=\""); writer.write("document.forms[0].mapImage.src='"); imagePath = (String) component.getAttribute("onmouseout"); if ('/' == imagePath.charAt(0)) { writer.write(imagePath); } else { writer.write(contextPath + imagePath); }The JavaScript that
AreaRenderer
generates for theonclick
action sets the value of the hidden variable,selectedArea
, to the value of the current area's component ID and submits the page:writer.write("\" onclick=\"document.forms[0].selectedArea.value='"); writer.write(component.getComponentId()); writer.write("'; document.forms[0].submit()\""); writer.write(" onmouseover=\""); writer.write("document.forms[0].mapImage.src='");By submitting the page, this code causes the JavaServer Faces lifecycle to return back to the Reconstitute Component Tree phase. This phase saves any state information--including the value of the
selectedArea
hidden variable--so that a new request component tree is constructed. This value is retrieved by thedecode
method of theUIMap
component class. Thisdecode
method is called by the JavaServer Faces implementation during the Apply Request Values phase, which follows the Reconstitute Request Tree phase.In addition to the
encodeEnd
method,AreaRenderer
also contains an empty constructor. This will be used to create an instance ofAreaRenderer
so that it can be added to the render kit.
AreaRenderer
also must implement thedecode
method and the other encoding methods, whether or not they are needed.Finally,
AreaRenderer
requires an implementation ofsupportsComponentType
:public boolean supportsComponentType(String componentType) { if ( componentType == null ) { throw new NullPointerException(); } return (componentType.equals(UIArea.TYPE)); }This method returns
true
whencomponentType
equalsUIArea
's component type, indicating thatAreaRenderer
supports theUIArea
component.Note that
AreaRenderer
extendsBaseRenderer
, which in turn extendsRenderer
. TheBaseRenderer
class is included in the RI of JavaServer Faces technology. It contains definitions of theRenderer
class methods so that you don't have to include them in your renderer class.Register the Renderer with a Render Kit
For every UI component that a render kit supports, the render kit defines a set of
Renderer
objects that can render the component in different ways to the client supported by the render kit. For example, the standardUISelectOne
component class defines a component that allows a user to select one item out of a group of items. This component can be rendered with theListbox
renderer, theMenu
renderer, or theRadio
renderer. Each renderer produces a different appearance for the component. TheListbox
renderer renders a menu that displays all possible values. TheMenu
renderer renders a subset of all possible values. TheRadio
renderer renders a set of radio buttons.When you create a custom renderer, you need to register it with the appropriate render kit. Since the image map application implements an HTML image map,
AreaRenderer
should be registered with the HTML render kit.You register the renderer using the application configuration file (see Application Configuration (page 807)):
<render-kit> <renderer> <renderer-type>Area</renderer-type> <renderer-class> components.renderkit.AreaRenderer </renderer-class> </renderer> </render-kit>The
render-kit
element represents aRenderKit
implementation. If norender-kit-id
is specified, the default HTML render kit is assumed. The renderer element represents aRenderer
implementation. By nesting therenderer
element inside therender-kit
element, you are registering the renderer with theRenderKit
associated with therender-kit
element.The
renderer-type
will be used by the tag handler, as explained in the next section. Therenderer-class
is the fully-qualified classname of theRenderer
.Identify the Renderer Type
During the Render Response phase, the JavaServer Faces implementation calls the
getRendererType
method of the component's tag to determine which renderer to invoke, if there is one.The
getRendererType
method ofAreaTag
must return the type associated withAreaRenderer
. Recall that you identified this type when you registeredAreaRenderer
with the render kit. Here is thegetRendererType
method from thecardemo
application'sAreaTag
class:
Download
FAQ History |
![]() ![]() ![]() |
API
Search Feedback |
All of the material in The Java(TM) Web Services Tutorial is copyright-protected and may not be published in other works without express written permission from Sun Microsystems.