Tuesday, August 20, 2013

for..in vs. Object.keys performance in JavaScript

For those curious, you may debate if the JavaScript for..in loop is faster than creating an array via Object.keys and iterating over that array.

Take an object with 26 attributes:

var attrs = {"a":1,"b":2,c:3,d:4,e:5,f:6,g:7,h:8,i:9,j:10,k:11,l:12,m:13,n:14,o:15,p:16,q:17,r:18,s:19,t:20,u:21,v:22,w:23,x:24,y:25,z:26}

Now run this code in a browser (non-IE would be best):

// Loop #1
var date = (new Date()).getTime();
for (var i = 0; i < 100000; ++i)
{
  for (var attr in attrs)
  {
    var num=attrs[attr];
  }
};
var endDate = (new Date()).getTime();
console.log(endDate - date);

// Loop #2
date = (new Date()).getTime();
for (var i = 0; i < 100000; ++i)
{
  var keys = Object.keys(attrs);
  for (var k=0, ksize = keys.length; k < ksize; ++k)
  {
    var num=attrs[keys[k]];
  }
};
endDate = (new Date()).getTime();
console.log(endDate - date);

In Chrome on a Mac, the first loop takes about 2000-3000ms and the second loop 4000-5000ms. In Safari on a Mac, it will take 500-1000ms for the first loop and 1000-2000ms for the second loop. Obviously the code above could be improved for loop #2 if the "var keys..." was outside of the outer for loop, but this test is to simulate a real app where the objects being iterated over would change and not always be the same. The conclusion is simply that for..in is about twice as fast as using Object.keys and iterating over the resulting array.

Thursday, October 25, 2012

Creating an adaptive layout in ADF for desktop vs. tablet

It is often ideal to create pages tailored to be accessed on a mobile device or on the desktop, but not every company has the resources to author and maintain two web sites. What if you could define most of your pages to be the same for both devices but simply adapt the layout based on the device?

The Oracle ADF framework has the necessary tools to make this easy. For example, take an application where you desire to show a list of navigation links that is always accessible and a main content area. On the desktop, you usually have a larger screen that you can work with. There you may choose to use a splitter pane that the user can collapse that is shown on the left side of the browser. On the right would be the details of the current page. On a mobile device, you may not be able to spare the width required to show the splitter and would instead rather show the navigation links in a popup.

The solution is fairly simple in ADF, by leveraging the dynamic declarative component, facet references and JSTL tags (that are supported in either facelets or JSP), you can have a layout that easily adapts to the device.

To create such a site, first create an ADF application. You can do so by downloading a 11.1.2.3.0 JDeveloper from the JDeveloper OTN page. Open JDeveloper and create a new Fusion Web Application (ADF) and accept the defaults. Create a new Page (either JSP or facelets based on your preference). In that page, you will want to add a reference to a page fragment that defines the content for a dynamic declarative component (note that a page template will also work and will allow you to pass an ADF model page template binding if desired). In this component, you will want to pass 2 facets, one for the navigation and one for the body. Should you want the same navigation on every page, you could create a page template and include the declarative component from the page template.

The technique allows you to define the content for the navigation area and the content separately from the layout. By passing these areas as faces to a declarative component, it allows you to dynamically place the content into different locations based on the device.

Example index page showing the usage of the declarative component:

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<f:view xmlns:f="http://java.sun.com/jsf/core" xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
  <af:document title="index.jsf" id="d1">
    <af:form id="f1">
      <af:declarativeComponent id="dc" viewId="/dynamicLayout.jsff">
        <f:facet name="navigation">
          <af:navigationPane hint="list" id="np1">
            <af:commandNavigationItem text="Home" id="cni1"/>
            <af:commandNavigationItem text="Manage items 1" id="cni2"/>
            <af:commandNavigationItem text="Manage items 2" id="cni3"/>
            <af:commandNavigationItem text="Manage items 3" id="cni4"/>
            <af:commandNavigationItem text="Manage items 4" id="cni5"/>
            <af:commandNavigationItem text="Manage items 5" id="cni6"/>
            <af:commandNavigationItem text="Manage items 6" id="cni7"/>
            <af:commandNavigationItem text="Manage items 7" id="cni8"/>
            <af:commandNavigationItem text="Manage items 8" id="cni9"/>
            <af:commandNavigationItem text="Manage items 9" id="cni10"/>
            <af:commandNavigationItem text="Manage items 10" id="cni11"/>
            <af:commandNavigationItem text="Manage items 11" id="cni12"/>
            <af:commandNavigationItem text="Manage items 12" id="cni13"/>
            <af:commandNavigationItem text="Manage items 13" id="cni14"/>
            <af:commandNavigationItem text="Manage items 14" id="cni15"/>
            <af:commandNavigationItem text="Manage items 15" id="cni16"/>
            <af:commandNavigationItem text="Manage items 16" id="cni17"/>
            <af:commandNavigationItem text="Manage items 17" id="cni18"/>
          </af:navigationPane>
        </f:facet>
        <f:facet name="content">
          <af:panelGroupLayout layout="scroll" id="pgl2">
            <af:outputText value="lorem ipsum dolor sit amet officia modi anim voluptas studiosius. viribus doloribus tempus, ratione quasi. voluptates laborum quis, unum rerum. quamque cumque dolor explicabo reprehenderit. maiores nostrud ad, mites quidem. honestam quamque placeat, Et propter. ad anim cum acceperat Ut. mollitia iure humani, quaerat acceperat. nec eos culpa reprehenderit dignissimos. aspernatur feris laboriosam dolore.
