Tuesday, March 18, 2008

Build time vs. render time

My blog has moved, please update your links. You can find this article here

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:

Monday, September 17, 2007

Trinidad versus Tomahawk component architecture

My blog has moved, please update your links. You can find this article here

I have been using Tomahawk quite a while and building several custom components with it. Relatively recently, I have incorporated Trinidad in a new project I am working on due to its AJAX support and large number of components.

Yesterday, I attempted to incorporate maven-faces-plugin into my project from the Trinidad code base. After trying it out, I have decided to back it out of my project, partially due to the amount of work, and mostly due to the architecture of Trinidad components.

Why is Tomahawk a better component development platform?

Yes, a bold statement, but I wanted to get your attention. Trinidad has a great offering, a lot of components, AJAX support and a good set of APIs, but there may be a large architectural flaw. This flaw is the architecture of Components and renderers around the FacesBean.

Comparison:

What I found is that Tomahawk follow an OO paradigm, but Trinidad breaks OOD standards. One of the major aspects of effective OOD is encapsulation. This basically means that the functionality an Object provides comes from the component itself. Tomahawk has a special map behind the getAttributes() method of each component. This map delegates the attributes to the property getter and setter methods of the component. Take for example:

// MyComponent comp; String value = comp.getMyProperty(); value = comp.getAttributes().get("myProperty");

These two lines of code are identical in terms of functionality, they both call "getMyProperty()" on MyComponent. This means that component developers know that the getter and setter methods of their component will be called, and they have the control to provide any functionality that is needed besides just storing and retrieving a value (they can manipulate values, check for illegal arguments, etc.). This illustrates a good comprehension of encapsulation, that the functions of MyComponent provide the functionality of MyComponent.

Trinidad works in a completely different way. Each UIXComponent has a FacesBean instance that is tied to a static Type that dictates what values are stored during state processing of the component. The getter and setter methods of the components retrieve and store values into this FacesBean. The break in encapsulation is that this FacesBean is made public. That means that people can access the FacesBean and get values without a reference to the component. Encapsulation is lost, the component no longer has any control over the functionality for its own properties. To make matters worse, all of the Trinidad JSP Tag classes and the Trinidad renders use this FacesBean directly, taking the component completely out of the picture.

Code generation

There were other issues that I had with the maven-faces-plugin. The biggest, is that this plugin drastically affects your project layout and architecture. Unlike the Tomahawk code generator which injects code into a component's source, Trinidad actually generates the entire component. This means that the Trinidad components have to be their own maven project. Furthermore, there is a two step process which requires a third project (i.e. trinidad-build, trinidad-api and trinidad-impl). After refactoring most of my code into this layout, the plugin still didn't work. It wasn't generating the taglib.xml files. Unfortunately the plugin is not documented

Conclusion

My conclusion from my research is to not use maven-faces-plugin for my project. For my custom components that extend Trinidad components, I am forced to use the FacesBean architecture or else risk breaking the Trinidad renderers, or at least not being compliant with the design.

To the Trinidad team:

Adam and the Trinidad team, what do you feel about inversing the FacesBean? What I mean by this, is that currently the get/set component methods store the values into the FacesBean. What about taking the design of the Tomahawk components and having the FacesBean call the get/set methods on the component to get their values and have the get/set methods of the component actually do the work? Since the code is generated, the cascade of the change shouldn't be too bad. Only people that have extended these components without using maven-faces-plugin would be affected.

Since this would break backwards-compatibility, Trinidad's major version could be bumped.


Updates and responses to comments

2007-09-17

Simon,

Yes, I know that the performance will be better and the generated code smaller, but is that a good reason for breaking standard OOD? With this model, the component's properties are reduced to the security and functionality of public fields.

I am a very strong believer in usage of OOD for Java objects and the current design forgoes the UIComponent design by having the renderers bypass the component and the component attributes by delegating component properties to the FacesBean.

Is the efficiency of FacesBean worth the cost of bypassing encapsulation and reducing a component's methods to not much more than a Map?

JDK 1.5 has made reflection much faster, and if the Method references were cached, it would be a much smaller performance hit. Take EJB3 for example, it uses reflection plus annotations to get and set values for database access. Even though there is a performance hit, the API remains viable for production use.

Instead of using FacesBean, renderers could use the attribute map instead, this would ensure that renderers remain component agnostic. For example:

public void encodeBegin(FacesContext facesContext, UIComponent comp) { Map attrs = comp.getAttributes(); Renderer delegate = getMyRendererDelegate(); delegate.renderStuff(facesContext, attrs); }

Or

public void encodeBegin(FacesContext facesContext, UIComponent comp) { Map attrs = comp.getAttributes(); String styleClass = toString(attrs.get("styleClass")); } protected String toString(Object obj) { return obj == null ? null : obj.toString(); }

In these crude examples, the renderer doesn't care what the component is, only that the component may (or may not) provide a specific attributes. In the first example, the delegation renderer can access the attributes to get a styleClass for example. The second example shows a class accessing a property via the attributes

With this paradigm, a renderer developer may choose to access the component directly (cast the component to one it supports) or use the attributes. If it uses the attributes, it choose to be able to support behaviors rather than types. In this way, renderers that are used as delegates could simply rely on the attribute map.

In terms of performance, the attribute may could cache, in a transient variable, the Method to call for the get and/or set property accessors. The component could choose to use FacesBean, or just store the value in a member variable. I know there is some performance overhead, but this is a side effect of a good encapsulation with the flexibility that you desire from the loose-binding a.k.a. late binding you desire for renderers.

2007-09-17

Adam,

The reason FacesBean violates OOD is that it delegates the behavior of the UIComponent to the FacesBean. The UIComponent no longer has any control over its own properties and is no longer aware of external accesses to its own data. Also, the way that an object chooses to serialize its data (saveState, restoreState behaviors in JSF), is an internal, not external function.

With the FacesBean being a public object, a piece of code can easily change the value of a property to something illegal, and the component has no opportunity to validate the new value.

Lastly, the component has no control over removing attributes. With proper use of encapsulation, a component could remove an attribute, maintaining the get/set properties as deprecated but store the value elsewhere. With the FacesBean, the component now is permanently bound to the data that it serializes, as people now code against the PropertyKey names instead of the exposed properties. The way that the FacesBean architecture is made, the private fields of UIXComponent have been made public.

2007-09-17

Simon,

Good point on the sub-classing FacesBean, perhaps I should give that option more thought. If I have the incentive and time, I may decide to create a new blog entry on customizing the FacesBean to create validation methods, the ability to create access methods (handle set/get) as a proof of concept.