RSS

Category Archives: Google Gears

Google Gears – Future of Web Application

How to take your Web Application Offline with Google Gears ?

• It will be hard to determine what is
and isn’t a web app
• The web will be everywhere
• Mobile (iPhone)
• Desktop
• Widgets
• TV
• The browser will be fast

Why?

• Reliability
• 1% of downtime can hurt at the wrong time
• Performance
• Local acceleration
• Convenience
• Not having to find a connection
• You are offline more than you think!

Offline Web via Open Web

• Why just solve this problem for Google?
• Why not solve it for others?
• Solution: Make it open source with a liberal license
• New BSD

What is the philosophy?

• One application, one URL
• Seamless transitions between online and offline
• Ability to use local data, even when online
• Available to all users on all platforms
• … and a pony

Do for offline what XMLHttpRequest did for web apps

Ajax Architecture

Offline Architecture

• Read and write using local store
• Changes are queued for later synchronization
• Server communication is completely decoupled from UI actions, happens periodically whenever there is a connection

What are the pieces?

Database

Embedded using SQLite Contributed Full Text Search

var db = google.gears.factory.create('beta.database', '1.0');
db.open('database-demo');
db.execute('create table if not exists Demo (Phrase varchar(255),
Timestamp int)');
db.execute('insert into Demo values (?, ?)', [phrase, currTime]);
var rs = db.execute('select * from Demo order by Timestamp desc');

GearsDB – (Abstract over the API)

var bob = {id: 3, name: 'Bob', url: 'http://bob.com', description: 'whee'};
db.insertRow('person', bob);
db.insertRow('person', bob, 'name = ?', ['Bob']);
db.selectAll('select * from person', null, function(person) {
document.getElementById('selectAll').innerHTML += ' ' + person.name;
});
var person = db.selectRow('person', 'id = 1');
// update
person.name = 'Harry';
db.updateRow('person', person);
person = db.selectRow('person', 'id = 1');
// force
person.name = 'Sally';
db.forceRow('person', person);
person = db.selectRow('person', 'id = 1');
db.deleteRow('person', bob);

GearsORM – Are we going to get a GearsHibernate?

var Person = new GearsOrm.Model("Person", {
firstName: GearsOrm.Fields.String({maxLength:25}),
lastName: GearsOrm.Fields.String({maxLength:25})
});
GearsORM.Transaction(function() {
new Person({name:"John"}).save();
new Person({name:"Doe"}).save();
});
Person.select("firstName = 'Uriel'");
Person.count("lastName = ?",["Katz"])

“While developing transaction support for GearsORM i had to write a test, in that test it execute 100 inserts and 100 updates, this test take about 15 seconds  for the inserts and about 10 seconds for the updates without transactions,when using transactions for each set it takes about 377ms for the inserts and 200ms for the updates that is about 39 times faster!”

GearShift – DB Migrations for Gears

Gearshift.rules[1] = {
// create the demo table
up: function() {
return this.e("CREATE TABLE demo_table (
id INTEGER PRIMARY KEY
AUTOINCREMENT,
name VARCHAR(30),
movie VARCHAR(30)
)").success;
},
down: function() {
return this.e("DROP TABLE demo_table").success;
}
};

Database Tools

Alignment with AIR – Ext.data.SqlDB

The APIs for AIR and Google Gears are nothing alike. In fact, AIR’s SQLite database API is 100% asynchronous via events while Gears API is all synchronous with results coming immediately on execution. So Ext.data.SqlDB was created to abstract both of these APIs into a single API to access both.

Local Server  – A mini-web server that groks 200 and 304

ResourceStore  Manually Capturing

var pageFiles = [
location.pathname,
'gears_base.js',
'../scripts/gears_db.js',
‘foo.html’
];
try {
localServer = google.gears.factory.create('beta.localserver', '1.0');
} catch (e) {
alert('Could not create local server: ' + e.message);
return;
}
var store = localServer.openStore(this.storeName) ||
localServer.createStore(this.storeName);
store.capture(pageFiles, function(url, success, captureId) {
console.log(url + ' capture ' + (success ? 'succeeded' : 'failed'));
});

