Building an offline application in IBM Lotus Expeditor

IBM Lotus Expeditor is a compelling platform for building solutions for desktops and devices. Learn about three architectural patterns for offline applications and approaches for synchronizing data between client and server. To illustrate an offline application, a sample is provided and explained.

Share:

Hunter Medney, Senior certified software specialist, IBM, Software Group

Hunter Medney is committed to maximizing customer return on investment in IBM Lotus technology. He is a senior certified software specialist with IBM Software Services for Lotus specializing in the IBM Workplace product family. He has extensive background in IBM Lotus Notes/Domino and has transitioned to J2EE and the game-changing IBM Workplace Client Technology. He helped lay the groundwork for application development in this space by creating public samples, building an internal community of developers, presenting at conferences, writing articles, and contributing to developerWorks.



08 May 2007

IBM Lotus Expeditor offers a comprehensive set of local APIs and services for building enterprise business applications on the desktop. These include a local relational database, Web services stack, assured and secure messaging, encrypted credential store, synchronization framework with scheduler to periodically synchronize client data with the server, and many others.

Lotus Expeditor is an exciting new middleware platform for building applications targeted for desktops and devices. It provides a comprehensive environment in which applications of different types and different sources can run together seamlessly. These applications can appear together on the same page, can extend each other, and can exchange data. Lotus Expeditor can be thought of as a client-side portal, where components from different providers are aggregated locally.

Software stack

As shown in figure 1, Lotus Expeditor is a layered software stack built on Java and Eclipse. IBM adds a number of value-add services for real-world business applications on top of Java and Eclipse.

Figure 1. Lotus Expeditor desktop software stack
Lotus Expeditor desktop software stack

The default Java Runtime Environment (JRE) is jclDesktop, an IBM-optimized subset of J2SE 1.4 that offers a smaller footprint and faster class loading. The desktop runtime can be optionally replaced with a full IBM J2SE 1.5 JRE. Refer to the Device Runtime Environment section of the Lotus Expeditor InfoCenter, included in the Resources section of this article.

Eclipse 3.2 provides the core runtime, presentation framework, extension framework, help subsystem, and other foundation services. Core to Eclipse 3.2 is OSGi technology, a Java-based framework for multiple applications to run in a single Java Virtual Machine (JVM). With OSGi technology, each application is a bundle. OSGi technology defines how bundles are packaged, how bundle dependencies are defined, which package bundles are exposed to other bundles, and other bundle metadata. Lotus Expeditor can be thought of as a collection of bundles on a thin OSGi runtime.

On top of Eclipse, Lotus Expeditor delivers a comprehensive set of value-add, standards-based services for building enterprise business applications while maximizing reuse of existing server-side components such as J2EE Web applications.

These value-add services include:

  • Local relational databases (IBM DB2 Everyplace and IBM Cloudscape)
  • Relational database synchronization
  • Synchronization framework
  • Messaging with IBM WebSphere MQ Everyplace
  • Web services consumer stacks
  • Web services provider stack
  • Local J2EE Web container
  • Local JSR-168 portlet container
  • Custom personalities
  • Accounts framework with secure credential store
  • Online/offline modes
  • Network awareness
  • Consolidated logging
  • Styled UI widgets
  • Bundle intercommunication using Property Broker
  • Server-managed application deployment
  • Server-managed settings
  • Embedded Transaction Container (EJB subset)
  • JNDI services

Applications are then built on top of this stack and can use Java, Eclipse, and Lotus Expeditor APIs and services.


Client/server data access architectures

Business applications deal with data. Examples of data include customers, orders, nurses, books, insurance quotes, inventory, and so on. A master version of this data is normally maintained on a centralized server in a relational database. Business applications designed to run on desktops and devices (clients) can access and modify business data in a variety of ways, and modified data must then be synchronized back to the master repository. This article explores data access architectures for client/server applications.

Client/server data access architectures can be classified as always offline, always online, or mixed. Each of these data access patterns dictates a different persistent store design for the client-side user interface.

Each pattern assumes a server data store and a local data store. The server data store is an enterprise relational database server such as IBM DB2, Oracle, or Microsoft SQL Server. The local data store is a local relational database provided in Lotus Expeditor Client. Lotus Expeditor provides IBM Cloudscape and IBM DB2 Everyplace as local database options.

