So, loading pages on your BrowserField2 application is taking quite some time and yet your app is repeatedly loading the same pages over and over again spending network bandwidth and providing a poor performance experience to users?
You’ve been thinking of implementing a web cache but has no idea how to extend the BrowserField2 (a.k.a. BF2) API for that purpose?
This article is definitely for you!
This article discusses how the BrowserField2 API (BlackBerry® Device Software 5.0 and later) can be properly extended to implement a simple web cache mechanism that will speed up the loading of pages and resources in a BF2 application significantly reducing bandwidth usage, server load, and ultimately improving the user experience. The code provided (please check the attachments) should serve as a basis for developers to build their own professional caching mechanism tailored to their particular needs.
The term “web cache” (from now on simply referred to as “cache“) will be used throughout this article to refer to a cache of HTTP resources (e.g., a web page, an image, a css file) in which HTTP headers and page content (sequence of bytes) are store together in a cache entry and later used to quickly reload HTTP resources. In terms of data persistency the source code provided implements a “short-term cache“, i.e., a cache that will not persist data after a device boot. For further information on web caches and related terminology please refer to the corresponding Wikipedia article: http://en.wikipedia.org/wiki/Web_cache.
BrowserField2 API and the ProtocolController
Despite the richness in functionality and ease-of-development provided by the BrowserField2 API, a caching mechanism for loading webpages does not come standard. That is, requesting the same web page twice will require establishing different connections with the web server to retrieve the page’s content. The good news is that a caching mechanism can be implemented straighforwardly by extending the BrowserField2 API, in particular one of its core components called the ProtocolController as we cover next.
Figure 1: The Role of the ProtocolController in the BrowserField2 API
(Figure extracted from BlackBerry DEVCON 2010 – DEV49 technical session)
The ProtocolController, depicted in Figure 1, reprsents the default implementation of the BrowserFieldController abstract component. The ProtocolControllerhandles navigation (e.g., a link was clicked on your page) and resource (e.g., an image or a CSS file needs to be loaded in your page) requests through a variety of protocols (e.g., http, https, local, file) and is responsible for providing a valid connection to a remote resource and, in some cases, for properly displaying the contents of a requested page on the screen.
Overriding the ProtocolController allows developers to intercept all kinds of page and resource requests and thus to customize the standard behavior. For instance, an application might be interested in checking the credentials of a user before giving her access to a particular page or resource. In fact, the BlackBerry® WebWorks™ application technology applies this very same strategy.
In particular, extending the standard controller is ideal for implementing the caching mechanism cover in this article since all requests are made via the controller. As shown in Figure 1, developers can either extend the abstract BrowserFieldController or its default implementation the ProtocolController. This article will use the latter approach as the ProtocolController provides convenient functionality that can be readily reused.
Creating a CacheProtocolController
Figure 2 depicts the four components created to implement the BF2 caching system discussed in this article, i.e., the CacheManager interface and classesCacheProtocolController, CacheManagerImpl and CacheItem as depicted in Figure 2. There is also the application entry point class BF2CacheSampleAppthat can be found in the attached source code.
Figure 2: Extending the ProtocolController to create a web cache
The CacheProtocolController class extends the default controller to link page requests to the cache component. The cache controller checks if a given page/resource request is cacheable and if so it either retrieves the resource from the cache (cache hit) of downloads the resource and stores it in the cache for later use (cache miss).
The code for the CacheProtocolController is show below. Methods handleNavigationRequest() and handleResourceRequest() override the default controller. Method handleNavigationRequest() reuses method handleResourceRequest() to retrieve a connection to the requested resource and afterwards requests the BrowserField to render the content via a call to method displayContent(). Method handleResourceRequest() first checks if the requested resource can be cacheable (using the CacheManager object). If the resource is not cacheable, the CacheProtocolController forwards the call to the standard controller via super.handleResourceRequest(). If the resource is cacheable and is already in the cache and not expired an InputConnection is created by theCacheManager and returned. If the resource is not in the cache, the standard controller’s functionality is called to retrieve a connection to the resource and theCacheManager creates a cache entry for that resource.
Note that the algorithm implemented in method handleResourceRequest() relies heavily on the CacheManager interface. Developers reading this article might want to create their own implementation of the that interface (or extend the class CacheManagerImpl) to customize the cache functionality discussed in this article. The reader is encouraged to have a careful look at the source code provided especially class CacheManagerImpl that provides a basic caching implementation used by the CacheProtocolController.
It is out of the scope of this article to discuss the implementatoin details of class CacheManagerImpl. Yet understanding this class by looking into the source code should be pretty straightforward.
Attaching the new CacheProtocolController to the Sample Application
The last step towards enabling caching on your BF2 application is to attached the new CacheProtocolController component to the BrowserField object. In the sample application provided (see class BF2CacheSampleApp in the attachments) the new controller is attached to the BrowserField as shown in the code below:
browserField = new BrowserField(); browserField.getConfig().setProperty(BrowserFieldConfig.CONTROLLER, new CacheProtocolController(browserField));
The reader is strongly encouraged to check the slides of the DEV 49 session entitled “Customizing BrowserField2 Advanced Components” presented at the DEVCON 2010.The slides cover several other extensible points of the BrowserField2 API and can be found in the BlackBerry Developer Zone portal.
Have fun with your BrowserField2 Web Cache!