ManagedResourceStore – Capture entire applications

• List application resources in a separate manifest
• Gears captures and updates the list atomically
• Gears auto-updates automatically on each view (within reason)
• Supports multiple users per application

Sample Code

var localserver = google.gears.factory.create('beta.localserver', '1.0');
var store = localserver.createManagedStore('mystore');
store.manifestUrl = 'http://myapp.com/offline-manifest.json';
store.checkForUpdates();

JSON Me

{
// version of the manifest file format
"betaManifestVersion": 1,
// version of the set of resources described in this manifest file
"version": "my_version_string",
// optional
// If the store specifies a requiredCookie, when a request would hit
// an entry contained in the manifest except the requiredCookie is
// not present, the local server responds with a redirect to this URL.
"redirectUrl": "login.html",
// URLs to be cached (URLs are given relative to the manifest URL)
"entries": [
{ "url": "main.html", "src": "main_offline.html" },
{ "url": ".", "redirect": "main.html" },
{ "url": "main.js" }
{ "url": "formHandler.html", "ignoreQuery": true },
]
}

Gears Manifest Generator – Ruby Me

json = Google::Gears::LocalServer::Manifest.new do |m|
m.version = 'MyNewVer'
m.add_entry({ :url => 'main.html', :src => 'foo.html' })
m.add_extra_info :to => 'main.html', :redirect => 'foo_redirect.html'
m.find_entries :in => '.', :ignore =>
Google::Gears::LocalServer::Manifest::LEADING_PERIOD
end

HTML 5 – Offline in General


There’s a concept of an application cache. An application cache is a group of resources, the group being identified by a URI (which typically happens to resolve to a manifest). Resources in a cache are either top-level or not; top-level resources are those that are HTML or XML and when parsed with scripting disabled have with the value of the attribute pointing to the same URI as identifies the cache.

When you visit a page you first check to see if you have that page in a cache as a known top-level page.

Worker Pool – JavaScript needs threads after all?

Run JavaScript in the background

• Provides thread-like functionality to JavaScript
• No more blocking the browser UI
• Communication is via IPC, no shared state or threading primitives

Worker Pool Code

function nextPrime(n) {
// TODO: New top-secret prime-finding algorithm goes here.
google.gears.workerPool.sendMessage(result);
}
var pool = google.gears.factory.create('beta.workerpool', '1.0');
pool.onmessage = function(message) {
alert('next prime is: ' + message);
}
var worker = pool.createWorker(String(nextPrime) + '; nextPrime()');

Worker Pool Improved!
• Cross-origin API allows Gears apps from different sites to work together
• WorkerPool improvements:
• createWorkerFromUrl()
• onerror allows handling exceptions thrown by workers
• New HttpRequest module allows fetching from WorkerPools
• New Timer module allows timer events in WorkerPools
• Implements the WhatWG Timer specification

var timer = google.gears.factory.create("beta.timer", "1.0");
timer.setTimeout(function() { alert("Hello, from the future!"); },1000);

How about Encryption?

dojox.sql("INSERT INTO CUSTOMERS VALUES (?, ?, ENCRYPT(?))", "Google", "Gear", "123-4561")

The Digg Oracle

Full Text Search

• Gears added FTS2 to SQLite
• Create the database db.execute(‘CREATE VIRTUAL TABLE recipe USING fts2(dish, ingredients)’);
• Search the database db.execute(‘SELECT dish FROM recipe WHERE recipe MATCH ?’, [‘tomatoes’]);
Fun queries: dish:stew tomatoes
Find rows with ‘stew’ in the dish field, and ‘tomatoes’ in any field.

What didn’t you see here?
Sync, sync, sync

Syncing is hard

• Read only, small data
• Read write, small data
• Read only, huge data
• Read write, huge data

Offline UI

When to ask for user input?

Working with and without Gears

content = hasGears() ? new GearsBaseContent() : new CookieBaseContent();

Two Versions? Really? – Only in the extreme

{
‘url’: ‘main.html’,
‘src’: ‘main_offline.html’
}

Debugging is a Pain ?

• Add Helper Code
• To clear out the DB
• Remove captured files
• Disable the cache
• Use Firebug / Lite

GearsBaseContent.prototype.clearServer = function() {
if (this.localServer.openStore(this.storeName)) {
this.localServer.removeStore(this.storeName);
this.store = null;
}
}
GearsBaseContent.prototype.clearTables = function() {
if (this.db) {
this.db.run('delete from BaseQueries');
this.db.run('delete from BaseFeeds');
}
displayQueries();
}

DOJO Offline – small. easy. open.

content = hasGears() ? new GearsBaseContent() : new CookieBaseContent();

GWT and Gears

try {
db = new Database("database-demo");
db.execute("create table if not exists Demo (Phrase varchar(255), Timestamp int)");
} catch (GearsException e) { ... }
button.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
try {
String phrase = input.getText();
if (phrase.length() > 0) {
db.execute("insert into Demo values (?, ?)", new String[] {
phrase, Integer.toString((int) System.currentTimeMillis())});
displayRecentPhrases();
}
} catch (DatabaseException e) {
Window.alert(e.toString());
}
}
});

 
Leave a comment

Posted by on October 6, 2008 in Google Gears

 

Tags: , , , , , , , , , , , , ,

Going Offline With GWT and Gears

Why?

Web apps are great …if you can connect

•Planes

•Trains

•Automobiles

•Users may not want their data in the cloud

•Increase response time for online apps

How?

GWT – Google Web Toolkit

Google Gears

s

  • Browser Plugin (FireFox, Internet Explorer)
  • http://gears.google.com
  • Features:
    LocalServer (“programmable cache”)
    SQLite Database
    Worker Threads for JavaScript

Take Your App Offline

  1. Manifest file of your app’s resources
  2. Download resources
  3. Create database schema
  4. Go

Manifest File

Load Resources

LocalServer localServer = new LocalServer();ManagedResourceStore managedRS =
localServer.createManagedResourceStore(“CompanyApp”);
managedRS.setManifestURL(“http://company.com/manifest.json”);
managedR.checkForUpdate();
new Timer() {
public void run() {
switch (managedResourceStore.getUpdateStatus()) {
case ManagedResourceStore.UPDATE_OK:
statusLabel.setText(“Ready for offline access”);
break;
case ManagedResourceStore.UPDATE_CHECKING:
case ManagedResourceStore.UPDATE_DOWNLOADING:
schedule(500);
break;
case ManagedResourceStore.UPDATE_FAILED:
statusLabel.setText(“Unable to go offline);
break;
} } }.schedule(500);

Gears Database

Create Database

  • “create table if not exists person (id integer, first_name text, last_name text)”
  • Datatypes: Integer, Real, Text, Blob
  • Constraints: “primary key”, “not null”, “unique”, etc.

private Database m_database = null;try {
m_database = new Database(“Test”);
ResultSet rs = m_database.execute(“create table…”);
rs.close();
} // try
catch (Exception e) {
// Gears not installed
} // catch

Queries

String sql = “select id, first_name, last_name  from person”;
ResultSet rs = m_database.execute(sql);
ArrayList results = new ArrayList();
while (rs.isValidRow()) {
PersonBean person = new PersonBean();
person.setID(rs.getFieldAsInt(0));
person.setFirstName(rs.getFieldAsString(1));
person.setLastName(rs.getFieldAsString(2));
results.add(person);
rs.next();
} // while
rs.close();

Insert, Update

String args[] = new String[3];
args[0] = Integer.toString(person.getID());
args[1] = person.getFirstName();
args[2] = person.getLastName();ResultSet rs = m_database.execute(“insert into person
(id, first_name, last_name) values (?,?,?)”, args);
rs.close();args = new String[3];
args[0] = person.getFirstName();
args[1] = person.getLastName();args[2] = Integer.toString(person.getID());
rs = m_database.execute(“update person set
first_name=?, last_name=? where id=?)”, args);
rs.close();

