Implementing Background Downloading on the Client Side

simultaneously active. Since most of them pursue individual tasks that can be impeded by external factors for example, network congestion can cause some of the threads to slow down, the fact that the threads are mostly independent means were taking full adva ntage of our available resources. Viewed this way, iterators arent just a convenient way to deliver partial responses to an impatient end user. Theyre also a way to write more efficient code. By breaking the response down to a set of small, individually handled chunks, weve come close to maximizing system throughput.

21.3.2 Implementing Background Downloading on the Client Side

The architecture for implementing background downloading isnt all that different from the architecture for polling. In both cases, the same general thing happens: the background thread on the client side repeatedly makes the same request of a server until the return value from the request indicates a stop condition. Assume our servers have the following two interfaces: public interface SalesHelper extends Remote { public QueryResponse getAllAccountsWithBalanceOverMoney amount throws RemoteException; } public interface AccountIterator extends Remote { public int getNumberOfRemainingAccounts throws RemoteException; public AccountList getNextint numberToFetch throws RemoteException; } This requires two value objects: AccountList and QueryResponse . AccountList encapsulates a set of accounts; it is the basic unit of information sent from the server to the client: public class AccountList implements Serializable { public int numberOfAccountsRequested; public int numberOfAccountsReturned; public boolean areThereMoreAccountsToFetch; public ArrayList accounts; } QueryResponse extends AccountList and adds a single attribute: public class QueryResponse extends AccountList { public AccountIterator accountIterator; } Given all of this, the clients implementation of background downloading looks something like the following: public abstract class AskServer implements Runnable { private AccountIterator _accountIterator; private String _salesHelperName; private Money _threshhold; private AccountList _currentAccounts; private int _fetchSize; protected abstract void handleResponseSetArrayList nextSetOfResponses; public AskServerString salesHelperName, Money threshhold, int fetchSize { _salesHelperName = salesHelperName; _threshhold = threshhold; _fetchSize = fetchSize; } public void performQuery { try { makeInitialRequest ; } catch Exception e { System.out.printlnError in connecting to server; e.printStackTrace ; return; } new Threadthis.start ; } public void run { while_currentAccounts.areThereMoreAccountsToFetch { try { _currentAccounts = _accountIterator.getNext_fetchSize; handleResponseSet_currentAccounts.accounts; } catch RemoteException e { insert exception handling here its fairly customary to break the loop at this point } } } private void makeInitialRequest throws Exception { SalesHelper salesHelper = SalesHelper Naming.lookup_salesHelperName; QueryResponse queryResponse = salesHelper.getAllAccountsWithBalanceOver_threshhold; _currentAccounts = queryResponse; _accountIterator = queryResponse.accountIterator; handleResponseSet_currentAccounts.accounts; } } This does exactly what youd expect: it establishes a connection in the main method and then delegates the background downloading to a secondary thread that it creates. In more complex systems, or for server-to-server communication, this secondary thread would probably be obtained from a pool of threads see Chapt er 12 . However, for a typical client, creating threads on the fly doesnt lead to a lot of overhead. There is an interesting point here, though. We didnt implement any exception handling inside the background-downloading loop. This code is rather tricky and application-specific. Ideally, wed like to detect what causes the error Was it a transient network failure? Did the server crash entirely? Was there a null pointer exception in that particular block of data? and work around it. However, without knowing more about the server, its hard to say what the correct behavior should be.

21.4 Generalizing from These Examples

The point of this chapter is simple: when your architecture goes beyond request-response cycles, you need to think carefully about what exactly your client is doing. Many times the boundary between clients and servers gets a little fuzzy, and the client starts responding to remote method invocations. More frequently, the client becomes a fairly complex application with a lot of threads performing secondary interactions with the server. The three basic techniques presented in this chapter™polling, callbacks, and interator-based data acquisition™go a long way towards solving a wide variety of client-server interaction design problems.

Chapter 22. HTTP Tunneling

One of the most pervasive problems in client-server computing is that servers are frequently inaccessible to clients. Sometimes this is because the server is down. More often, however, its because a firewall has been erected between the computer running the client and the computer running the server. In this chapter, well cover one widely used method, known as HTTP tunneling, that an RMI application can use to circumvent firewalls and enable your application to function. Before the Internet, corporate networks were isolated. Large companies frequently had multiple- computer networks, and computers on one network were often incapable of sending any information to computers on a different network. Now that the Internet has become a global network, the situation is quite different. Most computers are, at least occasionally, connected to the Internet. This situation, while making things like the World Wide Web possible, makes life very difficult for systems administrators. They are called upon to build robust networks that are fully connected to the Internet so companies can take full advantage of what it has to offer while simultaneously preventing unauthorized users from accessing corporate information.

22.1 Firewalls

This dilemma is frequently solved by using a firewall. A firewall is a combination of software and hardware that separates two logically distinct networks. If the firewall is removed, the two networks are no longer connected to each other. Because all traffic between the two networks must flow through the firewall, the firewall can screen all the packets sent between the two networks and throw away any packets that violate the firewalls security policy. For example, a company might place a firewall between its internal network and the Internet, and establish a policy such as: