Background
The Microsoft dominance in the browser wars, and their subsequent reluctance to "innovate" browser standards forward in non-proprietary ways, had somewhat slowed the evolution of the internet browser.
But an ever increasing market demand for richer and more dynamic web applications has generated enough pressure to bring all the major technology players to the standards table. And the establishment of a cooperative technology community has allowed a definite (albeit slow) path forward in the evolution of the web.
Finally we are seeing progress as new advances in HTML, CSS, JavaScript (and AJAX), and a myriad of plugin technologies are allowing the browser to become a more dynamic and powerful platform for presentation logic.
Web page development is becoming more sophisticated than the plain old HTML and JavaScript of the past several years. This can facilitate a division of labor where one team of developers can specialize in presentation technologies, while another team of developers specializes for back-end development (in Java or C# or Ruby or PHP or whatever).
At the same time this trend is happening, there is a counter-trend in the Application Development space that emphasizes do-everything IDE's and end-to-end frameworks for automatic generation of presentation logic. Platforms like .NET emphasize the ability of a developer to drag-n-drop pre-coded heavy-weight components that will handle all the details of presentation logic for you. These frameworks can even automatically adjust your application to different presentation platforms, such as JSP, WML, XHTML, XML, PocketPC, Windows, etc.
I am impressed with how much presentation logic can be done WITHOUT Java these days, and I'm equally impressed with how much presentation logic can be done IN Java these days.
Whether you subscribe to the philosophy of "Web Development" or "Application Development" will vary from environment to environment and project to project, depending on your requirements and resources available.
As a developer, I have no particular bias toward either methodology, other than I know my GUI design skills are luke-warm at best, and I do think I can deliver a higher quality product when I can team up with a more artistically-inclined developer helping me with the presentation in some fashion.
Java Frameworks
Now what on EARTH does all of that stuff above have to do with JSF Iteration tags? Well, oddly enough, these are the kinds of philosophical underpinnings that you have to know in order to understand the design decisions that went into the JSF specification.
Most modern Java Web Frameworks (like JSF and Struts) do have heavy-weight tag components (like Table tags and Panel tags and Tiles) that can speed up your page development greatly, but will do so at the expense of burying presentation control in Java instead of in HTML.
One school of thought says we should let Java handle presentation. Another school of thought says that presentation technologies are most effective when used independently of Java and natively. The same debate occurs with O/R mapping tools, like Hibernate and Toplink, which allow Java to generate all the SQL for an application. However, a SQL programmer working independently of Java can craft far more powerful and efficient SQL statements and stored procedures than Hibernate ever will. There are tradeoffs to choosing either path here.
JSF is one of those "encapsulating" types of technologies that was designed to be IDE-friendly to give the developer the ability to have drag-and-drop Web Application Development similar to .NET. (I have no doubt that JSF was created partly in response to competitive pressures from the .NET platform.)
And one of the most common (and legitimate) criticisms leveled against JSF that it's about one step away from replacing all of HTML with it's own web component markup language. (Just as Hibernate is replacing SQL with it's own particular query mechanisms.)
The jury is still out on how far Java can really go with that paradigm, because JSP is already a major kludge of a presentation technology without proper boundaries between form and function, and as such is not an appropriate container for a stateful component-based UI framework. But it appears that the Java Community will be addressing these issues by improving the JSP specification rather than kluging up JSF. And in the long-run I'm optimistic that they will come up with better web presentation technologies.
And even the heavy-weight tag libraries do have support for CSS, and can expose HTML to some extent, and so separation of the presentation layer is still achievable. Replacing the "<input>" HTML tag with the "<h:input>" Java tag need not steal any creative control away from your presentation developers. (Although it might make the page play less friendly in some WYSIWYG HTML editors.)
JSF iteration and JSTL iteration
The JSF tag library is complimented (and complicated) by another interesting tag library in Java called the "JSTL" (Java Standard Tag Library). JSTL is light-weight and HTML-friendly. But it also only provides a simple set of features and simple re-usable components. It has no back-end model/control layer like JSF and Struts.
The JSTL tab library has been part of the Java standard for quite a while. JSF is new to the Java standard. And there is significant overlap between the two tag libraries, which introduces interesting issues.
Both tag libraries have their own Expression Language (EL) for accessing properties in your model objects.
Tip #1: In both JSTL and JSF, EL is ONLY meant for accessing properties, not calling methods. Yes, you can easily kludge an EL statement into calling a Java method, but you are asking for long-term trouble. I know because I've been guilty of this. Both JSF and JSTL were developed under the design philosophy that method calls from the JSP page represent model-logic spilling into the presentation layer, and is a sign of bad design.
In JSTL, EL statements start with a dollar sign $ and are enclosed in curly braces {}. In JSF, EL statements start with a pound sign # (octothorpe) and are enclosed in curly braces.
JSTL: ${myObject.property}
JSF: #{myObject.property}
Isn't THAT nice and confusing! :)
Alright, lets go a step further and point out that both JSTL and JSF use nearly identical storage mechanism to access named objects in the session and request. So, a JSF session object called "widget" can be accessed from a JSF tag as #{widget} OR it can be accessed from a JSTL tag as ${widget} without having to even declare it in JSTL.
Objects in JSTL are created and dropped into the session (or request) using the "jsp:usebean" tag, whereas objects in JSF are declared in the control XML file as managed beans and created upon first use.
Here's a cheery article about the blending of JSF and JSTL written by someone who thinks this tag overlapping between JSF and JSTL is cool:
http://www.javaworld.com/javaworld/jw-12-2004/jw-1213-jsf-p2.html
JSF and JSTL tags can be used together in the same page. However, a general rule of thumb I've learned from my own experience and reading is that you should not nest one tag type inside of the other, ESPECIALLY tags that iterate.
Tip #2: Don't nest JSF tags inside of a JSTL "forEach" tag. And don't nest JSTL or HTML tags inside of some kind of an outer JSF tag. If you need to embed HTML into a JSF tag, use a "f:verbatim" tag.
Nesting JSF inside of JSTL (and vice-versa) CAN be done. I've done it. But you to be very careful and implement just the right kluges to bridge the different storage and state mechanisms used by the two tag libraries. Often this involves some sort of c:set tag to drop a JSTL variable into the request, and then a JSF EL statement to pick it up. And even then this solution is only stable so long as you are just displaying data. The moment you try and introduce clickable controls and actions into the iteration, you run the risk of corrupting state, because JSF will not be aware of JSTL iteration.
Example: If you assign an "id" to a JSF control, and then put that control inside a JSTL iterate tag (forEach), then you end up with multiple controls with the same "id" in one page when JSF isn't expecting that. And that causes problems. If you let the page dynamically assign id's, then you have another difficulty in not being able to easily detect which control the user clicked on, and JSF will be unable to properly re-populate form controls if the JSTL "forEach" tag generates a different number of rows the next time the page is drawn.
You can run into similar problems if you put JSF tags inside of a JSTL c:if tag. JSF will assign a concrete id to a control that may or may not be drawn the next time the page is refreshed, and that's a recipe for trouble.
Tip #3: Conditional rendering in JSF should be handled by putting your test in the "rendered" attribute of a JSF tag rather than by using c:if tags.
If you design your pages properly and use the full potential of JSF, you can get by without using JSTL tags for the most part.
So far, JSF is awesome as long as you don't cross weave it in JSTL tags. HOWEVER, I really do wish JSF had better iteration tags with support for embedded HTML like JSTL does!
Iteration is a particularly nasty issue, because any kind of table or list you want to display in HTML implies some sort of a "loop", and there are no native HTML iteration mechanisms that I am aware of. So you must use a Java tag to repeat sections of HTML.
JSF comes with a wonderful heavy-weight tag called "dataTable" that will generate an entire HTML table with tons of features and customizable columns. The problem is that the heavy-weight tag generates all the HTML for you as "table" tags. If you want to generate a table using Dictionary Lists <dl> instead of Tables <table>, you are out of luck. You could extend the "dataTable" tag or write your own tag that generates different HTML, but that still hides the HTML in Java code where your web designers can't reach it.
I want to be able to iterate across a list of Java objects, but I want to leave all the HTML code in the JSP page, and yet I still want to use other JSF tags inside of this iteration. Apparently that's a tall order!
I hate to overly criticize JSF just for having weak iteration support, but this has become an issue on my current project, because it seems that over half of the pages in our application need some kind of big iteration. And furthermore, most of these lists need dynamic behaviors and clickable controls with conditional navigation and so on (which means they need nested JSF tags.)
All of these things are well-suited for a heavy-weight tag that would give me control over everything. But that would come at the expense of me stealing the presentation layer as well.
So, early on, I abandoned the heavy-weight tags, and instead tried for the JSTL/JSF hybrid by kluging JSF controls into a JSTL iterate. This allowed for free-form HTML inside of the JSTL loop, and yet I could drop in some JSF commands where needed.
For reasons stated above, this became more klugey and unstable as the users demanded increasingly dynamic behaviors out of my lists.
My solution looked something like this:
<dl>
<c:foreach items="${myHandler.dataModel}" var="loc" varstatus="loop">
<dt class="name">${loc.name}</dt>
<dd class="title">${loc.title}</dd>
<dd class="action">
<c:set var="id" value="${loc.id}" scope="request">
<h:commandlink action="select"
actionlistener="#{myHandler.selectItem}">
<f:param name="id" value="#{id}">
<h:outputtext escape="false" value="Select">
</h:commandLink>
</dd>
</c:forEach>
</dl>
-
This kind of solution required some kluging on the back-end to figure out which commandLink or commandButton the user clicked on. And if clicking on an item resulted in a new item being added to the list, it would just corrupt state completely. So, in general, this solution is only stable enough for displaying data, as long as you don't have any clickable controls in the list.
I could take this solution one step further and not use any JSF tags inside of my iteration, and make it a pure JSTL loop. That would work great. But I would be running outside of the JSF framework, and that pretty much takes me back to plain old JSP's and Servlets.
So, we come to solution #3, which is to use JSF to perform the iteration, but use a different JSF tag than "dataTable". Fortunately, JSF is a highly extendable platform for creating your own tags, and there are lots of good 3rd party tags available. The Oracle ADF implementation of JSF even promises new "forEach" and "iterator" tags, but I haven't heard how well those actually work inside of JSP.
On my given project, we are using Apache MyFaces, and there is a "dataList" tag that is part of the MyFaces extension package. (And we have the source-code for this tag, so we can continue to use it even if we move to a different JSF implementation.)
<%@ taglib uri="http://myfaces.apache.org/extensions" prefix="x"%>
<x:dataList id="myList"
var="loc"
value="#{myHandler.dataModel}"
layout="ordered"
rowIndexVar="loop">
<f:verbatim> <dl> </f:verbatim>
<f:verbatim> <dt class="name"> </f:verbatim>
<h:outputText value="#{loc.name}">
<f:verbatim> </dt> </f:verbatim>
<f:verbatim> <dd class="title"> </f:verbatim>
<h:outputText value="#{loc.title}">
<f:verbatim> </dd> </f:verbatim>
<f:verbatim> <dd class="action"> </f:verbatim>
<h:commandlink action="select"
actionlistener="#{myHandler.selectItem}">
<f:param name="id" value="#{loc.id}">
<h:outputtext escape="false" value="Select">
</h:commandLink>
<f:verbatim> </dd> </f:verbatim>
<f:verbatim> </dl> </f:verbatim>
</x:dataList>
-
As you can see, this allows me to do a true iteration over a list of Java elements, and it also allows me to specify all the HTML generated by this tag. YAY! The only catch is that I have to specify the HTML using a ton of f:verbatim tags...which is really ugly. Bleh! But if this is the only bad constraint we have to deal with in order to keep 100% of the HTML in the JSP page, then I suppose it's acceptable.
The reason we have to use f:verbatim is because JSF by it's very design cannot interweave with JSP elements (like HTML) within a tag. You can put all the HTML you want AROUND JSF tags, just not within JSF tags. JSF is a stateful UI component technology, so think of each JSF tag as a solid box that you can place anywhere on page, but which will cover up any HTML it sits on top of.
The reasons JSF is designed this way have more to do with weaknesses in the JSP standard rather than any kind of undue stubbornness in the JSF design philosophy.
Here is an article by the author of the O'Reilly book on Java Server Faces discussing the technology issues involved:
http://www.onjava.com/pub/a/onjava/2004/06/09/jsf.html
Here is another good article that addresses the current state of affairs with JSF, Struts, and JSP:
http://www.devx.com/Java/Article/28420/0/page/1
I suppose another option is to go back to using heavy-weight JSF tags. I believe this is what the designers of the JSF standard had in mind for my situation. That would give me easy control over the iteration, but then I would be responsible for the HTML used to draw that table. And perhaps that's not so bad considering the tags can still take CSS directives as inputs, and our Web Designers will still have creative control over about 90% of the page.
There are many articles posted on this subject describing why JSF was designed the way it was, and what kinds of things can be done with the future with JSP to allow for JSF objects to interoperate with the script-like flow of a JSP page.
Everything we have today is quite usable and effective. It's just that some parts are not as elegant and complete and consistent as we would like, and the developer still insufficiently insulated from all the behind-the-scenes plumbing issues. Nothing is as easy as it could/should be. And there are several competiing philosophies at work that are trying to drive these technologies in different directions. So, perhaps there will continue to be several evolving and competing efforts in this space for much time to come.
OR maybe I'm just stubbornly resisting any technology that generates HTML the same way I stubbornly resisted Hibernate because it generated SQL for me. But somehow, I do think the ability to hand-craft HTML is more important than the ability to hand-craft SQL, especially when the presentation layer of your site is what really sells the site!
1 comments:
Good article!
After a year of working with JSF and MyFaces I've come to the conclusion that iterating over data (combined with A4J) is a nightmare. You need a heavyweight component to do the simplest thing.
Often you need just 20 characters of logic in your display code, for example when putting in a class to make an item look 'selected'. So what do you do?
- JSTL is very limited, and you can often not reach the data contained in your Bean.
- Your off-the-shelve component does not support what you are trying to achieve, and only a HUGE component will cover all the ways people will want to use it.
- You end up writing a component for almost every beyond-very-basic page.
You end up spending hours writing a component for this exceptional case that would have required only 20 characters in (excuse my french) PHP. I love JSF, it is a well structured framework for tiered java apps. But it fails miserably when you are trying to build a modern, ajax-enabled application rapidly.
You just want direct control over the html code sometimes. I must say that you did a nice workaround with the verbatim tags. But adding ajax to the equation will probably not work there.
Framework developers hear my call: I want rapid development, not bulky components! :p
-Sav
Post a Comment