lorem ipsum dolor sit amet repellat et molestias liberos quia. fugiat enim sint, reddidit earum. magnam eveniet id ut necessitatibus. reprehenderit aliquam commodo viribus dolor. et voluptate et, reprehenderit non. esse reiciendis reddere; culpa.
lorem ipsum dolor sit amet non voluptatem sapiens. officia harum illum ita rerum. iste in ipsa perniciosissimis natus. passim esse abditos animi dolore. quibusdam irure ut, Quis ipsum. tenetur victu ut enim quos. illum orationem se, delectus reddere;. sed velit velit, eaque aliqua. aliquam sapiente lorem voluptatum dolore. aut fugiat totam rerum.
lorem ipsum dolor sit amet nondum voluptatem ab. primo Duis propagabant consequatur non. dolor quia victu quid dolore. dolorem eos Sed odio inscientiam. id aut in, et facilis. quo deserunt sed, sint errorem. studiosius delectus maxime qui ducimus. sapiens soluta alias labore ex. et corporis unam non se. nisi corporis et expedita.
lorem ipsum dolor sit amet facere ex occaecati. magnam quae reprehenderit, culpa acceperat. natus nesciunt quia lorem iste. qui eu aequabile quisquam.
lorem ipsum dolor sit amet quadam earum quidam. perferendis in in, optio dolor. expedita cognovit rerum minus quia. quas qui quanta fuga deleniti. quam labore deinde ducimus materia. praesentium non saepe, si ut. voluptas quia se acceperat.
lorem ipsum dolor sit amet et et rerum quibusdam commodo. aute temeraria nuptias, audientes non. rem voluptate viderat sit irure. alias reddidit aliqua propter pariatur. ad doloribus doloremque, recusandae pariatur. elicere ad ius viribus tempor. dignissimos dolores res, dignissimos optio. consectetur deleniti atque excepturi.
lorem ipsum dolor sit amet est et placeat. religionis et et animi dispersos. modi nulla voluptate, officia esset. consequatur sunt quisquam soluta et. reprehenderit illo et, liberos cupiditate. inesset victu cupiditate magnam.
lorem ipsum dolor sit amet fero se congregavit recusandae ratione. ea ad quamque, nihil nobis. aperiam facilis ea voluptate conpulit. perferendis eveniet suscipit cupidatat ius. cognovit cillum conpulit impedit eligendi. deserunt corporis non aut Et. ut eam rem, non propagabant. molestiae quis commodi nemo.
lorem ipsum dolor sit amet amet aliquip reiciendis esse dolores. et beatae consequatur, unam et. divinae beatae agros, ducimus sint. do provident quo, temeraria qui. omnis Nemo utilem Excepteur minus. qui culpa perspiciatis, ratione in. et exercitationem qui, a libero. minima fero vel quo.
lorem ipsum dolor sit amet et consequatur qui Quis aperiam. voluptatibus nisi ad, viderat corporis. non nihil amet quos in. et numquam earum voluptate totam. voluptatum ad animi, minim et. videlicet perspiciatis nisi, libero propter. repellendus victu propter, rerum officiis. quidam possimus quicquam, dolore nihil. rerum ullamco aliquip, quaerat rerum. asperiores a vitam non.
lorem ipsum dolor sit amet hominum ipsum feris voluptatem ea. eos ad Itaque, dolorem consectetur. qui eligendi voluptatibus distinctio corporis. occaecat eveniet Excepteur, eos nihil. acceperat dolores elicere ea blanditiis. id esse satellitibus vagabantur.
lorem ipsum dolor sit amet consectetur consequatur officia sit nulla. expedita molestiae est nihil deserunt. molestiae adipisci quo iusto reclamantes. sint quia et ea.
lorem ipsum dolor sit amet maiores magnam deleniti. legitimas ex et nulla voluptates. sapiens alias quas victu nulla. veniam fuga eos est dolorum. autem distinctio corrupti, fuga inesset. consequatur autem viribus, officia Ut. propter non reprehenderit et culpa. laboriosam maximas in ipsum repudiandae. dolor et expedita sunt divinae. magnus autem necessitatibus bestiarum.
lorem ipsum dolor sit amet ad tempore opportunitas. aut sit magni, quis elit. sapiente liberos occaecat adipisci delectus. consectetur dignissimos et, inventore officii. impedit nec in, nuptias vitam. in voluptatem rerum minim et. administrabant et et, quo adipisicing. beatae ratione in, pariatur consequatur. quas animis fero si eius. quod rerum molestiae aliqua.
lorem ipsum dolor sit amet qui honestam acceperat animi voluptas. excepturi saepe et, tempus maxime. ut doloremque dolores, illo officiis. eam sed optio, unde Nemo. omnis laborum quis fugiat in. et voluptate aut, inducens in. molestias honestam laboris, mollit facere. voluptatem eos nihil occaecat repellendus. dolor cupiditas pleraque quos mollit. mollit hic conpulit aut.
lorem ipsum dolor sit amet in molestias qui. reclamantes sit reddidit, quis abutebatur. esse deserunt Ut, laboris atque. quas locum At, eaque studiosius. aspexerat elit dispersos, distinctio inesset. quo aut quadam, orationem ullamco. ac inscientiam lorem, amet ut. voluptas ex silvestribus videlicet.
lorem ipsum dolor sit amet aute abutebatur perniciosissimis omnis non. quis ullam sunt, nemo qui. quia id rerum mansuetos nobis. eos quid in si bestiarum. est earum placeat, nulla et. in reddidit sint, homines nostrum. in aut iste, accusamus et. velit in nulla soluta rem. atque honestam At ratio dolorum. natus omnis dolores laborum.
lorem ipsum dolor sit amet ratione aliquid rerum nam assumenda. nihil omnis ut, studiosius id. rem corporis enim quoddam aut. pariatur pleraque est voluptatem Duis. explendam deserunt pleraque numquam qui. commodo dolor sint, studiosius reddere;. Nemo ut voluptas rerum sit. officia sed nec, a est. reprehenderit mites laudantium veniam."
                           id="ot1"/>
          </af:panelGroupLayout>
        </f:facet>
      </af:declarativeComponent>
    </af:form>
  </af:document>
</f:view>

In the declarative component, you will now want to use JSTL to build either a splitter or a button that shows a popup based on the device. ADF has an API for the browser agent that includes capabilities. One of the capabilities that is exposed is if the agent is a touch screen device (Android and iOS devices). By referencing this capability from JSTL, you can change what components are created. Example EL usage:

<c:if test="${adfFacesContext.agent.capabilities['touchScreen'] eq 'none' ? true : false}">

Using this you can create two layouts, each using af:facetRef to include the passed in facets. Note that JDev will report errors that the facet is used more than once, but that is only because it does not know the c:if tag will be sure to only render one set. Example code for the declarative component page fragment:

<?xml version='1.0' encoding='UTF-8'?>
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
                xmlns:c="http://java.sun.com/jsp/jstl/core"
                xmlns:af="http://xmlns.oracle.com/adf/faces/rich"
                xmlns:f="http://java.sun.com/jsf/core">
  <af:componentDef var="attrs" componentVar="comp">
    <af:xmlContent>
      <component xmlns="http://xmlns.oracle.com/adf/faces/rich/component">
        <description>Layout dynamically adjusted based on user agent</description>
        <facet>
          <facet-name>
            navigation
          </facet-name>
        </facet>
        <facet>
          <facet-name>
            content
          </facet-name>
        </facet>
      </component>
    </af:xmlContent>
    <c:if test="${adfFacesContext.agent.capabilities['touchScreen'] eq 'none' ? true : false}">
      <af:panelSplitter id="dc_ps1" dimensionsFrom="parent">
        <f:facet name="first">
          <af:facetRef facetName="navigation" />
        </f:facet>
        <f:facet name="second">
          <af:facetRef facetName="content" />
        </f:facet>
      </af:panelSplitter>
    </c:if>
    <c:if test="${adfFacesContext.agent.capabilities['touchScreen'] eq 'none' ? false : true}">
      <af:panelStretchLayout topHeight="2em" bottomHeight="0" id="dc_psl1"
                             dimensionsFrom="children">
        <f:facet name="top">
          <af:panelGroupLayout id="dc_pgl1">
            <af:commandButton id="dc_cil1" text="Open navigation" iconPosition="trailing"
                                 icon="/afr/fusion/dropdown_ena.png">
              <af:showPopupBehavior popupId="dc_navPopup" triggerType="action" align="overlap"/>
            </af:commandButton>
          </af:panelGroupLayout>
        </f:facet>
        <f:facet name="center">
          <af:facetRef facetName="content"/>
        </f:facet>
        <f:facet name="bottom">
          <af:popup id="dc_navPopup">
            <af:facetRef facetName="navigation" />
          </af:popup>
        </f:facet>
      </af:panelStretchLayout>
    </c:if>
  </af:componentDef>
</ui:composition>

Now load the page in a browser and on an iPad and see the layout change. How it looks on the desktop:

desktop image

How it looks on an iPad:

iPad image

How it looks on an iPad with the navigation open:

iPad image

You can download the sample JDeveloper workspace for 11.1.2.3.0 here.

Wednesday, October 3, 2012

tr:forEach to soon provide support for changes to the collection

In order to address the issues that I discussed in my blog regarding the c:forEach tag, I implemented enhancements to the Trinidad forEach tag since I am a developer on that team.

The changes are part of TRINIDAD-1940 which should be part of the future Trinidad 2.1.0 release. Until then, you can try out the changes by using the snapshot build.

The forEach tag documentation does not have the new documentation as the site is currently based on the 2.0.2-SNAPSHOT documentation.

Until then, here is a preview of the new forEach documentation (Content owned by the ASF is covered by the Apache version 2.0 license):

Summary

Tag name: <tr:forEach>

The forEach tag provides additional functionality from the JSTL <c:forEach> tag. The tag is only supported in JSP.

Facelets

The <tr:forEach> is not supported in facelets. As a convenience, the tag handler for the <c:forEach> will be used in facelets when a <tr:forEach> is used in a facelets page, but no Trinidad functionality will be supported.

Supported collections

The Trinidad forEach tag supports the following collections for the items attribute:
  • Java array
  • java.util.List
  • org.apache.myfaces.trinidad.model.CollectionModel
  • java.util.Map

When using a map, the map should be one that has a consistent order. Either the java.util.LinkedHashMap or java.util.TreeMap are examples of maps that provide this functionality. The keys for the maps must implement java.io.Serializable.

Usage

Valid Use Cases

The for each tag is not as efficient as component stamping. When possible, the <tr:iterator> should always be used instead of the for each tag. There are times this is not possible and usually involve the inclusion of content from other pages. For example, if different <jsp:include> tags need to be generated, pointing to different files based on items in a list, a for each tag must be used and not a stamping component like the Trinidad iterator.

