![]() |
|
|
![]()
|
Value List HandlerContextThe client requires a list of items from the service for presentation. The number of items in the list is unknown and can be quite large in many instances. ProblemMost J2EE applications have a search and query requirement to search
and list certain data. In some cases, such a search and query operation
could yield results that can be quite large. It is impractical to return
the full result set when the client's requirements are to traverse the
results, rather than process the complete set. Typically, a client uses
the results of a query for read-only purposes, such as displaying the
result list. Often, the client views only the first few matching records,
and then may discard the remaining records and attempt a new query. The
search activity often does not involve an immediate transaction on the
matching objects. The practice of getting a list of values represented
in entity beans by calling an There are consequences associated with using EJB finder methods that
result in large results sets. Every container implementation has a certain
amount of finder method overhead for creating a collection of EJBObject
references. Finder method behavior performance varies, depending on a
vendor's container implementation. According to the EJB specification,
a container may invoke Forces
SolutionUse a Value List Handler to control the search, cache the results, and provide the results to the client in a result set whose size and traversal meets the client's requirements. This pattern creates a ValueListHandler to control query execution functionality and results caching. The ValueListHandler directly accesses a DAO that can execute the required query. The ValueListHandler stores the results obtained from the DAO as a collection of Transfer Objects. The client requests the ValueListHandler to provide the query results as needed. The ValueListHandler implements an Iterator pattern [GoF] to provide the solution. StructureThe class diagram in Figure 8.29 illustrates the Value List Handler pattern.
Participants and CollaborationsThe sequence diagram in Figure 8.30 shows the interactions for the Value List Handler.
ValueListIteratorThis interface may provide iteration facility with the following example methods:
Depending on the need, other convenience methods can be included to be part of the ValueListIterator interface. ValueListHandlerThis is a list handler object that implements the ValueListIterator interface. The ValueListHandler executes the required query when requested by the client. The ValueListHandler obtains the query results, which it manages in a privately held collection represented by the ValueList object. The ValueListHandler creates and manipulates the ValueList collection. When the client requests the results, the ValueListHandler obtains the Transfer Objects from the cached ValueList, creates a new collection of Transfer Objects, serializes the collection, and sends it back to the client. The ValueListHandler also tracks the current index and size of the list. DataAccessObjectThe ValueListHandler can make use of a DataAccessObject to keep separate the implementation of the database access. The DataAccessObject provides a simple API to access the database (or any other persistent store), execute the query, and retrieve the results. ValueListThe ValueList is a collection (a list) that holds the results of the query. The results are stored as Transfer Objects. If the query fails to return any matching results, then this list is empty. The ValueListHandler session bean caches ValueList to avoid repeated, unnecessary execution of the query. TransferObjectThe TransferObject represents an object view of the individual record from the query's results. It is an immutable serializable object that provides a placeholder for the data attributes of each record. StrategiesJava Object StrategyThe ValueListHandler can be implemented as an arbitrary Java object. In this case, the ValueListHandler can be used by any client that needs the listing functionality. For applications that do not use enterprise beans, this strategy is useful. For example, simpler applications may be built using servlets, JSPs, Business Delegates, and DAOs. In this scenario, the Business Delegates can use a ValueListHandler implemented as a Java object to obtain list of values. Stateful Session Bean StrategyWhen an application uses enterprise beans in the business tier, it may be preferable to implement a session bean that uses the ValueListHandler. In this case, the session bean simply fronts an instance of a ValueListHandler. Thus, the session bean may be implemented as a stateful session bean to hold on to the list handler as its state, and thus may simply act as a facade (see "Session Facade" on page 291) or as a proxy. Consequences
Sample CodeImplementing the Value List Handler as a Java ObjectConsider an example where a list of Project business objects are to be
retrieved and displayed. The Value List Handler pattern can be applied
in this case. The sample code for this implementation is listed in Example
8.29 as ProjectListHandler, which is responsible to provide the list of
Projects. This class extends the Example 8.29 Implementing Value List Handler Pattern package corepatterns.apps.psa.handlers; import java.util.*; import corepatterns.apps.psa.dao.*; import corepatterns.apps.psa.util.*; import corepatterns.apps.psa.core.*; public class ProjectListHandler extends ValueListHandler { private ProjectDAO dao = null; // use ProjectTO as a template to determine // search criteria private ProjectTO projectCriteria = null; // Client creates a ProjectTO instance, sets the // values to use for search criteria and passes // the ProjectTO instance as projectCriteria // to the constructor and to setCriteria() method public ProjectListHandler(ProjectTO projectCriteria) throws ProjectException, ListHandlerException { try { this.projectCriteria = projectCriteria; this.dao = PSADAOFactory.getProjectDAO(); executeSearch(); } catch (Exception e) { // Handle exception, throw ListHandlerException } } public void setCriteria(ProjectTO projectCriteria) { this.projectCriteria = projectCriteria; } // executes search. Client can invoke this // provided that the search criteria has been // properly set. Used to perform search to refresh // the list with the latest data. public void executeSearch() throws ListHandlerException { try { if (projectCriteria == null) { throw new ListHandlerException( "Project Criteria required..."); } List resultsList = dao.executeSelect(projectCriteria); setList(resultsList); } catch (Exception e) { // Handle exception, throw ListHandlerException } } } The Value List Handler is a generic iterator class that provides the iteration functionality. Example 8.30 Implementing Generic ValueListHandler Class package corepatterns.apps.psa.util; import java.util.*; public class ValueListHandler implements ValueListIterator { protected List list; protected ListIterator listIterator; public ValueListHandler() { } protected void setList(List list) throws IteratorException { this.list = list; if(list != null) listIterator = list.listIterator(); else throw new IteratorException("List empty"); } public Collection getList(){ return list; } public int getSize() throws IteratorException{ int size = 0; if (list != null) size = list.size(); else throw new IteratorException(...); //No Data return size; } public Object getCurrentElement() throws IteratorException { Object obj = null; // Will not advance iterator if (list != null) { int currIndex = listIterator.nextIndex(); obj = list.get(currIndex); } else throw new IteratorException(...); return obj; } public List getPreviousElements(int count) throws IteratorException { int i = 0; Object object = null; LinkedList list = new LinkedList(); if (listIterator != null) { while (listIterator.hasPrevious() && (i < count)){ object = listIterator.previous(); list.add(object); i++; } }// end if else throw new IteratorException(...); // No data return list; } public List getNextElements(int count) throws IteratorException { int i = 0; Object object = null; LinkedList list = new LinkedList(); if(listIterator != null){ while( listIterator.hasNext() && (i < count) ){ object = listIterator.next(); list.add(object); i++; } } / / end if else throw new IteratorException(...); // No data return list; } public void resetIndex() throws IteratorException{ if(listIterator != null){ listIterator = list.ListIterator(); } else throw new IteratorException(...); // No data } ... } package corepatterns.apps.psa.dao; public class ProjectDAO { final private String tableName = "PROJECT"; // select statement uses fields final private String fields = "project_id, name," + "project_manager_id, start_date, end_date, " + " started, completed, accepted, acceptedDate," + " customer_id, description, status"; // the methods relevant to the ValueListHandler // are shown here. // See Data Access Object pattern for other details. ... private List executeSelect(ProjectTO projCriteria) throws SQLException { Statement stmt= null; List list = null; Connection con = getConnection(); StringBuffer selectStatement = new StringBuffer(); selectStatement.append("SELECT "+ fields + " FROM " + tableName + "where 1=1"); // append additional conditions to where clause // depending on the values specified in // projCriteria if (projCriteria.projectId != null) { selectStatement.append (" AND PROJECT_ID = '" + projCriteria.projectId + "'"); } // check and add other fields to where clause ... try { stmt = con.prepareStatement(selectStatement); stmt.setString(1, resourceID); ResultSet rs = stmt.executeQuery(); list = prepareResult(rs); stmt.close(); } finally { con.close(); } return list; } private List prepareResult(ResultSet rs) throws SQLException { ArrayList list = new ArrayList(); while(rs.next()) { int i = 1; ProjectTO proj = new ProjectTO(rs.getString(i++)); proj.projectName = rs.getString(i++); proj.managerId = rs.getString(i++); proj.startDate = rs.getDate(i++); proj.endDate = rs.getDate(i++); proj.started = rs.getBoolean(i++); proj.completed = rs.getBoolean(i++); proj.accepted = rs.getBoolean(i++); proj.acceptedDate = rs.getDate(i++); proj.customerId = rs.getString(i++); proj.projectDescription = rs.getString(i++); proj.projectStatus = rs.getString(i++); list.add(proj); } return list; } ... } package corepatterns.apps.psa.util; import java.util.List; public interface ValueListIterator { public int getSize() throws IteratorException; public Object getCurrentElement() throws IteratorException; public List getPreviousElements(int count) throws IteratorException; public List getNextElements(int count) throws IteratorException; public void resetIndex() throws IteratorException; // other common methods as required ... } Related Patterns
|
|||||||||||||||||||||||
© 2001, Core J2EE Patterns, All Rights Reserved. |