IBM Lotus Notes/Domino is also a client/server application. Because the new Lotus Notes V8 client is built atop the Lotus Expeditor platform and because many readers are familiar with Lotus Notes, each pattern is also expressed in terms of familiar Lotus Notes concepts.

Always offline

Figure 2 illustrates the always-offline pattern. In this pattern, the client always interacts with data from a local database regardless of whether or not the client can physically connect to the server data store. When possible, the local database synchronizes with the server database on a regular schedule or at the user’s request.

Figure 2. The always-offline client/server data access architecture
The always-offline client/server data access architecture

In Lotus Notes, this pattern is the equivalent of a user always accessing a local database replica. Periodically, the user replicates the local database with the server. The user never opens the database using the server’s replica.

Synchronization does not need to always occur on a schedule. When the client is online – that is, when the client has connectivity to the server -- database synchronization can be triggered immediately after an update is made to the local database. This effectively provides an instant update of the server-side database when the client changes. Lotus Expeditor provides network awareness APIs along with an Online/Offline UI control to determine connectivity.

Benefits of the always-offline pattern include:

  • Availability. The client application can always function regardless of whether or not the client has connectivity.
  • Fast performance. Local database access is always quicker than accessing a remote database.
  • Reduced server load. Client/server interactions are limited to synchronization activity.

Always online

Figure 3 illustrates the always-online pattern. In this pattern, the client always reads and writes against a server-side data store. Remote procedure call (RPC) Web services or REST-based APIs are normally used for this type of client/server interaction.

REST-based APIs offer an alternative to Web services for client/server interaction. The REST pattern assumes that clients are interested in creating, reading, updating, and deleting (CRUD) remote resources. Resources can be anything from images to orders to people. In REST, clients address a remote resource and provide the CRUD action as the HTTP request method (GET, PUT, POST, DELETE). The server then typically returns an application-specific XML document with the results.

In RPC-style Web services, clients perform CRUD against remote resources by invoking remote actions like getPerson() and updatePerson(). Both request and response are wrapped in SOAP envelopes. Modern tooling shields developers from the work of creating and reading the SOAP envelopes.

Figure 3. The always-online client/server data access architecture
The always-online client/server data access architecture

For example, the client calls RPC Web service methods such as createTimesheet() or getOrdersByCustomer() against a server-side application to interact with the data store. Direct database access using JDBC from client to server is discouraged as this creates a tight coupling that greatly complicates application maintenance.

This architecture is similar to a Web browser experience using Ajax. In Ajax, the UI and application logic are downloaded and executed on the browser. The browser then uses JavaScript to read/write the data necessary for the application without forcing the user to reload the page. This parallels a Lotus Expeditor application that already contains the UI and application logic and only needs to read/write data from/to the server.

In Lotus Notes, this pattern is equivalent to a user always using a server replica of a Lotus Notes database. The user never replicates the database locally.

There are three key benefits of this architecture:

  • The client always works with current data.
  • The server data store is updated instantly.
  • There are no synchronization logic and conflicts to deal with.

Mixed architecture

Figure 4 illustrates the mixed architecture pattern. In a mixed architecture, the client application is aware of whether it is online or offline. When online, the client-side application operates against the server-side data store. When offline, the client-side application operates against the local data store. The client periodically synchronizes changes made to the local database to the server when the client is online. The presentation tier must know which mode the client is in and render the proper widgets and data accordingly.

Figure 4. The mixed client/server data access architecture
The mixed client/server data access architecture

To enable different application behavior when online rather than offline, Lotus Expeditor recognizes an overall online/offline client state. Online/offline state is determined by the user through a UI control and/or can be set programmatically. Client-side applications can query the platform for the current online/offline mode as well as respond to mode-change events.

Lotus Expeditor also provides network awareness APIs enabling applications to query physical network connectivity as well as the availability of specific remote resources. Refer to the network awareness section in the Lotus Expeditor InfoCenter listing in the Resources section of this article.

This pattern is the most complex of the three and can be thought of as a combination of the other two architectures that offers the best of both worlds. This pattern is a good fit for users who:

  • Are connected most of the time with good bandwidth
  • Occasionally go offline
  • Want to take their data with them or make updates while offline

In Lotus Notes, this pattern is equivalent to a user who normally uses the server replica while at the office and uses a local replica while traveling. Before traveling, the user replicates with the server to have the latest changes available while disconnected. When the user returns, he or she replicates the local changes to the server. This is a common usage pattern in Lotus Notes.

An alternative to this pattern is using the always-offline pattern and coding the application to synchronize immediately in the background when changes are made to the local database. This experience approximates the mixed architecture, but is simpler to implement because the presentation tier and application logic are always against the local database.

This architecture has the following benefits:

  • It takes advantage of connectivity when available to work with data in real-time and realizes all the benefits of the always-online architecture.
  • It provides an offline experience for the application.

Data synchronization options

In the always-offline and mixed architectures, local changes need to be propagated to the server, and the client needs to receive updates from the server. This section discusses different data synchronization options.

Data synchronization using IBM DB2 Everyplace

Lotus Expeditor Server includes IBM DB2 Everyplace Sync Server, which enables the Lotus Expeditor Client (desktop and device) to synchronize a local relational database with a server-side database. Lotus Expeditor Client includes an ISync client, which connects to DB2 Everyplace Sync Server and performs the synchronization. DB2 Everyplace Sync Server and ISync provide a powerful out-of-the-box engine to synchronize relational data.

Benefits of DB2 Everyplace include:

  • It is included with Lotus Expeditor Server.
  • It is a proven enterprise data synchronization product.
  • It offers row-level security.
  • It can filter data on a per-user basis.
  • It offers integrated conflict-handling logic.
  • It reduces the load on the source database through database mirroring (devices synchronize against a replicated mirror database instead of against the source database directly).

DB2 Everyplace synchronization has two main drawbacks:

  • Customers must install and administer a DB2 Everyplace Sync Server environment.
  • Data synchronization alone may not be sufficient for every application. Applications may instead require a transactional approach where devices submit transactions that update multiple backend systems instead of a single database.

Data synchronization using RPC Web services or REST APIs

Data synchronization can also be achieved using remote procedure call (RPC) Web services or a REST-based API. These technologies provide a more transactional model where clients send and receive data updates in HTTP requests. The server can then update backend database(s) and other resources from the client requests. For example, a server can provide RPC Web service methods such as getTimeSheets(), updateBillCode(), and deleteOrder(), which can pass in and/or return Java objects.

When using RPC Web services or REST APIs, the local and remote databases do not synchronize directly. Instead, objects or data are passed across the wire in HTTP requests, and both the client and the server update their own databases from this data. Both the client and the server have an object persistence layer that reads and writes objects to the local database.

REST-based APIs are an alternative to RPC Web services. Instead of sending Web service calls to the server, clients (desktops and devices) can communicate with the server using REST-style HTTP requests. For example, assume the client wants to retrieve a list of orders from the server. In Web services, the RPC call getOrders() is sent to the server in a SOAP envelope, and a collection of orders is returned in a SOAP envelope. In a REST-based API, the client sends a GET HTTP request to sa URL similar to http://example.com:1234/api/rest/orders, and the server returns an XML document with the orders.

While Web service calls are much more complex than REST-based API calls, Web services are mature and benefit from tooling that effectively shields developers from the complexity. On the client side, the Lotus Expeditor Toolkit has wizards to generate local proxies of remote Web services from the Web services’ WSDL (Web Services Definition Language). These local proxies enable you to call local Java methods such as getOrders() that return an array of Order objects from the server. You then typically map the objects returned by proxies into objects used in the local model. Similar tooling exists for most server-side platforms to take a service class and to generate a Web service provider and WSDL for that service.

When using RPC Web services or REST APIs to synchronize the client and the server, you must implement the synchronization logic to identify local and remote updates and to send and receive those updates accordingly. This logic can be contained on the client or spread across the client and the server.

What follows is an example process flow of a client synchronizing orders with a server using RPC calls over Web services. The client follows a push-pull approach where local updates are first pushed to the server, and then the server pulls updates from the server that include updates that were just pushed. In this example, the server’s version of a given record always takes precedence over the client’s record because the server’s record often has new data set by the backend.

  1. The user leaves the office with a laptop containing a Lotus Expeditor application for entering part orders. The user has no connectivity to the corporate intranet while away from the office.
  2. The user enters a new order into the Lotus Expeditor part order entry application while disconnected.
  3. The order entry application flags the order as Pending Create in the local database to indicate that it needs to be created on the server.
  4. The user returns to the office. Lotus Expeditor now has connectivity to the order entry server.
  5. The user initiates a sync by clicking “Synchronize the selected application now” on the Order Entry item in the Lotus Expeditor synchronization page. Lotus Expeditor provides a synchronization framework where application synchronization activities can be managed from a central synchronization page (much like the Lotus Notes replicator page). Users can start synchronization manually, define a synchronization schedule, and/or define platform events that trigger synchronization like client startup.
  6. The order entry application pushes all pending updates in the local database to the server. For each local order marked Pending Create, the order entry application calls the createOrder() method on the order entry server’s Web service, passing in an Order object constructed from the local database.
  7. The createOrder() calls complete successfully (no exceptions are returned).
  8. The order entry application removes the Pending Create flag from the local orders that completed successfully.
  9. The order entry application then pulls all updates since the last successful sync. These updates include orders submitted by other users and orders that were just pushed by this client. The client requests all orders from the server that have been modified or created since the last successful sync. The client maintains the timestamp of the last successful sync and uses this when requesting the updated orders.
  10. The order entry application persists the updates received from the server into the local database. When the order entry application receives an order from the server that also exists on the client, the application replaces the local order with the server’s order. The server’s version of the order always takes precedence.

Benefits include these factors:

  • RPC Web services and REST APIs enable further decoupling of client and server. As long as the Web service or REST API contract remains constant, clients and servers are free to change data store implementations.
  • RPC Web services and REST APIs do not depend upon DB2 Everyplace Sync Server.
  • RPC Web services and REST APIs are backend agnostic, which means that Lotus Expeditor clients could synchronize directly against application servers from any vendor.
  • RPC Web services and REST APIs enable a transactional model where client Web service calls or REST API requests can go beyond just CRUD (create, read, update, delete) of a remote resource. Client Web service calls or REST API requests can also trigger updates to other backend systems as well as trigger additional workflow.

One drawback is that you must write the actual synchronization logic and any conflict-handling logic. The Contacts sample provided with this article shows an example of data synchronization using Web services.

Data synchronization using IBM WebSphere MQ Everyplace

IBM WebSphere MQ Everyplace can be used to store client-side updates until they can be sent to the server. WebSphere MQ Everyplace provides point-to-point assured messaging between two devices. Features of WebSphere MQ Everyplace include:

  • Asynchronous and synchronous messaging
  • Support for a wide range of devices with a small, customizable footprint
  • Authentication, encryption, nonrepudiation, and compression
  • Automatic channel management
  • Built-in comprehensive security features
  • Object messaging (data and function)
  • Once-only assured delivery
  • Bridge to IBM WebSphere MQ

As shown in figure 5, WebSphere MQ Everyplace can provide an alternative to Web services or REST APIs for sending client updates to the server. When using Web services or REST, you implement logic to keep track of pending updates to the server. When using WebSphere MQ Everyplace, you place the update, such as a new order, into a WebSphere MQ Everyplace message, and then place that message onto a remote queue. WebSphere MQ Everyplace takes it from there to deliver that new order message to the server. The server can be set up to send a reply message when a client’s message is received and processed. The client considers the update complete when the reply message is received from the server.

Figure 5. Data sync using WebSphere MQ Everyplace
Data sync using WebSphere MQ Everyplace

IBM WebSphere MQ Everyplace provides an alternative for sending updates to the server. Clients can receive updates from the server using the options previously discussed (IBM DB2 Everyplace Sync Server/ISync, Web services, or REST APIs).

What follows is an end-to-end example of sending an order to the server:

  1. The user leaves the office with a laptop containing a Lotus Expeditor application for entering part orders. The user has no connectivity to the corporate intranet while away from the office.
  2. The user enters a new order into the Lotus Expeditor order entry application while disconnected. The order status is Pending.
  3. The order entry application places the order into a WebSphere MQ Everyplace message.
  4. The order entry application writes the MQ Everyplace message to a remote queue defined in the local queue manager.
  5. WebSphere MQ Everyplace attempts to deliver the message containing the order to the WebSphere MQ Everyplace queue on a remote queue manager.
  6. WebSphere MQ Everyplace fails to deliver the message because the user is disconnected.
  7. The user returns to the office and connects to the network.
  8. WebSphere MQ Everyplace succeeds in delivering the order message to the server.
  9. The server sends a reply message to the local queue manager on the laptop.
  10. WebSphere MQ Everyplace notifies the order entry application.
  11. The order entry application updates the order status to Received.

Data synchronization with WebSphere MQ Everyplace takes advantage of the WebSphere MQ Everyplace infrastructure for secure, assured message delivery from client to server. This benefit, though, is balanced by two drawbacks. You must install and administer a WebSphere MQ Everyplace environment. Plus, similar WebSphere MQ Everyplace capability can be achieved by adding some retry and exception-handling logic around Web services/REST calls.


Contacts Sample: Online/offline application with synchronization using RPC Web services

To illustrate an offline application in action, a synchronized contacts sample is provided. This application contains a simple list of contacts that are synchronized between the client and the server using the mixed pattern described previously.

The Lotus Expeditor Toolkit includes samples for WebSphere MQ Everyplace and DB2 Everyplace Sync Server, so this sample uses RPC Web services for data synchronization. Web services also allow the sample to be run without installing the DB2 Everyplace Sync Server or WebSphere MQ Everyplace products.

The Contacts Sample application shows a list of contacts from the server while the client is in online mode. When the client is in offline mode, the contacts are shown from a local DB2 Everyplace database.

Because Lotus Expeditor contains its own Web container and Web service provider stack, the server portion of the sample is hosted on Lotus Expeditor along with the client. The contact server bundle provides a Web service that is consumed by the contact client bundle. The client and the server interact only through these Web service calls.

Contacts Sample bundles

Table 1 shows the bundles used in the Contacts Sample application.

Table 1. Contacts Sample bundles
BundleDescription
com.ibm.dw.contacts.clientMain bundle. This bundle is the online/offline client-side application and contains all the UI and synchronization logic.

The bundle communicates with the server bundle using Web services and uses DB2 Everyplace as the local relational database to store the local contacts.
com.ibm.dw.contacts.serverServer bundle. This bundle acts as a remote server by providing a Web service. The Web service is hosted on the Lotus Expeditor Web container and Mobile Web Services stack.

This bundle has no UI and auto-starts when Lotus Expeditor starts. IBM Cloudscape is used to store the server-side contacts.
com.ibm.dw.contacts.featurewFeature project to contain the two bundles. This is needed to create installation artifacts.
com.ibm.dw.contacts.updatesiteUpdate site project for the feature. This is needed to create installation artifacts.

Let’s look at the end-to-end process of how a local contact is created, and then synchronized to the server.

Step 1: Create a new local contact

First, the user opens Contacts Sample in the offline mode. In Lotus Expeditor, online/offline mode is controlled by the toggle in the bottom-right area. In Lotus Notes V8 (which is built on Lotus Expeditor), online/offline mode is controlled by the current location setting.

Figure 6 shows that the Contacts Sample is using the local database (as indicated by the banner) and that a new contact named NEW USER was added.

Figure 6. New contact added to local database
New contact added to local database

The Contacts Sample uses a multitier pattern for data access: presentation - service - data access object - database. In this step, the Add button gathers the data, and then calls the LocalContactService to add the new contact.

LocalContactService calls LocalContactDAO to persist the Contact object. Using the fields in the Contact object, LocalContactDAO makes JDBC calls to persist the Contact in the local DB2 Everyplace database.

The snippet in listing 1 shows the createContact() method in LocalContactService.

Listing 1. createContent() method
public void createContact(Contact contact) throws Exception {
		contact.syncStatus = Contact.SYNC_PENDING_CREATE;
		insertContact(contact);
	}

Note the syncStatus field. This field flags the contact that it needs to be created on the server when the client synchronizes. The insertContact() method calls createContact() in LocalContactDAO.