Demo Source Code

Syncing Issues

  • Need GUIDs
  • Need timestamps (SQLite has no Date)
  • Need a strategy:
    Last one wins
    Lock / Check out
    Let user decide

Conclusion

Google Gears allows web applications to run offline
Google Web Toolkit makes it easy to program Gears

 
Leave a comment

Posted by on September 25, 2008 in Google Gears

 

Tags:

Google Gears Tutorial

About:

This tutorial introduces you to Google Gears. I tried the tutorial in the Developers Guide and thought it could be simplified. So here is a very simple tutorial for the Google Gears.

Day by day, web applications try to replace the desktop applications. The power of web applications lies in the availability (you are no longer tied to a particular PC), portability(any hardware/any OS) and simplicity (simple navigation model – links, back, forward). But the problem with these online applications is that, well, they are available only online. Once you are disconnected from the internet, those applications are inaccessible.

Think of your mail client like Outlook or Thunderbird. They do need a network connection to receive and send the mails, but even when you are not connected to the network, you can read the locally stored mails. You can compose new mails, they are saved locally and when you connect to a network, they silently send them. Can we bring this kind of off-line functionality to an online application? Yes. Welcome to Google Gears. The off-line web application is no more an oxymoron. Its a practical reality.

How does this work?

To start with, you need an online page.
The online page should present the user to switch to off line mode.
When the user selects to off line mode, the online page should download the required files and save it locally.
Even when there is no internet connection, the user will be able to do the operations with the local files.
Once the user goes online, the data that is modified will be synced with the server.

This sounds so simple. But the devil is in the details. Let us explore each step in detail.

First is the online page. Lets have the online.html as the initial page. On clicking the “Go Offline” button, we download this page and store it locally. This is done by this javascript:

localServer = google.gears.factory.create(“beta.localserver”);
store = localServer.createManagedStore(“first_offline_web_app”);
store.manifestUrl = manifest.json;
store.checkForUpdate();

The first line, we create an instance of LocalServer from the Google Gears factory. When you are in offline mode, LocalServer serves your HTTP requests. The contents are stored either in ResourceStore or in ManagedResourceStore. The former is used to store the not-so-frequently-updated resources like images. The latter is used to store a group of resources that might change frequently. Google Gears will automatically retrieve and update the local cache. The contents of a ManagedResourceStore is defined by a manifest file, which we set in line no 3. The checkForUpdate method in the ManagedResourceStore will initiate the update task and return immediately. The update task which will run the background will:
Get the manifest file from the URL
Compare the version number in the locally stored version
If they are different then fetch the contents specified in the manifest
For each URL, IfModifiedSince will be requested. If the URL gives a newer timestamp than the previous one, then the contents will be requested
Once all the URLs are fetched and saved, the version number of the local files are updated with the latest one

A point to note is that Google Gears will go and fetch the latest version if its DIFFERENT from the local one. So if the local version is “Version 5.9″ and the remote version is “Version 4.0″, the local cache will still be updated.

Everything looks fine now. One last thing to do is to install Google Gears :-)

Google Gears is a plugin for Firefox. Every URL request goes thru this plugin. Whenever there is a LocalServer available for the URL and its active, then the contents will be fetched locally. Else the normal behavior of fetching from the network will resume.

To detect whether Google Gears has been installed and to access its API, we need to include the gears_init.js file in the HTML.

 
Leave a comment

Posted by on September 25, 2008 in Google Gears

 

Tags:

 
Follow

Get every new post delivered to your Inbox.

%d bloggers like this: