Introduction
Nearly six months ago, I got the chance to work on my company�s first ever Smart Client application. Needless to say, being a very successful web development company, it was looked at as a high risk - high reward project. If we made it work, we�d open up a whole new market; if we did not, it would be back to the old game plan (at least for a while).
So we played it safe, and stuck to the recommended application blocks, most stable releases of the development tools etc. Surprisingly enough, we managed to put together our first prototype in record time, using .NET 1.1, the 2005 and 2004 releases of MS DAAB (Data Access Application Block) and SOAB (Smart-Client Offline Application Block), and WSE 2.0 SP 3.
Well now, we completed migrating our code to .NET 2.0, the new DAAB, and to WSE 3.0. But, where is the new Offline Application Block? While working on the last 2004 release of it, we found that it didn�t really deliver all the functionality we required. And we hoped that the next release would have included some of it. Well I, for one, got tired of waiting�
SOAB on Db4O
Now, if you take Microsoft�s Offline Application Block, it serializes the cache objects and command queue items on to its database. Once you do that, you lose lot of flexibility. Of course, in the RDBMS world, there�s hardly any alternative. In the MSDE world, there is no way to design a Cache database or a Queue database to hold arbitrary application specific objects. With SQL 2005, I�d assume you could use XML columns and along with XQuery to achieve this. But then again, there is a much better way.
Last year, while researching for my final year project, I took a look at Db4O. Db4O is an open-source, object database for .NET/MONO and Java. I was just playing with the idea of using the object database for the cache/queue database, and it didn�t took five minutes before the advantages became evident. The downside is that the free Db4O is distributed under GPL, and if you need to use it in a commercial application, you�d need to get a commercial license from the developers.
Benefits of the new SOAB
- Simplified deployment.
No SQL Servers to deploy, no database scripts to run, no logins to create; simply copy the application where you want and run it. The cache and queue databases will be created on the fly the very first time it�s needed. It�s that simple! This means it could deliver something that the SQL Server backed smart-clients cannot deliver: ability to run from a tiny USB flash drive.
- Inter-dependant queue elements.
Imagine a smart-client application used for cataloging books. The central server maintains a catalog of books and authors. For a book to be cataloged, its author must exist in the database. (Exactly how such an application would be useful is of no concern to us here :). The smart client downloads the list of authors from the server when it goes online. A problem arises when a book along with its author has to be created offline. When an author is created offline, a �Create Author� request is queued in the command queue. Likewise, when a book is created, a �Create Book� request is queued. The new SOAB provides a mechanism by which the programmer of the Smart-Client could specify that a �Create Book� request should be executed (transferred to the web-service) only once its related author object has been successfully put on the central database.
- All the glory of Db4O.
Db4O is a powerful object database, with advanced functionality such as native query, SODA query, etc. While the SOAB.Data.Database
class attempts to wrap most of the interactions with the underlying Db4O Object Container, it is still accessible to the brave-hearted. This opens up a number of additional possibilities such as modifying/deleting individual items from the queue, querying for specific items in the cache or the queue, determining which items are to be modified when the queued elements are executed etc.
- Tiny code base, built on .NET 2.0.
The application block has only about fifteen classes and interfaces in total: out of which only six you�d need to concern yourselves with. You�d probably take less than two hours to identify how to harness the full potential of the SOAB. The new SOAB uses generics, and the new event-based asynchronous invocation methods, breaking away from the old way of doing things.
Working with the SOAB
Working with the SOAB is almost effortless; simply follow these few steps:
- In your Smart Client application, add a class derived from
SOAB.ServiceAgent
. In the sample application, I have made the derived class (ServiceClient
) a singleton. While this is not always required, it might be a good idea to do so.
- Create a
ServiceContext
class and keep it around as it can be used for all service requests. Since, the ServiceClient
is a singleton, I�ve made the ServiceContext
instance, one of its fields. The ServiceContext
class is basically a builder for your web-service proxy class. Make sure that you pass the fully qualified class name of the proxy to its constructor.
- When you need to invoke a web method, create and populate a
ServiceRequest
object and enqueue it using the QueueManager.Instance.Enqueue(�)
method. To populate the ServiceRequest
, assign:
- The
ServiceContext
instance to the ServiceRequest.ServiceContext
property.
- The name of the web-method you are invoking to
ServiceRequest.RemoteMethodName
.
- The argument to the web-method to
ServiceRequest.Payload
.
- The name of a method accepting a
ServiceResponse
argument belonging to the ServiceAgent
derived class to ServiceRequest.CallbackMethodName
.
Remember that you should have authored your web methods to accept only a single parameter. While it was possible to author the Payload
property as an array, allowing multiple parameters on web methods, it would have been less efficient and resulted in dirty code on the Smart Client end.
The method specified in the CallbackMethodName
property is invoked once the ServiceRequest
has been executed. You should use the properties in the ServiceResponse
object passed on to the method to determine whether the request was successful, cancelled, or whether it generated an exception.
If you have any object types that might depend on other objects (such as Book
that depends on Author
), you should implement the ICacheDependant
interface on the dependant class. Provide the dependency resolution logic in the IsResolved
property-getter and return true
if the object is ready to be transferred to the web method.
The demo application
I have put together a pretty nifty application that demonstrates some of the key features of the SOAB.
- Caching and command queuing.
- Inter-dependant service-requests.
- Viewing of the command queue.
For testing purposes, I have used a pseudo connection detection strategy that mimics the online and offline state based on a Boolean field.
The code packages do not include the required Db4O DLL. This is due to the fact that I was unclear about the licensing issues related to distributing the library along side my non-GPL source code. You could of course get Db4O for free from www.db4o.com. But, to use the library in a commercial application, do obtain a commercial license. You may use my source code, freely under the Apache License 2.0, giving credit where it�s due.
Conclusion
For more information about my Offline Application Block, please read this blog.