Code Sample 4: A Page-By-Page Iterator pattern that is returned to the client.
Now let us see how the data access object will have to be modified a little to make use of the Page-by-Page Iterator pattern while returning the list of services:
// all required imports
public class CatalogDataAccessObject {
/*
the code for other methods, except the getServiceNames(), here is the same as in Code Sample 2. We will see the steps that will be done in the getServiceNames() method instead of going into detailed code. The changes will allow the client using Fast Lane Reader pattern and the Page-By-Page Iterator pattern to get the list of services of required size; The arguments are used while deciding how many objects to return as part of the Collection;
*/
public PageByPageIteratorImpl getServiceNames(int startIndex, int size)
{
// get the total count of the number of service into variable “total”;
// access the database and get the collection of service names in
// “retObjs”;
// the collection obtained will be of requested size only starting from
// the index specified;
// return the collection of service names as part of the Page-by-Page
// Iterator
return(new PageByPageInteratorImpl(startIndex, size, total, retObjs));
}
// other method definitions as required
}
Code Sample 5: A Data Access Object that encapsulates all types
of access to the Catalog and returns only the requested number of
objects in a PageByPageIterator
And the servlet client that gets and displays the list would look like:
// All required imports
public class DisplayServices extends HttpServlet {
private CatalogDataAccessObject dao;
// other declarations
public void init() {
CatalogDataAccessObject dao = new CatalogDataAccessObject();
// all other inits required
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
// other processing, if any
Integer startIndex = new Integer(request.getParameter(“StartIndex”));
Integer listSize = new Integer(request.getParameter(“ListSize”));
PageByPageIteratorImpl list = dao.getServiceNames(startIndex.intValue(),
listSize.intValue());
Collection objs = list.getCollection();
// Now the list received is of requested size only
// iterate thro the list and display the service names received
// do other processing as required
}
// other method definitions
}
Code Sample 6: Now the Servlet uses the Fast Lane Reader pattern along with data access objects to get read-only data; It also uses the Page-By-Page Iterator pattern to limit the number of objects returned to what was requested. In this sample, it is assumed that an HTML page set embedded parameters “StartIndex”, “ListSize” and then invoked this servlet on user action
Points To Note
Here is a set of points to be noted while considering to use this pattern:
* The client can specify the list size. So clients control the amount of data they want to receive. This gives them lots of flexibility.
* While this pattern provides efficient access to large serverside lists, the number of server hits might increase a bit as not all data is transferred at once.
* The iterator does not keep its own copy of the list being traversed. As a consequence, insertions or removals will interfere with the traversal. But this is may not be a problem if the client browses static data collections like list of services or search results.
* Network bandwidth is not wasted by transmitting unused data. This has to be weighed against the potential increase in number of server hits while deciding to use this pattern or not.
Value Object
Problem Domain
So far we have seen two patterns that could improve the efficiency and performance of our J2EE application when large amounts of objects are getting transferred between clients and server. All will be well if the actual objects that are being transferred were objects without any attributes. But more often than not, the data being transferred are collection of objects which have their own identity. In the financial services sample application that we have been discussing, the list of services being returned from server are actually collection of objects. Each of this service will have its own attributes like Service Name, Service Cost, Service Description, Terms, Conditions etc. And, more often than not, a client requesting the list of services will also want to know about all the above mentioned information that belong to a service. Given these circumstances, when do we transfer these finer details. It is definitely not efficient for the client to get a list of service names and then contact the server for getting the finer details of each service name received. That would entail lots of remote calls and additional stress on the network.
Suggested Pattern
While coming up with a common solution to this scenario, we have to keep in mind that:
* the probability of the client asking for the finer details of a service is
much more than the client asking for the complete list of services.
* all the attributes associated with the requested object will most probably be in the same database table and hence can be obtained in the same SQL call that gets the list of service names.
The suggested solution would be that we transfer coarse grained data (in this example, the list of service names along with all its attributes) rather than transferring fine grained data (like requiring the client to make separate remote calls for each of the attrbitue like service name, cost, terms etc). We can do this by using the Value Object pattern. Use of this pattern in our sample case, will result in the ServiceDataAccessObject aggregating each service and all its attributes into one instance of a Value Object , say ServiceInformation. Then a collection of these Value Objects are serialized and sent over the wire to the client where it will be deserialized and used.
To see some code example, let us first define the ServiceInformation Value Object:
// all imports required
public class ServiceInformation implements java.io.Serializable {
private String serviceName;
private double serviceCost;
private String[] serviceTerms;
// other attributes of a service
public ServiceInformation(String name, double cost, String[] terms) {
serviceName = name;
serviceCost = cost;
serviceTerms = terms;
}
public String getName() {
return(serviceName);
}
public double getCost() {
return(serviceCost);
}
public String[] getTerms() {
return(serviceTerms);
}
// similar accessor methods for other attributes
}
Mr. Vijay S. Ramachandran is the author of this article.