|
||||||||||
PREV NEXT | FRAMES NO FRAMES |
See:
Description
Packages | |
com.sun.data.provider | Fundamental data access APIs and event listeners. |
com.sun.data.provider.impl | Concrete DataProvider implementations and base classes. |
This package provides abstract API for accessing (both read and write) data that may be acquired from a variety of sources. The APIs serve to insulate client applications (for example, a web application using JavaServer Faces components bound to these values) from the details of acquiring, caching, or updating the underlying data.
Presume you have a Java class named Customer
, which has
typical properties like id
, name
,
address1
, address2
, city
,
state
, and zipCode
. However, you are considering
changing the implementation of your persistence strategy, so you do not
want client applications to be bound to the Customer
API
directly.
You can isolate yourself by having your persistence tier expose a DataProvider wrapping this bean. The back end code would do something like this:
Customer customer = ...; return new ObjectDataProvider(customer);
Client code can then access the individual data elements inside by using a FieldKey to identify the required element:
DataProvider custDP = ...; // Retrieve and display customer name System.out.println("Customer name is " + custDP.getValue(custDP.getFieldKey("name"))); // Change zip code to "99999" custDP.setValue(custDP.getFieldKey("zipCode"), "99999");
Now, the developers of your persistence tier are free to use different
technologies to represent data in memory (for instance, by storing the
available values in a Map
, or pointing at the current row of a
ResultSet
. As long as the persistence tier wraps the data in
an appropriate DataProvider
instance, client applications accessing the data are unaffected.
When you need access to multiple "rows" of data (each with the same set of underlying data elements), TableDataProvider provides both random and cursor-based access to the data for each row.
TableDataProvider custsDP = ...; // Retrieve the id of the last customer using random access int size = custsDP.getSize(); RowKey[] rows = custsDP.getRowKeys(size, null); System.out.println("Last customer id is " + custsDP.getValue(custsDP.getFieldKey("id"), rows[size - 1])); // Random access // List the names of each customer, using cursor based access do { System.out.println("Customer name is " + custsDP.getValue(custsDP.getFieldKey("name"))); // Cursor based access } while (custsDP.cursorNext()); // Directly access the third customer's city custsDP.setCursorRow(rows[2]); // The third RowKey object System.out.println("Third customer's city is " + custsDP.getValue(custsDP.getFieldKey("city"))); // Cursor based access
The DataProvider APIs include a JavaServer Faces PropertyResolver
that allows DataProvider
instances to participate in value binding and method binding expressions.
Presume that you have the following public methods in a managed bean registered
under the name backing
(in any desired scope):
public DataProvider getCustomer(); public TableDataProvider getCustomers();
Business logic in your application is responsible for initializing these
properties with appropriate DataProvider instances that wrap the underlying
model tier data. For singleton data elements, the syntax of a value binding
expression will look exactly like the expression you would use if you were
accessing a Customer
bean directly. For example:
<h:outputText ... value="#{backing.customer.value['id']}" .../> <h:inputText id="name" value="#{backing.customer.value['name']}" .../>
If you bind to an
TableDataProvider
instead, you will be using cursor-based access to select data elements
associated with the row selected by the cursorRow
property of the
TableDataProvider. This means that your application logic can update the
cursor to navigate through the rows, without having to adjust the bindings
on each component.
<h:outputText ... value="#{backing.customers.value['id']}" .../> <h:inputText id="name" value="#{backing.customers.value['name']}" .../>
It is also feasible to create JavaServer Faces components that include
properties of type DataProvider
. For example, consider a
version of the standard UISelectMany
component that provided
a items
property (of type
TableDataProvider
) to specify the set of available options.
The component would document that it expects this provider to supply
data elements named label
and value
for use in
creating the markup to be rendered.
The items
property, as with any other component property,
can be initialized either from Java code or as a JSP tag attribute. In the
latter case, you would typically use a value binding expression pointing to
a managed bean, or a property of such a bean. For example, assume you have
a managed bean registered under the name domains
, with a property
of type TableDataProvider
named categories
that
defines the list of music categories the user of your shopping site might
indicate that he or she prefers. The component might be initialized in a
JSP page like this:
<custom:SelectManyList ... items="#{domains.categories}" .../>
|
||||||||||
PREV NEXT | FRAMES NO FRAMES |