SlideShare a Scribd company logo
Mobile, Web and Cloud -
The Triple Crown of Modern Applications
Ido Green, Developer Advocate
Danny Hermes, Developer Programs Engineer
Modern Mobile/Web Applications
Modern Applications
● Self Contained
● "Offline First"
● MV* Frameworks
● Device Aware
● #Perfmatters
#io13
AngularJS - Client Side Framework
Angular.js - Let you extend HTML
vocabulary for your application.
● Data binding
● Extensible HTML
● Dependency Injection / Testable
#io13
More options: addyosmani.github.com/todomvc/
Mobile World - RESTful World
#io13
Photos
● GET http://ex.com/_ah/api/picturesque/v1/photos
● POST http://ex.com/_ah/api/picturesque/v1/photo
● PATCH http://ex.com/_ah/api/picturesque/v1/photo/id
Users
● POST http://ex.com/_ah/api/picturesque/v1/users/join
And more...
● Performance! #Perfmatters
● Flaky connections (e.g. cafes, car)
● Airplane, road trip, deserted island
● Consolidates the concept of permanent application.
* We will use: Lawnchair for our demo.
Offline - Why?
#io13
● Storing assets: AppCache
● Storing data: localStorage, IndexedDB, File API.
● Offline first:
○ Pretend that there's no internet connection
○ Implement a sync layer that works only when
online.
Offline - How?
navigator.onLine & window.(ononline|onoffline)
#io13
Google Cloud Endpoints
Modern Apps and The Server Conundrum
All modern applications have to deal with a server
○ Offload Computation
○ Sharing and Collaboration
○ Logs
But who wants to run a server
○ Spikey traffic
○ Client Server communication
○ Serialization
○ OAuth Dance
#io13
Google App Engine
#io13
Google App Engine
#io13
Google Cloud Endpoints
#io13
Back the Truck Up
#io13
Google APIs: The Discovery Document
#io13
Google APIs: Client Libraries Like Whoa!!
● Web
○ JavaScript: google-api-javascript-client
○ Node.js: google-api-nodejs-client
○ Dart: google-api-dart-client
● Mobile
○ Objective C: google-api-objectivec-client
○ Java: google-api-java-client
● Server-side
○ Ruby: google-api-ruby-client
○ Python: google-api-python-client
○ Go: google-api-go-client
○ PHP: google-api-php-client
○ .NET: google-api-dotnet-client
○ GWT: gwt-google-apis
#io13
Google APIs
Client Libraries Like Whoa!!
HTML
<body>
...
<script type="text/javascript">
function init() {
gapi.client.load(‘urlshortener’, 'v1’, function() {});
}
</script>
<script src="https://apis.google.com/js/client.js?onload=init"></script>
</body>
What Was that Again: Google Cloud Endpoints
#io13
Demo Time!
picturesque-app.appspot.com
Data Model for CRUD App
Python
from endpoints_proto_datastore.ndb import EndpointsModel
class Photo(EndpointsModel):
...
Data Model for CRUD App
Python
from endpoints_proto_datastore.ndb import EndpointsModel
class Photo(EndpointsModel):
title = ndb.StringProperty()
Data Model for CRUD App
Python
from endpoints_proto_datastore.ndb import EndpointsModel
class Photo(EndpointsModel):
title = ndb.StringProperty()
description = ndb.StringProperty()
Data Model for CRUD App
Python
from endpoints_proto_datastore.ndb import EndpointsModel
class Photo(EndpointsModel):
title = ndb.StringProperty()
description = ndb.StringProperty()
base64_photo = ndb.BlobProperty('base64Photo', indexed=False)
Data Model for CRUD App
Python
from endpoints_proto_datastore.ndb import EndpointsModel
class Photo(EndpointsModel):
title = ndb.StringProperty()
description = ndb.StringProperty()
base64_photo = ndb.BlobProperty('base64Photo', indexed=False)
updated = ndb.DateTimeProperty(auto_now=True, indexed=False)
Data Model for CRUD App
Python
from endpoints_proto_datastore.ndb import EndpointsModel
class Photo(EndpointsModel):
_message_fields_schema = ('id', 'title', 'description',
'base64Photo', 'updated')
title = ndb.StringProperty()
description = ndb.StringProperty()
base64_photo = ndb.BlobProperty('base64Photo', indexed=False)
updated = ndb.DateTimeProperty(auto_now=True, indexed=False)
Simple GET API Request
Using Data Model for Insert
Python
@endpoints.api(name='picturesque', version='v1',
description='Photos API for Picturesque App')
class PicturesqueApi(remote.Service):
@Photo.method(path='photo', name='photo.insert')
def PhotoInsert(self, photo):
# do some validation
photo.put()
return photo
Insert With Drag and Drop Demo
Python
Update
Python
@Photo.method(path='photo/{id}', http_method='PUT', name='photo.update')
def PhotoUpdate(self, photo):
if not photo.from_datastore:
raise endpoints.NotFoundException('Photo not found.')
photo.put()
return photo
Update Demo
Python
Add some tags to support that UI
Python
class Photo(EndpointsModel):
title = ndb.StringProperty()
description = ndb.StringProperty()
base64_photo = ndb.BlobProperty('base64Photo', indexed=False)
created = ndb.DateTimeProperty(auto_now_add=True, indexed=False)
tags = ndb.StringProperty(repeated=True)
List and Search, All at Once
Python
@Photo.query_method(query_fields=('limit', 'pageToken', 'title'),
path='photos', name='photo.list')
def PhotoList(self, query):
return query
List Demo - Get Photos Baby!
Python
var req = gapi.client.picturesque.photo.list();
req.execute(function(data) {
data.items = data.items || [];
console.log("-- We have " + data.items.length);
addPhotos(data.items);
});
Lemme, Lemme Upgrade U!
picturesque-app-upgrade.appspot.com
Adding auth via OAuth 2.0
Python
@Photo.method(user_required=True,
path='photo/{id}', http_method='PUT', name='photo.update')
def PhotoUpdate(self, photo):
...
Really that easy
Adding auth via OAuth 2.0
Python
from endpoints_proto_datastore.ndb import EndpointsUserProperty
class Photo(EndpointsModel):
_message_fields_schema = ('id', 'title', 'description',
'base64Photo', 'updated'
title = ndb.StringProperty()
description = ndb.StringProperty()
base64_photo = ndb.BlobProperty('base64Photo', indexed=False)
updated = ndb.DateTimeProperty(auto_now_add=True, indexed=False)
owner = EndpointsUserProperty(required=True, raise_unauthorized=True)
Alternative: Using models for auth
OAuth2.0 Demo - 1
Python
The
live
demo
Interface Informed by Client
● Network calls are expensive
● "Client" photo library
○ Lawnchair allows us to store photos' metadata offline
○ filer.js to store the photos
○ Application Cache
○ HTML5 Storage
● DRY: Applies to code and to API calls
○ Only retrieve photos that have been updated since the last
API call
Extending query_method
Python
from endpoints_proto_datastore.ndb import EndpointsAliasProperty
from endpoints_proto_datastore import utils
class Photo(EndpointsModel):
...
_last_updated = None
@EndpointsAliasProperty(name='lastUpdated', setter=LastUpdatedSet)
def last_updated(self):
if self._last_updated is not None:
try:
return utils.DatetimeValueToString(self._last_updated)
except:
raise endpoints.BadRequestException(
'Invalid timestamp for lastUpdated')
Extending query_method
Python
class Photo(EndpointsModel):
...
def LastUpdatedSet(self, value):
try:
self._last_updated = utils.DatetimeValueFromString(value)
if not isinstance(self._last_updated, datetime.datetime):
self._last_updated = None
raise TypeError('Not a datetime stamp.')
except TypeError:
raise endpoints.BadRequestException('Invalid timestamp for lastUpdated.')
self._endpoints_query_info._filters.add(
Photo.updated >= self._last_updated)
Extending query_method
Python
@Photo.query_method(query_fields=('limit', 'pageToken',
'title', 'lastUpdated'),
path='photos', name='photo.list')
def PhotoList(self, query):
return query.order(Photo.updated)
Client Side Conventions
Javascript
PicturesqueApp.showCarousel = function() {
if (!PicturesqueApp.localImagesAdded) {
PicturesqueApp.populateCarouselFromLocalImages();
};
PicturesqueApp.applyLastUpdated(PicturesqueApp.listSinceUpdated);
};
Key Take Aways
● Build powerful applications with Google Cloud Endpoints
● Cloud Endpoints makes for easy deployment at scale
● Use AngularJS to be more productive
● Leverage Modern Browser Features:
○ Offline
○ Web RTC
○ Websockets
○ New CSS3 artifacts
○ Web workers
#io13
Questions?
Ido Green
Developer Relations
http://plus.google.com/+greenido
App:: https://picturesque-app-upgrade.appspot.com/
Code: https://github.com/greenido/
Slides: https://picturesque-app-upgrade.appspot.com/slides
Danny Hermes
Developer Programs Engineer
plus.google.com/+DannyHermes

More Related Content

Mobile, web and cloud - the triple crown of modern applications

  • 1. Mobile, Web and Cloud - The Triple Crown of Modern Applications Ido Green, Developer Advocate Danny Hermes, Developer Programs Engineer
  • 3. Modern Applications ● Self Contained ● "Offline First" ● MV* Frameworks ● Device Aware ● #Perfmatters #io13
  • 4. AngularJS - Client Side Framework Angular.js - Let you extend HTML vocabulary for your application. ● Data binding ● Extensible HTML ● Dependency Injection / Testable #io13 More options: addyosmani.github.com/todomvc/
  • 5. Mobile World - RESTful World #io13 Photos ● GET http://ex.com/_ah/api/picturesque/v1/photos ● POST http://ex.com/_ah/api/picturesque/v1/photo ● PATCH http://ex.com/_ah/api/picturesque/v1/photo/id Users ● POST http://ex.com/_ah/api/picturesque/v1/users/join And more...
  • 6. ● Performance! #Perfmatters ● Flaky connections (e.g. cafes, car) ● Airplane, road trip, deserted island ● Consolidates the concept of permanent application. * We will use: Lawnchair for our demo. Offline - Why? #io13
  • 7. ● Storing assets: AppCache ● Storing data: localStorage, IndexedDB, File API. ● Offline first: ○ Pretend that there's no internet connection ○ Implement a sync layer that works only when online. Offline - How? navigator.onLine & window.(ononline|onoffline) #io13
  • 9. Modern Apps and The Server Conundrum All modern applications have to deal with a server ○ Offload Computation ○ Sharing and Collaboration ○ Logs But who wants to run a server ○ Spikey traffic ○ Client Server communication ○ Serialization ○ OAuth Dance #io13
  • 13. Back the Truck Up #io13
  • 14. Google APIs: The Discovery Document #io13
  • 15. Google APIs: Client Libraries Like Whoa!! ● Web ○ JavaScript: google-api-javascript-client ○ Node.js: google-api-nodejs-client ○ Dart: google-api-dart-client ● Mobile ○ Objective C: google-api-objectivec-client ○ Java: google-api-java-client ● Server-side ○ Ruby: google-api-ruby-client ○ Python: google-api-python-client ○ Go: google-api-go-client ○ PHP: google-api-php-client ○ .NET: google-api-dotnet-client ○ GWT: gwt-google-apis #io13
  • 16. Google APIs Client Libraries Like Whoa!! HTML <body> ... <script type="text/javascript"> function init() { gapi.client.load(‘urlshortener’, 'v1’, function() {}); } </script> <script src="https://apis.google.com/js/client.js?onload=init"></script> </body>
  • 17. What Was that Again: Google Cloud Endpoints #io13
  • 19. Data Model for CRUD App Python from endpoints_proto_datastore.ndb import EndpointsModel class Photo(EndpointsModel): ...
  • 20. Data Model for CRUD App Python from endpoints_proto_datastore.ndb import EndpointsModel class Photo(EndpointsModel): title = ndb.StringProperty()
  • 21. Data Model for CRUD App Python from endpoints_proto_datastore.ndb import EndpointsModel class Photo(EndpointsModel): title = ndb.StringProperty() description = ndb.StringProperty()
  • 22. Data Model for CRUD App Python from endpoints_proto_datastore.ndb import EndpointsModel class Photo(EndpointsModel): title = ndb.StringProperty() description = ndb.StringProperty() base64_photo = ndb.BlobProperty('base64Photo', indexed=False)
  • 23. Data Model for CRUD App Python from endpoints_proto_datastore.ndb import EndpointsModel class Photo(EndpointsModel): title = ndb.StringProperty() description = ndb.StringProperty() base64_photo = ndb.BlobProperty('base64Photo', indexed=False) updated = ndb.DateTimeProperty(auto_now=True, indexed=False)
  • 24. Data Model for CRUD App Python from endpoints_proto_datastore.ndb import EndpointsModel class Photo(EndpointsModel): _message_fields_schema = ('id', 'title', 'description', 'base64Photo', 'updated') title = ndb.StringProperty() description = ndb.StringProperty() base64_photo = ndb.BlobProperty('base64Photo', indexed=False) updated = ndb.DateTimeProperty(auto_now=True, indexed=False)
  • 25. Simple GET API Request
  • 26. Using Data Model for Insert Python @endpoints.api(name='picturesque', version='v1', description='Photos API for Picturesque App') class PicturesqueApi(remote.Service): @Photo.method(path='photo', name='photo.insert') def PhotoInsert(self, photo): # do some validation photo.put() return photo
  • 27. Insert With Drag and Drop Demo Python
  • 28. Update Python @Photo.method(path='photo/{id}', http_method='PUT', name='photo.update') def PhotoUpdate(self, photo): if not photo.from_datastore: raise endpoints.NotFoundException('Photo not found.') photo.put() return photo
  • 30. Add some tags to support that UI Python class Photo(EndpointsModel): title = ndb.StringProperty() description = ndb.StringProperty() base64_photo = ndb.BlobProperty('base64Photo', indexed=False) created = ndb.DateTimeProperty(auto_now_add=True, indexed=False) tags = ndb.StringProperty(repeated=True)
  • 31. List and Search, All at Once Python @Photo.query_method(query_fields=('limit', 'pageToken', 'title'), path='photos', name='photo.list') def PhotoList(self, query): return query
  • 32. List Demo - Get Photos Baby! Python var req = gapi.client.picturesque.photo.list(); req.execute(function(data) { data.items = data.items || []; console.log("-- We have " + data.items.length); addPhotos(data.items); });
  • 33. Lemme, Lemme Upgrade U! picturesque-app-upgrade.appspot.com
  • 34. Adding auth via OAuth 2.0 Python @Photo.method(user_required=True, path='photo/{id}', http_method='PUT', name='photo.update') def PhotoUpdate(self, photo): ... Really that easy
  • 35. Adding auth via OAuth 2.0 Python from endpoints_proto_datastore.ndb import EndpointsUserProperty class Photo(EndpointsModel): _message_fields_schema = ('id', 'title', 'description', 'base64Photo', 'updated' title = ndb.StringProperty() description = ndb.StringProperty() base64_photo = ndb.BlobProperty('base64Photo', indexed=False) updated = ndb.DateTimeProperty(auto_now_add=True, indexed=False) owner = EndpointsUserProperty(required=True, raise_unauthorized=True) Alternative: Using models for auth
  • 36. OAuth2.0 Demo - 1 Python The live demo
  • 37. Interface Informed by Client ● Network calls are expensive ● "Client" photo library ○ Lawnchair allows us to store photos' metadata offline ○ filer.js to store the photos ○ Application Cache ○ HTML5 Storage ● DRY: Applies to code and to API calls ○ Only retrieve photos that have been updated since the last API call
  • 38. Extending query_method Python from endpoints_proto_datastore.ndb import EndpointsAliasProperty from endpoints_proto_datastore import utils class Photo(EndpointsModel): ... _last_updated = None @EndpointsAliasProperty(name='lastUpdated', setter=LastUpdatedSet) def last_updated(self): if self._last_updated is not None: try: return utils.DatetimeValueToString(self._last_updated) except: raise endpoints.BadRequestException( 'Invalid timestamp for lastUpdated')
  • 39. Extending query_method Python class Photo(EndpointsModel): ... def LastUpdatedSet(self, value): try: self._last_updated = utils.DatetimeValueFromString(value) if not isinstance(self._last_updated, datetime.datetime): self._last_updated = None raise TypeError('Not a datetime stamp.') except TypeError: raise endpoints.BadRequestException('Invalid timestamp for lastUpdated.') self._endpoints_query_info._filters.add( Photo.updated >= self._last_updated)
  • 40. Extending query_method Python @Photo.query_method(query_fields=('limit', 'pageToken', 'title', 'lastUpdated'), path='photos', name='photo.list') def PhotoList(self, query): return query.order(Photo.updated)
  • 41. Client Side Conventions Javascript PicturesqueApp.showCarousel = function() { if (!PicturesqueApp.localImagesAdded) { PicturesqueApp.populateCarouselFromLocalImages(); }; PicturesqueApp.applyLastUpdated(PicturesqueApp.listSinceUpdated); };
  • 42. Key Take Aways ● Build powerful applications with Google Cloud Endpoints ● Cloud Endpoints makes for easy deployment at scale ● Use AngularJS to be more productive ● Leverage Modern Browser Features: ○ Offline ○ Web RTC ○ Websockets ○ New CSS3 artifacts ○ Web workers #io13
  • 43. Questions? Ido Green Developer Relations http://plus.google.com/+greenido App:: https://picturesque-app-upgrade.appspot.com/ Code: https://github.com/greenido/ Slides: https://picturesque-app-upgrade.appspot.com/slides Danny Hermes Developer Programs Engineer plus.google.com/+DannyHermes