ID and Component State

Due to the way JSF and JSP create ValueExpression objects, the for each tag cannot safely map the expressions created and stored on JSF components to the iteration of the for each loop. As a result, it is possible to cause a discrepency between the component's location in the for each tag and the value expressions that are stored in the tag.

Due to this limitation, the forEach tag must place usage requirements on the pages they are placed on. For index based collections (arrays and lists), the components must be mapped to the index of the for each loop and not the item in the collection. In these cases, the index of the for each loop is stored into the value expressions created and stored into the components. This results in the component state (like expanded state of disclosure components) being tied to the index of the for each loop. As a result, a key based collection (map or collection model) is always recommended when the collection may change between requests.

For key based collections (map and collection model), the component IDs must be associated with the key of the collection. This is because the key of the collection is used in the value expressions and if the ID were not bound to the key, then the component state would not match the EL values. You should associate the component to the key using immediate EL in the ID attribute. See the examples below.

Generated IDs

When the collection may change between requests, a key based collection should be used. When this is done, it is not recommended that JSF be allowed to generate the IDs of any components inside the for each tag. The reason is that JSF auto-generated IDs are based on the sequence that they are created in the current page. If items are re-arranged in the for each loop, the IDs will have a different generation order. As a result, JSF will not find the components with auto-generated IDs when it tries to map the JSP tag to the component ID. Existing components will be thrown out and new ones will be created and component state will be lost if this occurs.

Reordering and Collection Modifications

Modifications to the collection in the same JSF view (between requests) are only supported with key based collections. Even with this being supported, the for each tag will not auto-rearrange the children.

When JSP seeks to locate a component that was created in a previous request, it creates the ID that it expects the component to have and then searches the children of the parent component of the tag for the child component with that ID. If the component is not found, a new one will be created. If it is found, the framework does not do anything to the component, it is left to exist where it is found. This means that if you reorder items in your collection between requests, the component order will no longer match the order of the items in the collection. Page authors must reorder the components when changes to the collection are made.

Trinidad supports re-ordering of components using the change manager (org.apache.myfaces.trinidad.change.ChangeManager) and the org.apache.myfaces.trinidad.change.ReorderChildrenComponentChange class. The change manager may be retrieved from the org.apache.myfaces.trinidad.context.RequestContext instance. See the Trinidad demo application for examples on how to reorder the components when the collections changes.

When using a key based collection, it is recommended to use a naming container to simplify tying the component ID to the key. See the examples below.

Examples

Please see the Trinidad demo application for complete examples.

Index Based Collection

<tr:forEach var="person" items="#{forEachBean.simpleList}" varStatus="vs">
  <f:subview id="sv${vs.key}">
    <tr:panelGroupLayout id="personPgl" layout="horizontal">
      <tr:outputText id="personName" value="#{person.firstName} #{person.firstName}"
                     inlineStyle="padding-right: 1em;"/>
      <tr:outputText id="clientId" value="(Client ID: #{component.clientId})"/>
    </tr:panelGroupLayout>
    <tr:spacer id="s1" height="1em" />
  </f:subview>
</tr:forEach>

Key Based Collection

<tr:forEach var="person" items="#{forEachBean.collectionModel}" varStatus="vs">
  <f:subview id="sv${vs.key}">
    <tr:panelGroupLayout id="personPgl" layout="horizontal">
      <tr:outputText id="personName" value="#{person.firstName} #{person.firstName}"
                     inlineStyle="padding-right: 1em;"/>
      <tr:outputText id="clientId" value="(Client ID: #{component.clientId})"/>
    </tr:panelGroupLayout>
    <tr:spacer id="s1" height="1em" />
  </f:subview>
</tr:forEach>

Example Re-Order Code

// Create a list of all the children IDs of the parent component of the for each loop. This must
// contain all the children, not just those created by the for each tag.
List<String> orderedIds = ...;

// Get the reference to the component that is the parent of the for each tag. For finding relative
// components, you may try using
// org.apache.myfaces.trinidad.util.ComponentUtils.findRelativeComponent(UIComponent, String)
UIComponent forEachParent = ...;

ReorderChildrenComponentChange componentChange = new ReorderChildrenComponentChange(orderedIds);
RequestContext requestContext = RequestContext.getCurrentInstance();
ChangeManager cm = requestContext.getChangeManager();
// The component change must be added before the tag execution (before the render response JSF
// phase)
cm.addComponentChange(FacesContext.getCurrentInstance(), forEachParentComponent,
  componentChange);

// Ensure that the view is updated during PPR requests
requestContext.addPartialTarget(forEachParentComponent);
        

Attributes

Name Type Supports EL? Description
begin primitive int or java.lang.Number subclass No index at which iteration begins
end primitive int or java.lang.Number subclass No index at which iteration ends
items Object Only EL the collection to iterate over. Supported classes:
  • Java array
  • java.util.List
  • org.apache.myfaces.trinidad.model.CollectionModel
  • java.util.Map
step primitive int or java.lang.Number subclass No number to increment the index by on each iteration
var String No name of the variable exposed when iterating that references the item in the collection
varStatus String No name of the loop status exposed when iterating.

Properties:

Name Description
index the current index (int)
count the total number of times the for each tag will iterate (int)
begin the index to start at when collections are not used (int)
end the last index when collections are not used (int)
first true if this is the first iteration (boolean)
last true if this is the last iteration (boolean)
key the index (int) for index based collections and when the items has not been specified. The key (java.io.Serializable) for key based collections

Wednesday, January 4, 2012

Component scope

It is often confusing to users what it means by having a JSF component be "in scope," especially in JSF 2. JSF is processed by a set of phases, each one usually iterates the component tree, acting upon each component in turn. Some components, like the h:dataTable, perform stamping.

Note, for more information on stamping, please see my blog on tables.

When a component is being processed, the EL context may be altered. For example, the data table injects "var" and "varStatus" variables into the request scope. This also means that when the table is not being processed, these variables are either not available, or point to another value.

This is what I mean by a component being "in scope," that it is currently being processed by the JSF lifecycle or JSF APIs in a manner congruent with the JSF specification for working with components.

How a component enters scope

A component can enter scope one of three ways:

  1. The JSF lifecycle is being run. This will be the result of calls from methods on the component:
    • processDecodes
    • processValidators
    • processUpdates
    • processSaveState
    • processRestoreState
    • broadcast
  2. During an invokeOnComponent callback
  3. During a visitTree callback

At any other time, it may not be valid to be interacting with the component. Take for example, using Oracle ADF components, an input text component inside of an iterator:

<af:iterator var="item" value="#{bean.items}">
  <af:inputText value="#{item.value}" binding="#{bean.inputText}" />
</af:iterator>

Now consider this Java code for the bean:

private RichInputText _inputText;

public RichInputText getInputText()
{
  return _inputText;
}

public void setInputText(RichInputText text)
{
  _inputText = text;
}

public Object getValue()
{
  return _inputText == null ? null : _inputText.getValue();
}

Should code call the bean's getValue() method, what is the outcome? Well that is indeed the problem. Before the JSF view is built, the value will be null as the component has not been bound yet. Between JSF phases, it will also be null because #{item} will not be present in the EL context.

As this example shows, the attributes and behavior of the component in question change based on what component is currently being operated on. What makes this even more of an issue, is component frameworks that setup and tear down contexts. For example, Oracle ADF faces has a base component class called a oracle.adf.view.rich.component.fragment.ContextSwitchingComponent. When a component is processing its JSF lifecycle, or one of its children is being called back via a visitTree or invokeOnComponent call, the setupContext method has been run. If one of these components is accessed through code, and the context has not been set up yet, unreliable results may occur, or even exceptions may be thrown. One use case is of the ADF page template component. By using context switching, this component alters the EL context so that facets in the page with the <af:pageTemplate /> tag are executed in the EL context they were defined in, and the components inside the page template definition are executed within the context of the page template definition file.

Note that JSF 2 has a compound component like the ADF page template, but I am not sure how it handles EL context resultion.

It is therefore, never a good idea to call methods or evaluate attributes on JSF components unless the caller is sure that the component being accessed is currently in scope. Here is another example:

<af:iterator var="item" value="#{bean.items}">
  <af:pageTemplate viewId="template.jspx" item="#{item}">
    <f:facet name="center">
      <af:outputText id="facetText" value="#{item.itemValue}" />
    </f:facet>
  </f:pageTemplate>
</af:iterator>

Page definition:

...
<af:pageTemplateDef var="attrs">
  <af:xmlContent>
    <component xmlns="http://xmlns.oracle.com/adf/faces/rich/component">
      <description>This component lays out an entire page.</description>
      <facet>
        <description>The center content.</description>
        <facet-name>center</facet-name>
      </facet>
      <attribute>
        <description>the item.</description>
        <attribute-name>item</attribute-name>
        <attribute-class>com.mycompany.MyItem</attribute-class>
      </attribute>
    </component>
  </af:xmlContent>
  <af:iterator var="item" value="#{item.innerItems}">
    <af:facetRef facetName="center"/>
    <af:outputText id="templateText" value="#{item.itemValue}" />
  </af:iterator>
</af:pageTemplateDef>

This is a very simplified example, but it illustrates the question, what does #{item.itemValue}" evaluate to? In the facet, this should be the item from the bean's items collection, as shown with the output text with id "facetText". Inside the page template, the value should be the item from the inner items collection of the item passed into the page template, show by the output text with the id "templateText". Depending on when this EL is evaluated, different values will be returned. Therefore, is is crucial, that in order to evaluate the RichOutputText.getValue() method, that the call is made while that component is "in scope," or "in context."

Putting a component into context

Components are automatically put into context when they are being validated, updated, broadcasting events, rendering, etc. Sometimes it is necessary to interact with a component outside of its context. For example, perhaps you have backing bean code that wishes to get the input text value. This may be done by knowing a component's client ID, and using the visitTree method. Here is an example:

public void performAction(ActionEvent evt)
{
  String clientId = "template1:table1:0:firstNameInputText";
  FacesContext facesContext = FacesContext.getCurrentInstance();
  VisitContext visitContext = VisitContext.createVisitContext(facesContext,
    Collections.singleton(clientId), EnumSet.of(SKIP_UNRENDERED));
  GetFirstNameCallback callback = new GetFirstNameCallback();
  facesContext.getViewRoot().visitTree(visitContext, callback);

  String firstName = callback.getFirstName();
  ...
}

private static class GetFirstNameCallback
  implements VisitCallback
{
  private String _firstName;

  public String getFirstName()
  {
    return _firstName;
  }

  public VisitResult visit(
    VisitContext visitContext,
    UIComponent  target)
  {
    RichInputText inputText = (RichInputText)target;
    _firstName = (String)inputText.getValue();
    return VisitResult.COMPLETE;
  }
}

Here the code illustrates how to access the input text value for a component in the first row of a table.

Summary

Due to the fact that EL is contextual, it is important that any EL based functionality is only accessed in the correct context for that EL. As such, JSF developers should use caution when interacting with components via their Java APIs. Using visit tree should always be considered when trying to access properties from a component in order to ensure that the expected EL context has been setup when the component attempts to access its data. Failing to do so may cause issues with your programs, and even data contamination.

Sunday, February 1, 2009

Problems with the Mozilla Component.utils.Sandbox

Writing a Firefox extension can be time consuming for the first time, the documentation is more reference oriented, more oriented to C++ than the JavaScript version, but it is the worst when there are bugs and you waste hours of work. That is what happened to me with the Sandbox APIs of Firefox 3. After talking to members of the FireBug extension on its Google groups forum, I found out that I am not alone with Sandbox frustrations.

The Sandbox

The sandbox, introduced in full in FF3, is a container that allows extension developers to run code in lower security. This is helpful for interacting with browser web pages or for running code from a server. The Sandbox API Documentation is pretty light, and gives no useful examples for real-world applications. The primary use of the sandbox is probably to work with pages, but they show no example on how to do that.

My Problem

When I was working on an extension I write for work, I found that I had some extremely peculiar results. As an illustration, lets say there are two types of JavaScript objects in a page that you want to work with. The first, is a single instance object that looks up other JS objects, and the second, a 'normal' JS object that we want to create. So for my example, lets say we want to lookup an object, pass that object into a constructor and then run a method on that new object:

  var obj = TheRegistry.lookupObject('customId1');
  var ref = new ObjectReference(obj);
  ref.save();

Now, I want to run this code in my extension, so I setup the sandbox and execute the code like this:

  var evalInSandbox = function(win, script, vars)
  {
    win = getUnwrapped(win);
    var sandbox = new Components.utils.Sandbox(win);
    sandbox.window = win;
    sandbox.document = sandbox.window.document;
    sandbox.XPathResult = Components.interfaces.nsIDOMXPathResult;
    sandbox.__proto__ = win;
    if (vars)
    {
      for (var prop in vars)
      {
        sandbox[prop] = vars[prop];
      }
    }
    return Components.utils.evalInSandbox(
      "(function() { " + script + "\n })();", sandbox);
  };
  
  var getUnwrapped = function(obj)
  {
    while (obj.wrappedJSObject)
    {
      obj = obj.wrappedJSObject;
    }
    return obj;
  };
  
  var doSomething = function(window)
  {
    evalInSandbox(window,
      "var obj = TheRegistry.lookupObject('customId1');"+
      "var ref = new ObjectReference(obj);"+
      "ref.save();");
  }

What I was surprised to find out is that ref had no 'save' method, but I knew that was not the case. Looking further into it, ref == obj. What the heck?! I tried wrapping the code with with (window) { ... }, using new window.ObjectReference(obj), but nothing would work. Finally I gave up on the code and used a FireBug technique to inject a script tag into the page's DOM.

Wrap Up

I wrote this article, not to teach, but hopefully to save other people some time so if the google 'mozilla sandbox bugs' or something similar, they may find this. Hopefully Mozilla will fix the sandbox and improve its documentation, but until then, watch out for bugs, and stay away from creating page objects using the 'new' keyword inside of the sandbox, it just doesn't work.

BTW, the google group discussion I mentioned can be found here.

Tuesday, January 27, 2009

JSF Component Binding Stinks

Whoever came up with JSF component binding should be taken out back. While a nice thought, it really is just a purely awful piece of design and was not thought through at all.

Too harsh? Well, it sounds harsh, but when you consider all the flaws and bugs it causes, it isn't.

1. The problem

I have been telling people on the MyFaces mailing list to always ensure that they use binding with request scope beans, but I have realized that this advice was now bad. My advice should have been to never use binding at all, or to at least only use a setter, but no getter.

The reason behind this, is that there is a fundemental flaw in how binding was designed. Binding is too completely separate pieces of functionality, jammed together in one implementation:

  1. Component factory
  2. Component access from code

The latter is what people normally use binding for. This is how the framework uses binding in a JSP component tag:

  1. Does the tag have the binding attribute set?
    1. If so, call the getter method
      1. If returns not null, use that value
      2. Else, create a new component
        1. Call the setter with the new component

What you now see is that the getter method acts as both a normal JavaBean property getter as well as a factory. The problem is that 90% of the time, the lifetime of this member variable is too long. Almost always, the component in the bean should only be ever stored as long as the view is being processed. Take this example:

Developer has a managed bean with a request scope with a bound component. The page navigates from view1 to view2.

Jspx Code:

  <?xml version='1.0' encoding='utf-8'?>
  <jsp:root
    version="2.1"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:jsp="http://java.sun.com/JSP/Page">
    <jsp:directive.page contentType="text/html;charset=utf-8"/>
    <f:view>
      <html>
        <body>
          <h:form>
            <h:outputText binding="#{myBean.textComponent}" />
          </h:form>
        </body>
      </html>
    </f:view>
  </jsp:root>

Now the views would probably be different, but it is not unusual for someone to reuse #{myBean.textComponent} in the page. Now what happens is that view1 causes the #{myBean.textComponent} to be set since it would return null on the restore view. View 2 is navigated to, but the #{myBean.textComponent} returns the component from view 1, so it is not re-created. Now we have an illegal state, a component is shared between two views.

There could have been two ways of fixing this:

  1. There could have been a create or factory attribute on the JSP tag and only that attribute could ever create the component and the set method on the binding would be used, but never the getter method.
  2. The JSP tag component creation should be smart enough to always check that a component is never shared across views. Therefore, if a binding expression returns a component that already has a parent and by looking up the tree, the view root is not the current view root, a new component should have been created.

So what is the best work around for this problem?

Well the best solution is to never use binding under any circumstances, ever, no exceptions. This is the only safe way to write JSF pages. If your bean needs to access a component, use findComponent or invokeOnComponent to get the component.

The other alternative is to check the view root yourself in you bean when the getter is called. If the view has changed, return null. Example:

  package blog;
  
  import java.util.Map;
  
  import javax.faces.component.UIComponent;
  import javax.faces.component.UIViewRoot;
  import javax.faces.context.FacesContext;
  
  public class MyBean
  {
    public void setMyComponent(UIComponent myComponent)
    {
      this.myComponent = myComponent;
    }
  
    public UIComponent getMyComponent()
    {
      checkViewRoot();
      return this.myComponent;
    }
  
    private void checkViewRoot()
    {
      UIViewRoot current = FacesContext.getCurrentInstance().getViewRoot();
      if (this.viewRoot == null || (current != null && current != this.viewRoot))
      {
        this.viewRoot = current;
        // view is new or has changed, make sure the component is not re-used
        this.myComponent = null;
      }
    }
  
    private UIComponent myComponent;
    private UIViewRoot viewRoot;
  }

Ugly? Bad performance? Yes! Unfortunately this may be the best solution if you have to use component binding. From what I have seen from JSF 2.0 I think there may be factory support, so that component binding to be able to gain access to a component in a bean is separated from component creation. I hope so. Until then, I strongly recommend that you forget that the binding attribute exists at all.

Monday, January 19, 2009

JSF compared with CGI-like development for small web sites

I have been developing small side web sites in PHP, Python and Java. With my primary job working with Java / JSF, I found that it was not my favorite development environment. I thought I would share some of my experiences.

JSF

JSF is a great framework, with a lot of promising ideas, but the more I have tried to work with it, the more I find that it may not be the best solution for writing web pages nor small web applications.

Pros:

  • Many open source libraries to leverage
  • Large company backing
  • Complex components with 3rd party libraries
  • Code and view are separated
  • Java has good refactoring tools
  • Fail-over, clustering and other robust business features
  • Part of J2EE
  • Built-in validation and conversion
  • 3rd party libraries can make AJAX fairly easy

Cons:

  • Must be compiled and deployed
  • Too much XML configuration
  • Components are good for 90% of use cases, but severely handicap the other 10%
  • AJAX geared for PPR only, hard to use AJAX for web-service like functionality
  • State saving methodology is abysmal and kills performance and scalability
  • Multi-phased processing on server is confusing to many users
  • Poor CSS support as components and HTML are loosely tied
  • Poor JavaScript library integration
  • Very few web hosting choices

Comparison with CGI

CGI and similar programming usually involves Perl, PHP, Ruby or Python. I have not written Perl in a while as I prefer python and hove not written and Ruby, but I have written full sites in PHP. CGI, or Apache module based languages do not have the framework idea that Java has. Java seeks to give you factories, factories for your factories, paradigms, many standard and rigid APIs, where these other libraries do not. This is a pro. and a con. in my opinion. I love jQuery as it makes client side development terrific, I could do a whole set of blogs on it (maybe I will), but it is more easily used from these other languages compared to Java.

What I find is that even though I love the cool frameworks of Java, the many nice APIs, it is very hard to make a web site with JSF that looks even remotely appealing. From my experience, I can create about a third of a website with jQuery, PHP or Python and PosgreSQL before I have written one page in JSF. This is mostly because of the problem that JSF is too high-level. It does not let me do what I want. In PHP I can loop over a data set and create a table and then easily use jQuery and AJAX to add & remove rows from that table. JSF this is extremely hard, you get validation errors from current rows, the 3rd party render kits never have add & remove rows, their AJAX is almost always built in and you can't customize it.

What it comes down to is that I do not need help with the GUI and HTML, I just want some help with tedious tasks. JavaScript libraries like jQuery make rapid web development easy as there are a ton of plug-ins written for it, many of which are more customizable than the ones offered for JSF. Since I can design my own site and get low level, I do not have to fight a render kit from JSF, or the phases of JSF, I just write it the way I want. Now for users that may not be the best with HTML and JavaScript, maybe a framework is great.

Even though this is important, the other thing I love about developing on Apache and not in a JSF server, is that to make a change, I save a file. In Java, I run mvn (Maven 2) to build, then restart Jetty to test. Working with Tomcat, JBoss or another application server is even worse. It just takes too long to work on. I can make a couple of changes and test with PHP when I am still waiting for my Java application server to start up. Not too mention that Java servers tend to be a major RAM hog.

JSF and Component Trees

Another thing that keeps bothering me in JSF is the notion of a web application and the component tree. In JSF, the pages are designed to be shown once, but this is not how web applications work. Web applications, should be mostly one web page that changes as I interact with it (like gmail for example). I should not have to wait for full page refreshes all the time. JSF's components can do this, but not the view layer. JSP is horrendous with dynamic includes and Facelets has issues too (mostly tag / tag handler to component ID matching issues). Without dynamic includes, it is very hard to author wizards, or pages that change (not reload).

I wonder if Google was smart to avoid Java's JSRs and avoid JSF and develop GWT, a web application development framework made for robust clients.

Final thoughts

This is truly a blog post, in that I am just sharing some thoughts as they stream from my head to my keyboard. I could say more on the subject, but don't have the time at the moment. Perhaps JSF2 will improve JSF development, but from what I have seen it only goes so far and will have many of the same flaws, although it does have a lot of cool new functionality.

It will be interesting to see where the space goes in 5 years, but I will be surprised if JSF lasts that long with its current design. I think that high-level frameworks are just too hard to work with. I really see why most web sites are still written using interpreted languages like Perl, PHP and Python. I still love Java and JSF, but for small web sites on the side, I really don't think JSF can compete at all with its light-weight competitors.

Tuesday, January 13, 2009

tr:switcher has some lifecycle caveats

The Apache MyFaces Trinidad has some optimizations in the component that can easily cause application exceptions.

The switcher only decodes, validates, updates and renders the facet that is currently show. For example:

<tr:switcher defaultFacet="#{bean.facet}">
 <f:facet name="one" />
 <f:facet name="two" />
</tr:switcher>

If bean.facet evaluates to "one", then only the facet with that name will be decoded, validated, updated and rendered. This means, that if the bean value is changed, another component will be acted upon. Take this example:

<tr:selectOneChoce id="soc1" value="#{bean.facet}" autoSubmit="true">
 <f:selectItem itemLabel="One" itemValue="one" />
 <f:selectItem itemLabel="Two" itemValue="two" />
</tr:selectOneChoce>
<tr:switcher id="sw1" defaultFacet="#{bean.facet}">
 <f:facet name="one">
   <tr:inputText id="it1" value="#{bean.one}" />
 </f:facet> 
 <f:facet name="two">
   <tr:inputText id="it2" value="#{bean.two}" />
 </f:facet> 
</tr:switcher>

What will happen is this:

  1. APPLY_REQUEST_VALUES
    1. soc1 is decoded (submitted value is set)
    2. sw1 is decoded
    3. it1 is decoded (submitted value is set)
  2. PROCESS_VALIDATIONS
    1. soc1 is validated (value is converted and set as a local value)
    2. sw1 is validated
    3. it1 is validated (value is converted and set as a local value)
  3. UPDATE_MODEL_VALUES
    1. soc1 is updated (backing bean #{bean.facet} is set to new value)
    2. sw1 is updated
    3. it2 is update (no submitted or local value)

As you can see it1 is decoded and validated, but not updated. it2 is updated but not decoded or validated.

Now, lets consider the Trinidad tree (UIXTree component). Inside the decode of the tree, the code ensures that the component has been initialized using its __init() method. This method ensures that the tree's disclosed and selected row key sets are not null. Since the JSF phases dictate that the decode method will be called before the updateModel method, the init method is not run for the other phases. Now, if the switcher is used as it is above and there is a tree in one of the facets, this means that the tree may not have ever initialized its disclosed row keys.

The 'fix'

To ensure that a component's lifecycle is fully run, that means that the switcher's facet cannot be changed between the decode and the end of the update model phase. This basically means that the value should only be changed during the INVOKE_APPLICATION phase. So here is an example of that:

<tr:selectOneChoce id="soc1" valueChangeListener="#{bean.switch}" autoSubmit="true">
 <f:selectItem itemLabel="One" itemValue="one" />
 <f:selectItem itemLabel="Two" itemValue="two" />
</tr:selectOneChoce>
<tr:switcher id="sw1" defaultFacet="#{bean.facet}" binding="#{bean.switcher}">
 <f:facet name="one">
   <tr:inputText id="it1" value="#{bean.one}" />
 </f:facet> 
 <f:facet name="two">
   <tr:inputText id="it2" value="#{bean.two}" />
 </f:facet> 
</tr:switcher>
public class Bean
{
 private String facet;
 private UIXSwitcher switcher;

 public Bean()
 {
   this.facet = this.selectFacet = 'one';
 }

 public UIXSwitcher getSwitcher() { return this.switcher; }
 public void setSwitcher(UIXSwitcher switcher) { this.switcher = switcher; }

 public String getFacet() { return this.facet; }

 public void switch(ValueChangeEvent event)
 {
   if (event.getPhaseId() != PhaseId.INVOKE_APPLICATION)
   {
     event.setPhaseId(PhaseId.INVOKE_APPLICATION);
     event.queue();
     return;
   }
   this.switcher.setFacetName((String)event.getNewValue());
 }
}

Now this is a bit of a hack, but this ensures that the callback to set the switcher only occurs during the correct phase.

Change UIXSwitcher?

A very good argument could be made that UIXSwitcher should not prevent the decoding, validating and updating of all of its children. This would be more acceptible from a JSF perspective. The problem with this is that it would drastically impact performance of users that are expecting this behavior.

Wrap Up

The take away, is that any component that affects the lifecycle methods of other components must be used with care. A component should always decode, validate and update in that order, and should never have its lifecycle changed. Hopefully this post will help avoid problems that are not that easy to debug.

New location

I am moving my previous blog of http://andrewfacelets.blogspot.com to here. This is to broaden the scope of my blogs to all software development instead of constraining myself to JSF and facelets. Some blogs to be posted here shortly. Thanks for reading.

Sunday, August 10, 2008

c:forEach with JSF could ruin your day

Last week, a co-worker of mine at Oracle was attempting to use a forEach tag to produce components in a loop and developed issues. Having some experience trying to deal with for each I started looking into the problem and found a disturbing problem.

The JSTL <c:forEach/> tag was written to make JSP development easier, but was never intended to be used with Java Server Faces. In JSP 2.1 some enhancements were made to improve the usage of non-JSF JSP tags intermingled with JSF by introducing deferred expressions. The idea behind the deferred expressions was to be able to create expressions that would normally have to be evaluated at JSP tag execution and allow them to be executed with JSF components instead. The problem is that the implementation of deferred expressions is flawed for the <c:forEach/> loop except for basic usage only.

Use Case

For the illustration of the problem with the <c:forEach/> I will simplify the use case. The are two main problems with the tag both of which involve the changing of the list bound to the items attribute. For the first, consider the following requirements:

  • For each loop required, JSF stamped iteration components cannot be used (like JSP tags that include a page)
  • Ajax used to partially render the page
  • Id's of components must be tied to the item in the loop to allow actions

Problem 1 - static EL

A simple example can be used to show the problem:

<h:form>
  <c:forEach var="item" items="#{bean.items}">
    <h:commandButton
      id="button_${var.key}"
      value="Remove #{var.key}"
      actionListener="#{bean.remove}" />
  </c:forEach>
</h:form>

Take for example a list of "A", "B", "C" and "D". The buttons render as:

ID Text
button_A Remove A
button_B Remove B
button_C Remove C
button_D Remove D

Now should the user click "Remove A", the managed bean removes the value from the items list. The result is:

ID Text
button_B Remove C
button_C Remove D
button_D Remove

Notice the mismatch of ID and text? Notice that the last button's #{var.key} evaluated to null?

To understand the problem, it is best to describe a step by step process of how the code works:

  1. The for each tag is executed and the first iteration (count 0) is begun
  2. The tag creates an IndexedValueExpression. This sub-class of ValueExpression.
    • The expression to get the items is stored (#{bean.items})
    • The index of the for each iteration is stored (0)
  3. This IndexedValueExpression is then added to the VariableMapper as the var - item.
  4. The body of the tag is executed
  5. The command button tag is instructed to create or find a component with ID button_A.
  6. The command button component is created with all its attributes.
    • When the component is created, the ValueExpression instances are created
    • Each ValueExpression is created with a reference to the FunctionMapper and VariableMapper
  7. The for each tag proceeds with its execution and processes indexes 1-3

When the action executes and removes A, the following occurs during the render phase. First, the for each tag looks for the button for B and finds it. Then the loop repeats. At the end of processing the tags, the code realizes that button_A was never referenced, and is therefore removed from its parent, the form.

The problem is that once the component is created, the ValueExpression instances are created, and are never re-created. This is because the expressions with their mappers are serialized and restored as part of the component state. This means that button_B which was found for the first item after item A was removed still has its original ValueExpression for the value attribute. This expression has the variable mapper with the indexed value expression for the var which has index 1.

This means that if components are used with IDs that tie to the items, it is possible to have the value expressions pointing to the wrong index in the for each loop once changes are made to the items list.

Problem 2 - Component State

One workaround to problem one is to use dynamically created IDs. This will violate our above requirement of needing to match the component to the item for advanced PPR (AJAX) replacement, but it is a consideration.

Lets use the above use case with the IDs removed:

<h:form>
  <c:forEach var="item" items="#{bean.items}">
    <h:commandButton
      value="Remove #{var.key}"
      actionListener="#{bean.remove}" />
  </c:forEach>
</h:form>

This renders as:

ID Text
j_id_id2 Remove A
j_id_id2j_id_1 Remove B
j_id_id2j_id_2 Remove C
j_id_id2j_id_3 Remove D

When A is removed, since the item key is not used in the ID, the above problem is not witnessed:

ID Text
j_id_id2 Remove B
j_id_id2j_id_1 Remove C
j_id_id2j_id_2 Remove D

What you will notice is that item B which used component with ID j_id_id2j_id_1 is now rendered by component with ID j_id_id2. Unlike above, this component has the correct index stored for it, but its state may break the view. Now command buttons are not a great example of this, but many components have state that is more evident, like tree node expansion. What this will mean to the user is that component state that belongs with item B is now associated with item C.

How could this be addressed?

The fundamental problem is that the implementation of the for each loop tag assumes that the location of the components that are created are independent of the items used to produce them. The ValueExpression instances are created for components with hard coded indexes and there is no way that I know of to update the index to the correct value later.

One fix is to allow the for each loop to use keys for the item instead of indexes. The obvious problem with this idea is that it would involve a significant API enhancement to be able to specify a key for an object and the use of a Map instead of a List or array to be able to lookup the value for the key. Something like:

<h:form>
  <c:forEach var="item" keys="#{items.keys} items="#{bean.items}">
    <h:commandButton
      value="Remove #{var.key}"
      actionListener="#{bean.remove}" />
  </c:forEach>
</h:form>

Where keys would be a List or array of serializable objects for keys in the items which would be represented as a Map.

Summary

As I have always recommended on the Apache MyFaces and Facelets mailing lists the best solution is to never use JSTL tags for JSF development. Unfortunately there are some pieces of functionality which is hard to replicate using components. Perhaps JSF 2.0 will allow things like component controlled sub-page inclusion.

Update 2012-10-03

Partial fix to be available as part of Trinidad. My blog on the enhancement to the Trinidad for each tag.

Saturday, June 7, 2008

Understanding the dataTable

The <h:dataTable/>, although easy for many to understand to use is often not understood in how it actually works. Since my article on component tree construction and rendering with respect to JSTL seemed to be received pretty well, I have decided to cover how the <h:dataTable/> works.

Table Of Contents

Looping components

The dataTable is one of many components that loop, although it is unfortunately the only one provided with core JSF. Other looping components are from 3rd party libraries. Here are some:

Each of these components, although renders quite different HTML all work using a similar design, modeled by the core <h:dataTable/>.

General Architecture

The API is simple, but the architecture, not so much. The API involves the construction of a set of components that produce an outer HTML element followed by inner HTML elements. For example, the <h:dataTable/> creates an outer <TABLE> with a <TR/> for each iteration of the loop. Others like <t:dataList>, <ui:repeat> and <tr:iterator> produce no HTML usually, so they simply allow one to loop over a set of components for many objects in a model.

Each of these components have value and var attributes, although their names may change slightly from component to component. The value provides some kind of model data to the component. This may be a model class (like a tree model for a tree component), or just object arrays or collections of objects. Each component differs on what values they support, but either way all point to a model of data that contains many objects. When the component is rendered, each object in the model is iterated over. In order for page developers to access the data, an EL variable is injected into scope temporarily. This variable has a name given by the var attribute. Take for example this code that shows all of the cookies sent to the server in a table in a servlet environment:

<h:dataTable
  var="_cookie"
  value="#{facesContext.externalContext.request.cookies}">
  <h:column>
    <f:facet name="header">
      <h:outputText value="Name" />
    </f:facet>
    <h:outputText value="#{_cookie.name}" />
  </h:column>
  <h:column>
    <f:facet name="header">
      <h:outputText value="Value" />
    </f:facet>
    <h:outputText value="#{_cookie.value}" />
  </h:column>
</h:dataTable>

The value is an array of Cookie objects. The var is "_cookie" (I use an underscore to make sure the name does not intefere with any scoped objects). The table renders the header and footer as a normal JSF component, but then iterates over the data. In this case, it converts the array to a DataModel. It then sets the rowIndex which caused the rowData to return the current cookie (so a row index of 0 returns the first cookie and setting the index to 1 will cause the 2nd cookie to be returned). Basically this is a simple iterator pattern. Some components loop through all, some loop only through a subset (the table can loop through a portion using the rows and first attributes).

The most important thing to note is that even though there may be several cookies, there are only ever 4 outputText components (1 in each header and one in each column).

Encoding the Children

What happens to produce multiple <TR/> elements is that the TableRenderer encodes its children in a loop. Here are the steps of TableRenderer.encodeChildren:

  1. get the first row to be rendered from UIData.getFirst()
  2. get the number of rows to be rendered from UIData.getRows()
  3. write the <TBODY/> start tag
  4. loop until the correct number of rows have been rendered
    1. if row is not available then stop
    2. render the row, encoding all the children recursively

Understanding "var"

The var is not controlled by the renderer, but the component, UIData to be precise. Non-UIData components that loop perform similar logic if designed after the JSF table. The scope of the var is limited to when the <t:dataTable/> is currently iterating. To be exact, it is available when the rowIndex is not -1. In the UIData.setRowIndex(int) method, if the index is being set to a value not equal to -1, then the row state is updated for the appropriate index. If the value is -1, the state is cleared.

The state is comprised of all the children components that implement EditableValueHolder. So before the row index is changed, UIData saves the value, localValueSet, valid and submittedValue properties for each child below the table and restores any state saved for the new index. This means that only EditableValueHolder components may vary state for different rows. Non-EditableValueHolder components may only vary their behavior (a.k.a. attributes) per row by using EL expressions that use a value that changes per row, like var.

The code stores the row data for the current row into the request map using the value of var as the key. When the row index is set to -1, the key and value are removed from the request map. This means that if the var is the same as another request map variable, it will be overridden and then lost. Therefore, it is very important to use a value for var that will not conflict with other request map variables. This is why I always prepend my var values with and underscore.

Note:
The var is only in scope when the UIData's row index is not -1. This means that it is not available when the component tree is being built, or usually when accessed from outside the component. If you would like to get access a child component of UIData with the correct scope, you must set the row index to the desired value, otherwise the data will not be there.

Other Phases

The decode, validate and updating processes of the <h:dataTable/> work the same way as the rendering. They loop through each row index and invoke the appropriate methods on the children components. Since the code to alter the var and save and restore the states is in UIData, the behavior is shared.

Understanding Client IDs

You may have noticed that the client IDs of looped components are altered in a table. Take this use case:

<h:dataTable
  id="cookies"
  var="_cookie"
  value="#{facesContext.externalContext.request.cookies}">
  <h:column>
    <h:outputText id="cookieName" value="#{_cookie.name}" />
  </h:column>
</h:dataTable>
<h:outputText id="after" value="After the table" />

The two <h:outputText/> components will have different client IDs. The one outside the table will just be "after" (assuming that there are no parent naming containers). The one in the table however will be "cookies:0:cookieName". The number, '0' in this example, will be the row index. This happens because the UIData component returns a different ID from getClientId when the row index is not -1. The code from the JSF RI (a.k.a. Mojarra) is:

    @Override
    public String getClientId(FacesContext context)
    {
        String clientId = super.getClientId(context);
        int rowIndex = getRowIndex();
        if (rowIndex == -1)
        {
            return clientId;
        }
        return clientId + NamingContainer.SEPARATOR_CHAR + rowIndex;
    }

As you can see, NamingContainer.SEPARATOR_CHAR + rowIndex is added onto the end of the table's client ID when the row index is not -1. This ID convention stops ID collision in the HTML, but it also is used for event broadcasting.

Update: 2007-06-22
Just today, I found an "interesting feature" of UIData. After looking into Jira ticket TRINIDAD-1514, I found that UIComponentBase in both the RI as well as MyFaces caches client IDs. This means that a client ID is not re-generated per-stamp. What happens is the UIData has a kluge to surf all of the components recursively of the UIData, setting its ID to the same value. The setId() on UIComponentBase clears the cached client ID, even if the ID is not actually changed by the function. It is an interesting piece of code (a.k.a. ugly hack). I thought it would be good to mention it here.

Event Broadcasting

When a child of the table is decoded, it decodes correctly due to the client ID. Take for example an <h:inputText id="myInputText"/> component that is in a table. Using just two rows as an example here is a map of the client IDs:

Row Index Client ID
-1 myTable:myInputText
0 myTable:0:myInputText
1 myTable:1:myInputText

When the renderer for the input text is decoding, it looks for a value submitted by the client using the client ID as the key. Since the client ID changes, the input text correctly decodes the value from the client for the current row index.

Now this is great for decoding, but a different mechanism must be used for the queuing and the broadcasting of events. The UIData component wraps all events in a wrapper class that stores the event being queued, the client ID of the UIData component and the current row index. Here is what each property is used for:

Client ID
The client ID is used in case this table is nested in another table. By identifying the event to broadcast using this ID, the framework can ensure events are broadcast to the correct state of a nested looping component.
Event
The original event that will be unwrapped during broadcast. The wrapper delegates much of its functionality to the wrapped event (like the phase ID).
Row Index
During broadcasting of the event, this stored index is used to correctly re-position the model to the correct row so that the event is fired in the same row state as when it was queued.

Binding

When binding looping components or children of them to managed beans, it is important to realize what the row index is. For example, if you have an <h:commandLink action=#{bean.actionMethod}"/> component as a child of a column in a table, the action method is run in the scope of the correct row index. This is because the event is wrapped knowing the correct row index. Therefore, your action method may access the current row data.

Also since the var's scope is only valid during iteration, it is not accessible during the construction of the component tree. Therefore and JSP tags or Facelets TagHandlers may not attempt to retrieve row data using the UIData APIs.

Conclusion

The data table component and looping components like it re-use a set of components encoded several times, once for each item to be rendered. The value, submitted value, if the component is valid and if the local value is set properties of EditableValueHolder children components are supported across iteration of the model. Other properties of components are not saved and thus must use EL to vary their behavior based on the current row.

Client IDs and event wrappers are used to ensure that the event model of JSF is not broken by the iteration of the component.

Hopefully this helps you understand looping components better and helps you design better pages as a result. Thank you for reading.

Tuesday, March 18, 2008

Build time vs. render time

Overview

There always seems to be someone posting about how MyFaces or JSF is "broken" and it turns out that they misused JSTL tags. No matter how many times a solution is posted, the issue comes up again. Therefore, I am writing this blog to help those that do not understand how facelets and JSP view handlers work.

The Problem

JSF works entirely differently than JSP. JSP, when used for JSF, is used to build a JSF component tree, not render a page. JSTL tags alter the contents of what is built, the component tree, not the HTML that is output by the component renderers.

A Background of JSP

JSP was written so that authoring servlets would be easier. JSP pages are servlets, nothing more. Using a JSP compiler, a JSP file is compiled into a Java Servlet. Before tag libraries were introduced, JSP pages simply were compiled down into System.out.println(...); statements.

Tag libraries enhanced JSP by providing an API to tag authors to write Java code that would not have to be embedded in <% ... %> tags. The tags gave developers access to the text content of the tag body so that they could alter it or use it in a custom way. After some time, Sun released the Java standard tag library API, also known as the JSTL.

The JSTL

The JSTL is a set of JSP tags to perform common JSP functionality (note that they are not related to JSF in any way at all). Many of them perform logic to alter their contents. In the case of c:if and c:choose, they choose which tag contents to be included in the response or not.

I will be mainly talking about the JSTL core tags in this article (catch, choose, forEach, forTokens, if, etc.). It is these that have such a profound, and often confusing to some people, affect on JSF.

What JSF Is

JSF is a component technology, and architecturally is not related to JSP at all. In fact, using JSP with JSF has drawbacks, included serious performance implications due to the architecture of JSP and how the JSP view handler works.

Note

Sun probably made the default view handler as one that uses JSP, so they would not have to admit that JSP did not meet the needs of users and needed to be replaced.

Component Technology

What I mean by JSF being a component technology, is that HTML is produced by the processing of a component tree by renderers. This design is much more similar to Swing than it is Servlets and JSP. Regardless of the view handler that is used, a tree of components is built.

Note

A component is simply a Java Object that implements the UIComponent interface, nothing more.

These components simply store attributes, have some behaviors and are similar in nature to the Swing Tree component. JSF relies on renderers (classes that extend Renderer) to produce content from the component tree. During the restore view, a JSF view should be restored to its previous state, so that it appears to code that there was never a round trip for the code to the client (this is important as I discuss the JSTL tags and especially c:forEach).

Note

Components do not have to use renderers to produce their content, but it is considered bad design to use the encode methods in a component to render a response.

Note

JSF is typically used to produce HTML, but can be used to generate any output that doesn't even have to be XML related, although the ResponseWriter's API is designed for XML content.

JSF with JSP

JSF is implemented using JSP by default (see my note above why this stinks). What this means is that JSP is used to build the JSF component tree. This is important to note because JSP is not used to generate any of the HTML, unlike a typical JSP page. There are two main stages of JSF on JSP:

  1. Building of the component tree using JSP tags
  2. Rendering of the component tree using the standard JSF lifecycle

Building of the component tree using JSP tags

As I mentioned earlier, JSF is a component technology. When JSP tags are used, instead of writing text (HTML) onto the servlet response, the tags create components and set attribute values on them. Most of this work is done by UIComponentClassicTagBase. The class hierarchy is:

  • java.lang.Object
    • javax.faces.webapp.UIComponentTagBase
      • javax.faces.webapp.UIComponentClassicTagBase
        • javax.faces.webapp.UIComponentELTag
        • javax.faces.webapp.UIComponentTag

The doStartTag method of UIComponentClassicTagBase calls findComponent, which despite its name creates the component (if needed) and calls setProperties. Therefore, the JSF component is created when the start of the JSP tag is processed. The setProperties method is responsible for setting the attributes of the component. Typically there is a one-to-one map of JSP tag attribute to JSF component attribute, so the setProperties simply copies the attributes over, doing any necessary conversion of the string value in the JSP attribute to an object that the component expects for the attribute.

How JSTL fits in

Most of the "work" of a component takes place during rendering. For example, the h:dataTable sets up the var attribute during rendering (and other phases too, but that is not pertinent to this article). This means that EL expressions that rely on variables that only have scope during the rendering phase are not valid during component creation. That is to say, there is no component lifecycle method for when the component is created.

Since JSTL tags are plain JSP tags and do not involve the JSF lifecycle, they do not have access to the environment that components create, like the var variable of an h:dataTable. Take this code for example:

<f:view> <h:dataTable var="_row" value="#{bean.rows}> <h:column> <c:choose> <c:when test="#{_row.editable}"> <h:inputText value="#{_row.value}" /> </c:when> <c:otherwise> <h:outputText value="#{_row.value}" /> </c:otherwise> </c:choose> </h:column> </h:dataTable> </f:view>

Although from the pure XML standpoint this looks valid, it is not. Thinking about what I just said it is a simple problem:

  1. Data table component created from the data table JSP tag
  2. Column component created from its JSP tag
  3. The when tag in the choose attempts to evaluate #{_row.editable}
    • Since _row is not bound (yet) in the EL resolver, null is returned
      (an argument could be made that the EL engine should throw an error or at least give a warning, but that is not how it is designed)
    • Since null is technically false, the outputText is created instead of the inputText
  4. The output text component is created by its tag

So the page author was probably expecting that the choose would be evaluated for every row in the table. But the table has no rows at this point, the component is being created. So, the inputText component is never created as the when tag will not process its contents if the test fails.

The proper solution is to use JSF functionality and not JSP functionality. To the confusion of JSP developers, there are no c:if, c:choose or c:forEach equivalent components (see the Tomahawk Sandbox limitRendered for c:if and c:choose functionality and the Tomahawk dataList or Trinidad iterator components for c:forEach type of functionality). Without third party components, the rendered attribute can also work, although it requires more work:

<f:view> <h:dataTable var="_row" value="#{bean.rows}> <h:column> <h:inputText value="#{_row.value}" rendered="#{_row.editable}" /> <h:outputText value="#{_row.value}" rendered="#{not _row.editable}" /> </h:column> </h:dataTable> </f:view>

In this case both the input and the output components are created. The rendered is evaluated by the renderer during the rendering phase while the data table is iterating over each of its rows.

When it is okay to use JSP tags with JSF

So now that you know the problem, you may ask why is using any non-JSF, JSP tags allowed? This is because they still work, but must be used correctly. Since JSP tags are evaluated while components are being built, they can control which components to create. For example, I may want to include certain components in a page template if the current user is an administrator. Because the components are not created if the user is not an administrator, there will be less components objects created and less components to process for each JSF lifecycle phase, and thus improving performance.

It is very important to remember that you cannot have components "re-appear" on post back of a JSF form. This is because a JSF component tree should never be altered between having its state saved and when its state is restored. This is very important, so let me say again, a JSF component tree should never be altered between having its state saved and when its state is restored. The reason is that this would violate the JSF specification/design. Take for example a c:forEach loop that when evaluated had five items it its list. Assuming that there was one JSF component tag inside the for each tag, that means five components were created. Now JSF saves the state for five components. Then lets say this for each loop data is coming from a database that can change and now there are only four items. When JSF attempts to restore the component tree, there is data for 5 components, but there are only 4 in the component tree. This causes a restore state exception.

Therefore, always ensure that when a component tree is restored, it is not changed! There is no problem changing a component tree after restoring it or before saving it, only between those times.

Hey, what about Facelets?

I did mention that I would talk about facelets, didn't I?

Facelets is similar in its behavior to JSP although it has much more efficient code and is designed quite differently than JSP. Instead of JSP tags, facelets has TagHandlers. These tag handlers analyze the XML content of a facelet and create components. Just like JSP tags, the tag handlers have no access to the render-time scope of the components. In fact, facelets provides tag handlers to mimic the JSTL functionality. These tag handlers have the same pitfalls as the JSP tags. Therefore, the same considerations and rules apply to tag handlers that apply to JSP tags.

Other Blogs

Here are some other helpful resources on this topic: