Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

How to Implement a Web Cache for Your BrowserField2 Application

by BlackBerry Development Advisor (Retired) on ‎03-08-2011 01:35 PM - edited on ‎03-08-2011 01:46 PM by Community Manager (Retired) (6,444 Views)

 

 

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!


 


 

Goal

 

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

 

The BrowserField2 API, introduced with the release of BlackBerry Device Software 5.0, allows BlackBerry developers to embed Web content into their Java applications. As a result, developers are able to quickly build BlackBerry applications that easily integrate with legacy back-end web-based systems. In addition, BrowserField2 applications running on OS 6.0 benefit from the high-quality and top-notch performance of the BlackBerry Webkit rendering and Javascript engines.

 

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.

 

 

BrowserField2 and the ProtocolController

 

 

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 ProtocolController handles 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 classes CacheProtocolController, CacheManagerImpl and CacheItem as depicted in Figure 2. There is also the application entry point class BF2CacheSampleApp that can be found in the attached source code.

 

 

bf2_cache.PNG

 

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 the CacheManager 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 the CacheManager creates a cache entry for that resource.

 

 

public class CacheProtocolController extends ProtocolController{

// The BrowserField instance
private BrowserField browserField;

// CacheManager will take care of cached resources
private CacheManager cacheManager;

public CacheProtocolController(BrowserField browserField) {
super(browserField);
this.browserField = browserField;
}

private CacheManager getCacheManager() {
if ( cacheManager == null ) {
cacheManager = new CacheManagerImpl();
}
return cacheManager;
}

/**
* Handle navigation requests (e.g., link clicks)
*/
public void handleNavigationRequest(BrowserFieldRequest request)
throws Exception {
InputConnection ic = handleResourceRequest(request);
browserField.displayContent(ic, request.getURL());
}

/**
* Handle resource request (e.g., images, external
* css/javascript resources)
*/
public InputConnection handleResourceRequest(BrowserFieldRequest request)
throws Exception {

// if requested resource is cacheable
// (e.g., an "http" resource), use the cache
if (getCacheManager() != null &&
getCacheManager().isRequestCacheable(request)
) {
InputConnection ic = null;
// if requested resource is cached, retrieve it from cache
if (getCacheManager().hasCache(request.getURL()) &&
!getCacheManager().hasCacheExpired(request.getURL())
) {
ic = getCacheManager().getCache(request.getURL());
}
// if requested resource is not cached yet, cache it
else {
ic = super.handleResourceRequest(request);
if (ic instanceof HttpConnection) {
HttpConnection response = (HttpConnection) ic;
if (getCacheManager().isResponseCacheable(response)) {
ic = getCacheManager().createCache(request.getURL(),
response);
}
}
}
return ic;
}
// if requested resource is not cacheable make a standard request
return super.handleResourceRequest(request);
}

}

 

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!

 


load MKS page only when "arrow" is clicked. I was trying to copy/paste text but was accidentally opening the MKS page.

Rank tasks by priority?

Expand/collapse tasks per person

Contributors