Jan 20

Working with WebSQL in an HTML5 mobile app

I wrote some days ago that I now work on a BlackBerry 10 app using BlackBerry WebWorks, which is basically Apache Cordova (Phonegap).

The app needs to read data from JSON sources and store it locally, so that the app works offline. So I need local storage, and although the WebSQL specification came to an end, it’s supported in WebWorks, Chrome and other platforms.

Working with WebSQL is relatively straightforward because in the end it’s the well known SQLite in the backend. But, you have to deal with callbacks. For example, to write stuff you’re using this kind of code:

// size in bytes, for example 1024*1024*1
// params may be an array of data for the sql statement
var size = 1024*1024*1;
var db = openDatabase("mydb", '1.0', "mydb", size);
var f = function(tx) {
  tx.executeSql(sql, params, function(transaction, result) {
	// success, do something with the result
  }, function(tx, e) {
     // failure, error is in e.message
  });
};
db.transaction(f);	

So there are two callbacks, one in case of success and one in case of error. If you want to execute multiple statements at once, you can put them all into one transaction. In that case you have to do some work to handle the results and errors. Something like this:

f = function(tx) {
	var hasError = false;
	var errors = [];
	var results = [];
	_.each(sql, function(singlesql) {
		tx.executeSql(singlesql, params, function(transaction, result) {
			results.push(result);						
		}, function(tx, e) {
			// failure
			hasError = true;
			errors.push(e.message);						
		});	
	});
	// do something with the result
};

(Note: _.each() is a method of underscore.js framework.)

Unfortunately this does not work reliable. Do you spot the error?

The function iterates though an array of sql statements, and each statement is being executed and in the result callback the result of that statement is added to a result array.

But what happens if you want to use the result array right after the _.each() loop? You’re using the result array before all the callbacks from the sql statements has been executed! So it may be null or contains only some entries, but not all.

You need to work on the results only when all sql statements have been executed:

f = function(tx) {
	var hasError = false;
	var errors = [];
	var results = [];
	var len = sql.length;
	for (var i = 0; i < len; i++) {
		tx.executeSql(sql[i], params, function(transaction, result) {
			results.push(result);
			if (i == (len-1)) {
				// do something with the result HERE!
			}			
		}, function(tx, e) {
			// failure
			hasError = true;
			errors.push(e.message);						
		});	
	};
};

In a real world app that may get cumbersome when you do lot of work with WebSQL. Therefore I started to write a framework, just like I always do when things get complicated 🙂

What about this code:

b = new JBUDatabase("mydb");
// create table if it does not exist yet
db.createTable("tickets", [ {
	name : 'id',
	type : 'TEXT'
}, {
	name : 'title',
	type : 'TEXT'
} ]);
// create a demo array of data for 100 tickets
var data = [];
for (var i = 1; i < 100; i++) {
	data.push(["ID "+i,"ticket title "+i])
}
// write the data to the WebSQL database
db.writeEntries("tickets", data);

All the WebSQL stuff packaged in a simple to use API. Much more clear, isn't it?


Dec 05

Making a “immedidate” ft index really immediate – please try this notes.ini variable

Yesterday I wrote about problems with the “immediate” update frequency of a ft index. I didn’t found any way to make the indexer faster.

A collegue from IBM told me to try this notes.ini setting on the Domino server:

UPDATE_SUPPRESSION_TIME=-1

Which should set the interval when the indexer looks for work to one second. Sounds wonderful in theory, but on two 9.01 servers I tested this setting does not do anything.

If you have a Domino server at your hands where you can test things, can you please set UPDATE_SUPPRESSION_TIME=-1 to the server’s notes.ini and check if the ft index of a database with the update frequency “immediate” is updated faster than usual?

Thanks!

 


Apr 09

I am proud of DominoToGo. It. Just. Works.

(If you see a video about what I’m writing about, just scroll down…)

I’m just back from a customer in Zurich, Switzerland where we kickstarted a DominoToGo project.

A quite interesting project from my perspective: it’s about coroners that want to write reports about dead people on an iPad mini while they are on site.

So far they had a Notes application in the office, so that they needed to make notes somewhere, for example on a sheet of paper, and enter the information when they’re back in the office.

Since the Notes application should continue to be master of the data, the iPad app needs to push new reports to the Notes application. Furthermore, to create a report, several lists are needed from Notes, for example Notes user names and selection lists for fields like “cause of death”.

Does everyone die in places with good network coverage?

Unfortunately, people do not always die in places with good network coverage, so offline functionality is essential. Therefore a web based app is out of the question, just as in so many other projects I recently worked on.

About the app

So basically the app needs to:

– get a list of all Notes users from the Domino Directory
– get several selection lists from one NSF
– get a list of customer records from another NSF
– offer a form to enter the data
– offer several selection dialogs in the form, something like a view pick list in Notes
– save the data to a new document
– upload the document to a third NSF in Domino, when the device is online
– if the device is offline, the data needs to be queued locally and uploaded sometime later

What we did

In Appcelerator Titanium we started with a template that is delivered with the DominoToGo package. This template contains an app with basic functionality like

– layout for iPad, iPhone and Android
– a configuration dialog for entering the Domino username and password
– an HTML based “about” page
– basic navigation
– a skeleton for synchronization functionality

This template app already has the DominoToGo libraries included so we could start immediately with the business logic.
Futhermore, this template app already uses Titanium’s Alloy framework, which is a system where layout, logic and data is organized separately and the app code is very well structured. The layout is defined with simple XML tags while the logic is written with JavaScript.

First step: synchronization

We started with the synchronization logic. As written above, several Notes views needed to be synchronized to the app. With DominoToGo, this was a no-brainer, here is a piece of the code:

function sync_personen(success, e) {
if (!success) {
DTG.log("Sync von names fehlgeschlagen: "+e.error);
return;
}
var view = Alloy.Globals.notesdb_adressen.getView("(iLotus_Personen)");
view.update(sync_adressen, false, 'Synchronisation fehlgeschlagen: %s');
}

function sync_names(success, e) {
if (!success) {
DTG.log("Sync von fehlgeschlagen: "+e.error);
return;
}
var view = Alloy.Globals.notesdb_names.getView("(iLotus_People)");
view.update(sync_personen, false, 'Synchronisation fehlgeschlagen: %s');
}

Regarding the amount of data, we counted some hundred Notes users from the Domino Directory, some 500 customer records and about one hundred keywords used in selection lists.

The synchronization took about one second to complete. It is so fast, that we simply let the synchronization run everytime the app starts, the user doesn’t notice it at all.

Second step: designing the form

The basic form was done very quick thanks to the great Titanium Alloy framework. For example, have a look at this code:


and now look what this kind of tag produces in the app:

It’s a generalized view picker dialog which displays the content of a Notes view in a picker dialog in the app (of course, even when the iPad is offline). I wrote code for various generalized picker dialogs, like a date picker, a view picker and a selection list picker. My customer now only needs one line of XML code like the one above to use such dialogs. Not that bad, isn’t it?

Third step: uploading data to Notes

Data entered in the form in the app should be uploaded to a Notes application in Domino. Nothing simpler than that, look here (no, that’s not LotusScript! It’s JavaScript in Titanium);

var notesdb = Alloy.Globals.notesdb_ereignisse;
var doc = notesdb.createDocument();
doc.replaceItemValue("form", "FM-LN");
doc.replaceItemValue("Name", $.fields1.c_getValue1());
doc.replaceItemValue("Vorname", $.fields1.c_getValue2());
doc.save(true);

But there was one additional requirement: the documents need to get a number based on special numbering rules. This numbering could only be done on the Domino side. A problem? Hell no!

In DominoToGo there is a SSJS library on the Domino side that provides extension points, for example when a new document has been uploaded from the app to Notes,

So we simply needed to write some server side JavaScript code in this library which computes a new number and stores it in the new document that just has been uploaded by the app. Simple and clean.

My job was done and I am proud

After developing and explaining all this functionality my job was done. Now the customer has all the functionality and pieces needed to finish the app by himself.

I’m proud of DominoToGo. All the synchronization functionality needed in this project was implemented in minutes and just worked. Reliable and fast.

Yes, since I developed the DominoToGo framework by myself such a statement seems to be selfish. Nevertheless, I’m still proud of my work 🙂

If you want to read more about DominoToGo, have a look here.


Jun 14

More experience with developing Appcelerator Titanium mobile Apps (Alloy, Performance…)

Note: this post has been migrated from another blog. Some links may be broken.

Recently I got a new project to develop a mobile app as frontend for a complex IBM Notes application. Target platform is iOS first and Blackberry 10 later, maybe even Android. The customer selected Appcelerator Titanium as platform and Domino To Go as framework for working with IBM Notes data. Offline capability with storage of relatively big datasets was mandatory, so any mobile web or hybrid approach was out of the game.

I know there are posts in the Web
saying how ugly Titanium is, how many problems it has et al. From my experience, all of that is not true, at least not today. The Titanium development environment works smooth and stable, every API works as it should. The API documentation is very good, and Appcelerator even offers a lot of additional documentation for topics like how to setup the native SDK for iOS, Android and Blackberry 10. Furthermore, the Q&A section of Appcelerator’s website is excellent and a reliable source for solving development questions.


Since I know Titanium for a long time now, I’m aware that in the early days of Titanium things were completely different. There were lots of memory and stability problems and documentation was poor – but as I said above, all of those problems are gone, at least in my experience.


And most importantly, I like the approach of using simple JavaScript to access native APIs across all platforms. It spares the huge learning curve of Objective C for iOS, Java for Android and whatever for Blackberry 10. And, you can have the same codebase to deliver an app for all platforms.


The new Alloy model-view-controller framework of Titanium is a great addition, too. It allows to seperate UI definitions and data models from business logic, and it’s well engineered, clean and logical. In Alloy, the UI is defined with simple XML code, which is transformed to traditional Titanium JavaScript code automatically by the Alloy compiler. It allows you to work with stylesheets and to create your own UI components for re-use in the same project or in another projects.


When working in an Alloy Titanium project, you are motivated to modularize your code with the CommonJS technique, which is also a good thing because it prevents namespace issues and offers a well-established system to split your project into manageable pieces.


In that project, the customer uses Domino To Go to synchronize about 100.000 datasets from Notes views to the device, so they can be used offline. There are three components that take time during the synchronization:


1.) Domino To Go on the Domino side needs to run through the view, read view entries and build JSON data.


2.) The device needs to download the JSON data from Domino.


3.) The JSON data needs to be processed on the device to transform then into a NotesView-like data structure and store it in the SQLite database on the device.


First, a full synchronization took more than 3 minutes in the simulator. After some optimization, we managed to bring this down to about 40 seconds. After the first full synchronization, caching techniques are used, so next synchronisations will be even faster.
But, from my point of view, 40 seconds for about 100.000 view datasets is not that bad after all 🙂


The only ugly thing
with developing a native iOS App is the amount of work needed to be able to deploy the app on test devices first, and for the enterprise distribution later. To deploy on test devices, you need apply for the Apple developer program, which can take some days until Apple checked and processed your application. Then you need to understand their system of provisioning profiles and all the certificates you need.


For every test device you need to get it’s UUID, enter it in the member area of the iOS developer center, create a new provision profile, download it and install it on the Mac. Sure, you will do this work seldom, only when you got a new test device, but for new developers, it takes some time to understand this procedure.


But the Apple procedures have nothing to do with Titanium. I think, Titanium is a very good choice to develop native mobile apps. I like mobile web apps, too, but so far, I like working with Titanium better.


Jan 29

Updated our YouAtNotes Workflow for Notes and XPages Demo!

Note: this post has been migrated from another blog. Some links may be broken.

As you might know, we have a wonderful solution for developing workflows for classic Notes and XPages: YouAtNotes Workflow.

I just want to let you know that we updated the free demo version to version 5.9, which is the most recent version at the moment. So if you just downloaded the demo, you should download again 🙂