JSF 1.2 DataTable management during view creation

JSF 1.2 DataTable management during view creation

 I have a question on how JSF 1.2 manages DataTable exactly. Consider this table (suppose that tableList.persone has 3 items):


<h:dataTable id="tablePersone" value="#{tableList.persone}" var="item"> 
 
<h:column> 
<f:facet name="header"> 
<h:outputText value="STATO" /> 
</f:facet> 
<h:inputText value="#{item.stato}" /> 
</h:column> 
 
<h:column> 
<f:facet name="header"> 
<h:outputText value="CODICE" /> 
</f:facet> 
<h:inputText value="#{item.codice}" /> 
</h:column> 
 
</h:dataTable> 
<h:dataTable id="tablePersone" value="#{tableList.persone}" var="item">

<h:column>
<f:facet name="header">
<h:outputText value="STATO" />
</f:facet>
<h:inputText value="#{item.stato}" />
</h:column>

<h:column>
<f:facet name="header">
<h:outputText value="CODICE" />
</f:facet>
<h:inputText value="#{item.codice}" />
</h:column>

</h:dataTable>
 

I read that jsf iterates over the items of the list during the render response phase, in fact, "item" is not available when jsf builds the view.
Does it means that jsf does not duplicate the content of the table for each item in the list when creating the tree component?
In the table above, each row has 2 inputText. If jsf does not create a couple of inputText objects for each row, how jsf handles all the 6 request parameters when the form is submitted (in particular during the apply request values phase).
A dataTable is a 2-dimensional construct. While it is not uncommon to render it by iterating its model row-by-row and rendering each row sequentially, it is not a good idea to think in such terms. There is no particular reason why a parallel-processing engine could not render whole groups of rows - even the entire table in a single operation.

A datatable is simply a 2-dimensional rendering (View) of a 2-dimensional data collection (Model). How it gets rendered is immaterial. Or should be.

A more serious misunderstanding that many people have, however, is that there is a direct linkage between the backing collection and the View. This
misunderstanding is something that JSF2 has actually made worse.

The actual Model for a dataTable is an instance of javax.faces.DataModel. It is used as the
reference object to hold JSF-specific information relating to the rendering of the dataTable and to the determination of which row you click a commandButton/commandLink on.

In JSF 1, you had to explicitly create this object and wrap your actual data inside it. In JSF2, if you define a "value=" attribute to be a collection object, JSF will automatically construct and an anonymous model object to wrap that collection. However, I don't recommend letting it do this in most cases, since it is anonymous and therefore there's no easy way to query it when an action processor needs to know what row you clicked in.

There are no "request parameters" for a dataTable. JSF is based on Model/View/Controller. In JSF, the master controller is the FacesServlet and the sub-view controllers are the respective ui elements such as dataTable. The sub-view controllers are responsible for rendering what is in the Model to the View, and (for input controls), accepting changes to the View controls and translating them back into the Model.

In the case of the dataTable, there is no input side, and the output side is all done as part of the render-response phase.

JSF actually manages Views by constructing a View Component Tree. Being a tree (directed graph), it is a 2-dimensional construct with an anchor node and child nodes. As the various element definitions are compiled from their xhtml source, they cause component objects to be constructed and placed at appropriate points in the View Component tree. The Component Tree is constructed when the initial rendering of that View is done and it is what the HTML renderers use to produce the actual HTML sent to the client. When a form in that View is submitted from the client, the View Component tree is referenced in order to direct the validation and updating (if the data is all valid) of the Model(s) from the form data.

In between requests, the Component tree may be compacted for efficiency's sake and it is a configuration option as to whether it will be stored on the server (more secure, less network overhead, more server memory needed) or on the client (less secure, more network overhead, less server memory needed). A cache of compiled Views is maintained so that the Component Tree will not have to be compiled from scratch each time, but it's of limited (although configurable) size, and if you go too long without using that view, it gets dropped from the cache and a subsequent request will throw a ViewExpiredException.

Note that all of the View Component stuff is essentially magic internal to JSF itself. JSF is designed with the idea that you do most of your work with POJOs, and, in fact, the only JSF-specific code you would do for a dataTable would be the use of the DataModel class that wraps your collection data. Everything else is handled externally by the JSF framework.

They aren't request parameters.

XML requires that each and every id in an XML document must be unique. That is technically true even in the degenerate versions such as HTML. However, in the process of rendering a JSF View into an HTML document, often there is not a 1-to-1 correspondence between the JSF View Definition Language components and the resulting HTML components. Table rows are one such case.

What JSF does, then, is synthesize unique IDs using context as a basis. If it can't find anything else, it will make an ID component up. There is a JSF concept known as a naming container that defines ID bases. Among the most common naming containers are h:form, h:panelGrid and h:dataTable.

I don't think that there is any explicit rule in JSF as to how those synthesized IDs are actually composed, but most implementations will, for example, incorporate a row number as part of what makes the ID for a given row unique. It's not really safe to assume the format or content of these internal labels, although I will confess that I have exploited how my JSF implementation does implement them because at present JSF cannot accurately track rows of datatables that are themselves embedded within other datatables. Some day I may get punished for this, but it's the best I could do in the mean time.

As for what manages the mappings between the row IDs and the corresponding rows of the collection being displayed (your so-called "request parameters"), that is precisely the job of the DataModel object and it does it without any further interaction from you, simply by existing. When you click a button or commandlink that's in a table row, the action method invoked by that command will be able to tell which row you clicked on. It's available via the "rowData()" Datamodel method or the "rowIndex()" DataModel method if you prefer the collection index instead of the actual row object reference.

Because the DataModel works as the cursor for outbound rendering and the row-detection mechanism for inbound row data, it cannot exist with Request Scope. Request Scope destroys the original DataModel and creates a new one that doesn't contain the context that the old one did. For that reason, DataModel objects must be properties of beans with View Scope or higher.

JSF isn't actually a "web framework". What JSF actually is is a Model/View/Controller system that uses the web (specifically, J2EE/JEE) as its linkage between client and server. The level of abstraction is fairly high. For example, the same basic JSF application can potentially work in a completely non-HTML, non-HTTP environment. The actual web page rendering is all done via plug-in components that can be easily swapped out in favor of alternative presentation systems such as WAP or PDF, for example. The actual data submission is whatever the JSF architects determined would work best, and so any relationship to traditional web forms and parameters is mostly co-incidental.

Additionally, the traditional concept of submitting URLs takes a hit, since a large part of what JSF does involves a mechanism called "postback", where the user enters data, submits it, gets back error messages on invalid inputs, corrects them, re-submits, and so on until the data passes validation. You've probably also noticed that the displayed URLs in the browser don't always track the name of the resource being displayed, because the URL is used more like a "conversation handle" than it is a traditional resource locator.

There are also 3 other places where people not intimately familiar with JSF go awry. One of them is that if you attempt to wrest direct control of the HTTP Response object from within JSF code, you will generally regret it, since JSF assumes that only JSF will be accessing the Response directly.

The second, and more common one is the idea of bouncing data back and forth between Model and View. JSF generally works on the idea that data is held on the server and that most data interactions will be between objects on the server. It facilitates this paradigm via such things as its Inversion of Control architecture that allows JSF to wire beans together.

The third, and worst way that people typically go astray is when they start putting logic in the View template. This is bad for several reasons. It de-centralizes functionality, since you can no lon

[1] [2] Next

Copyright © 2007-2012 www.chuibin.com Chuibin Copyright