The code in listing 2 shows the createContact() method in the LocalContactDAO, which persists the contact.

Listing 2. createContact() method
public void createContact(Contact contact) throws Exception {
		logger.entering(getClass().getName(), "createContact", contact);
		Connection conn = getConnection();
		try {
			PreparedStatement pstmt = conn.prepareStatement(SQL_INSERT_CONTACT);
			pstmt.setString(1, contact.guid);
			pstmt.setString(2, contact.fname);
			pstmt.setString(3, contact.lname);
			pstmt.setString(4, contact.phone);
			pstmt.setInt(5, contact.syncStatus);
			pstmt.execute();			
			pstmt.close();			
		} finally {
			conn.close();
		}
		logger.exiting(getClass().getName(), "createContact");
	}

Step 2: Synchronize

The next step is to synchronize the local change to the server using the Lotus Expeditor synchronization page as shown in figure 7. Note that synchronization can be performed only when Lotus Expeditor is in online mode.

Figure 7. Lotus Expeditor synchronization page and Contacts Sample entry
Lotus Expeditor synchronization page and Contacts Sample entry

Entries on the Lotus Expeditor synchronization page are called sync units. When the Contacts Sample sync unit is invoked, ContactSyncService.sync() is ultimately invoked as shown in listing 3.

Listing 3. Invoking the Contacts Sample sync unit
public void sync() throws Exception {
		logger.info("Sync: start");
		pushLocalUpdates();
		pullRemoteUpdates();
		logger.info("Sync: end");
	}

ContactSyncService.sync() uses a push-pull approach to synchronization. First, all the local contacts flagged as create-pending, update-pending, or delete-pending are sent to the server.

The code in listing 4 shows the pushLocalUpdates() implementation. The clearSyncFlag() method simply removes the sync flag from each contact so it will not be processed again.

Listing 4. pushLocalUpdates() implementation

Click to see code listing

Listing 4. pushLocalUpdates() implementation

private void pushLocalUpdates() throws Exception {
		logger.info("Sync: pushing local updates to server");
		Contact[] pendingContacts = localContactService.lookupPendingContacts();
		for (int i=0; i<pendingContacts.length; i++) {
			if (pendingContacts[i].syncStatus == Contact.SYNC_PENDING_CREATE) {
				remoteContactService.createContact(pendingContacts[i]);
				clearSyncFlag(pendingContacts[i]);
				logger.info("Sync: created new contact on server: " + pendingContacts[i]);
			} else if (pendingContacts[i].syncStatus == Contact.SYNC_PENDING_UPDATE) {
				remoteContactService.updateContact(pendingContacts[i]);
				clearSyncFlag(pendingContacts[i]);				
				logger.info("Sync: updated contact on server: " + pendingContacts[i]);
			} else if (pendingContacts[i].syncStatus == Contact.SYNC_PENDING_DELETE) {
				remoteContactService.deleteContact(pendingContacts[i]);
				localContactService.removeContact(pendingContacts[i]);
				logger.info("Sync: deleted contact on server: " + pendingContacts[i]);
			}
		}
	}

Once all the local changes are pushed to the server, the sync() method pulls all updates from the server. These updates include the changes that were just pushed. In this application, the server’s record always takes precedence over the client’s record. For example, the server’s record could contain additional fields set by the server.

The code in listing 5 shows the pullRemoteUpdates() implementation. This method requests all server updates since the last successful sync and then updates the local database by creating, replacing, or deleting local contacts. After each server update is processed successfully, the client records the timestamp of the update. The last recorded timestamp is used in the next sync to find new updates.

Listing 5. pullRemoteUpdates() implementation
private void pullRemoteUpdates() throws Exception {
		logger.info("Sync: pulling remote updates");
		long timestamp = store.getLong(IConstants.PREF_LAST_SYNC_TIME);
		Contact[] updatedContacts = remoteContactService.lookupUpdatedContacts(timestamp);
		
		// sort contact list so they are processed in-order
		List contactList = Arrays.asList(updatedContacts);
		sortContacts(contactList);
		
		for (Iterator it = contactList.iterator(); it.hasNext();) {
			Contact remoteContact = (Contact)it.next();
			Contact localContact = localContactService.lookupContact(remoteContact.guid);
			if (localContact == null && !remoteContact.serverDeleted) {
				// new contact
				localContactService.insertContact(remoteContact);
				updateTimeStamp(remoteContact);
				logger.info("Sync: created new contact on local: " + remoteContact);
			} else if (localContact != null && remoteContact.serverDeleted){
				// delete local contact
				localContactService.removeContact(remoteContact);
				updateTimeStamp(remoteContact);
				logger.info("Sync: deleted contact on local: " + remoteContact);
			} else if (localContact != null && !remoteContact.serverDeleted) {
				// replace local contact
				localContactService.replaceContact(remoteContact);
				updateTimeStamp(remoteContact);
				logger.info("Sync: replaced contact on local: " + remoteContact);
			}
		}
	}

Step 3: Verify new contact on server

With the client in online mode, switch back to the Contact Sample application to verify that the new local contact now appears as shown in figure 8.

Figure 8. Local contact has been synchronized to the server and now appears when the client accesses the online store
Local contact has been synchronized to the server and now appears when the client accesses the online store

When the client is in online mode, the contacts table is populated from the server using Web service calls. The new contact now appears in this list because it now exists in the server’s database.

Running the sample

Follow these steps to install the sample in Lotus Expeditor.

  1. Download contacts-sample zip from the Downloads section of this article.
  2. In Lotus Expeditor, choose File – Application – Install.
  3. In the Install/Update dialog box, select “Search for new features to install.”
  4. In the Install dialog box, click Add Zip/Jar Location and browse for the contacts-sample.zip file you downloaded in the first step. When it is selected, the file appears as an install location.
  5. Click Finish in the Install dialog box. The Updates dialog box appears showing the available features from contacts-sample.zip. Select the feature to install as shown in figure 9.
Figure 9. Contacts Sample as an install location
Contacts Sample as an install location
  1. Complete the install wizard by accepting the license agreement and restarting Lotus Expeditor. When the restart is complete, the sample appears in the Open menu as shown in figure 10. The open application is shown in figure 11.
Figure 10. Contacts Sample now in Open menu
Contacts Sample now in Open menu
Figure 11. The Contacts Sample application. “Default User” is created automatically on the server during application initialization.
he Contacts Sample application. “Default User” is created automatically on the server during application initialization.

Conclusion

One of the key benefits of the Lotus Expeditor platform is its ability to build applications that can function offline. This article introduced three general architectural patterns for designing online/offline applications. These patterns determine how applications deal with data.

The first pattern is the always-offline pattern. In this pattern, the user always interacts with data from a local data store. Periodically, the application will refresh the local store from data on the server and propagate changes made by the user to the server. This pattern simplifies online/offline development because the presentation tier always uses the local data store.

The next pattern is the always-online pattern. In this pattern, the user always interacts with data from a remote data store. Business logic and UI are rendered locally, and the application makes requests to the server for data. This pattern is similar to a brower-based application using Ajax.

The third pattern is the mixed pattern. In this pattern, the user interacts with a remote data store when the client is online and interacts with a local data store when the client is offline. This pattern allows users to take advantage of server connectivity when available and provide an offline experience when connectivity is not possible. The trade-off is that this pattern can be the most complex to implement.

To illustrate the mixed pattern, a sample is provided with this article. The Contacts Sample application enables a user to maintain a set of contacts. When online, the user works with the contacts on the server data store. When offline, the user works with the contacts in the local store. The user can synchronize the two stores from the Lotus Expeditor synchronization page.

In the always-offline and mixed patterns, data needs to be synchronized between the client and the server. This article also reviews three methods for synchronizing data. These include using IBM DB2 Everyplace Sync Server, using Web services or REST APIs, and using IBM WebSphere MQ Everyplace.


Downloads

DescriptionNameSize
Code samplecontacts-sample-src.zip180KB
Code samplecontacts-sample.zip63KB

Resources

Learn

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into IBM collaboration and social software on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Lotus, WebSphere, Information Management
ArticleID=218334
ArticleTitle=Building an offline application in IBM Lotus Expeditor
publish-date=05082007