Hi all, I have a question on how JSF 1.2 manages DataTable exactly. Consider this table (suppose that tableList.persone has 3 items):
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.
An IDE is no substitute for an Intelligent Developer.
Joined: Jun 12, 2011
Hi Tim, could you tell me how a <h:dataTable> is added to the jsf view exactly and what happens to the request parameters of the table during the apply request values phase? Thanks a lot
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.
Joined: Jun 12, 2011
Hi Tim, thanks a lot for the complete explanation on how jsf build its views.
Just a last question on request parameters handling: when I said "the request parameters of the table" I meant the request parameters generated by the presence of input fields inside the html table rendered from an h:dataTable.
This is what the http post contains when I "submit the previous table" (from tab "net" of Firefox):
I added some ids to the previous table but the structure is exactly the same:
myform is the id of the h:form
in1 is the id of the first inputText in the table (STATO)
in2 is the id of the second inputText in the table (CODICE)
I think that jsf has to store these values somewhere during the apply request values phase and the presence of an index in the name of the 6 parameters seems to "remember" to jsf how many rows are in the table.
Is it possible to know what happens to these 6 request parameters or I'm too paranoid considering that the main purpose of a mvc framework is to forget about http posts (as your last sentence said).
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.
Joined: Jun 12, 2011
Hi Tim, ok Jsf applies its mechanisms to make dataTables easy to use, I see.
There is only one thing that I don't manage to understand: why they are not request parameters exactly? When I spoke about request parameters I always wanted to refer to these 6 key/value pairs
They are inside an html form and are added to the body of an http post when the form is submitted. I think this makes them request parameters.
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 longer look at a single object to see what the logic is, and in the worst-case can even result in maintenance issues when Model and View have co-dependent update requirements. It makes looking for logic a "treasure hunt", because you know longer have a simple rule for locating application logic. And finally, EL is a right royal to debug anyway, so it's better to do the serious work in Java code.