Oli Brown wrote:So if I need to retrieve an entry from the database based on a particular clientID, I am supposed to have a separate get method for each entry? Without knowing how many entries there are? Or how many are going to be added in the future?
No. Absolutely not!
JSF has a set of Model wrapper classes for dataTables. They're all based off of javax.faces.DataModel. The most commonly-used ones are ListDataModel and ArrayDataModel, but there are others, and I even occasionally subclass the List and Array DataModel classes when it's useful to do so.
What a DataModel does is decorate your raw data (List, Array, or whatever) with some extra JSF-specific enhancements (cursor capabilities). You can then use the DataModel's getRowData() and getRowIndex() methods in your action method to determine precisely which table row was selected without either coding logic (parameters) on your View Template or implementing multiple action methods, one for each row.
If you pass a raw collection as the value of a dataTable tag, a DataModel is produced automatically, but it's an anonymous DataModel, and you have no way to access it to employ its cursor methods for your benefit. As a rule, I only recommend using raw data in a dataTable when you won't need those methods. Which is primarily when you're doing a simple display without any need to click on any of its rows. You don't save much effort by not supplying your own dataTable and don't expect things to be any more efficient if you lest JSF do it - the amount of work done by JSF itself is just about the same.
A DataModel wraps data. You can either pass in the wrapped data (List, array, or whatever) in its constructor, or you can set/update it via its setWrappedData() method. The 2 approaches are equivalent. Once wrapped, you don't have to do anything further to the DataModel. Changes to the wrapped data itself reflect automatically, so the only time you need to change it is if you're throwing away the original raw data and replacing it with an entirely new set of data.
In practical terms, since a DataModel is pretty low overhead, my typical method for triggering a (re)read of the raw data is to set my table's datamodel to null. My "get" method considers this as a trigger to load the appropriate raw data, wrap it, and cache the results as a new datamodel.
Incidentally, DataModels (whether explicit or implicit) are one reason why I say that "Request scope is almost 100% useless in JSF". The DataModel contains cursor information carried over from the last request/response cycle. If you use Request scope, that DataModel is destroyed and a new DataModel is constructed - but the cursor information is now gone.
DataModels are one also one of the few exceptions to my famous Rule #1 of JSF - the more javax.faces objects and code in your app, the more likely you're doing it wrong. The Model classes (DataModel and SelectItems) are helpers that allow the data that they present to remain as POJO constructs while augmenting them with essential JSF capabilities.