developing applications with cloud services #javaone 2012
DESCRIPTION
Cloud computing isn't just about application deployment. There are also a growing number of cloud-based web services that you can use to develop your application. One of the most well known is Amazon's Simple Storage Service. But there are many others including web services for messaging, relational and NoSQL databases, email and telephony. Using these services allows you to build highly scalable applications without the pain and cost of having to develop and operate your own infrastructure. In this presentation, you will learn about the benefits and drawbacks of these Web services; their typical use cases and how to use them. We will describe a location aware, telephony application that is built using cloud services. You will learn about strategies for building resilient, fault tolerant applications that consume cloud services.TRANSCRIPT
![Page 1: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/1.jpg)
DEVELOPING WITH CLOUD SERVICESChris Richardson
Author of POJOs in ActionFounder of the original CloudFoundry.com
@[email protected]://plainoldobjects.com/
![Page 2: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/2.jpg)
Presentation goal
How to build robust, scalable applications with
Cloud Services
![Page 3: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/3.jpg)
About Chris
![Page 4: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/4.jpg)
(About Chris)
![Page 5: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/5.jpg)
About Chris()
![Page 6: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/6.jpg)
About Chris
![Page 7: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/7.jpg)
About Chris
http://www.theregister.co.uk/2009/08/19/springsource_cloud_foundry/
![Page 8: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/8.jpg)
vmc push About-Chris
Developer Advocate for CloudFoundry.com
Signup at http://cloudfoundry.compromo code: cfjavaone
![Page 9: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/9.jpg)
Agenda
• Why use cloud services?
• Developing location-based applications
• Building SMS and telephony enabled applications
• Developing robust, fault tolerant applications
![Page 10: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/10.jpg)
Three phases of every galactic civilization
Survival
Inquiry
Sophistication
![Page 11: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/11.jpg)
Three phases of every galactic civilization
How
Why
Where
can we eat?
do we eat?
Where shall we have lunch?
![Page 12: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/12.jpg)
Where shall we have lunch?
Solved by VoteMeetEat.com
![Page 13: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/13.jpg)
VoteMeetEat.com
•What restaurants are nearby?•Which friends are close by? •Where do your friends prefer to eat?
To sign up text "register" to 510-555-????
![Page 14: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/14.jpg)
VoteMeetEat.com
Restaurant database +
SMS +
Voice callsTo sign up text
"register" to 510-555-????
![Page 15: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/15.jpg)
Key story: registration
5551212
![Page 16: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/16.jpg)
Key story: registration
+5105551212
![Page 17: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/17.jpg)
Key story: voting
555 1212
![Page 18: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/18.jpg)
Key story: announce location
![Page 19: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/19.jpg)
VOTEMEETEAT.COM
To sign up text "register" to 510-555-????
![Page 20: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/20.jpg)
High-level architecture
VoteMeetEat
TelephonyIntegration
Friend GeoDatabase
Restaurant Database
MobilePhone
Do we really want to build all this?
DIY = DIFFICULT
![Page 21: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/21.jpg)
Use cloud-based services
• Highly scalable services
• Someone else’s headache to develop and maintain
• Provided by IaaS/PaaS
• Provided by 3rd party
![Page 22: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/22.jpg)
Cloud Foundry services
![Page 23: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/23.jpg)
Thousands of 3rd party services
http://www.programmableweb.com/apis/directory
http://www.slideshare.net/jmusser/j-musser-apishotnotgluecon2012
![Page 24: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/24.jpg)
• Predominantly REST
• Predominantly JSON
• > billion API calls/day: Twitter, Google, Facebook, Netflix, Accuweather, ...
• Increasing number of API-only companies
http://www.slideshare.net/jmusser/j-musser-apishotnotgluecon2012
Cloud service trends
![Page 25: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/25.jpg)
Diverse
![Page 26: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/26.jpg)
Benefits of cloud services
• Someone else’s headache to develop and operate
• Focus on your core business problem
• Get up and running quickly
• Elasticity
• Capex ⇒ Opex
![Page 27: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/27.jpg)
Drawbacks of cloud services
• Complexity and drawbacks of a distributed system
• You are dependent on service provider
![Page 28: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/28.jpg)
Risks of cloud services
Urban Airship’s Strategic Partnership With SimpleGeo Turns Into An Acquisition
![Page 29: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/29.jpg)
Cloud Services-based architecture
VoteMeetEat
TwilioMongoDB
Factual.Com
MobilePhone
![Page 30: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/30.jpg)
DEMO
![Page 31: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/31.jpg)
Agenda
• Why use cloud services?
• Developing location-based applications
• Building SMS and telephony enabled applications
• Developing robust, fault tolerant applications
![Page 32: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/32.jpg)
Location-based services are hot!
![Page 33: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/33.jpg)
![Page 34: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/34.jpg)
Client-side APIs for finding location
W3C Geolocation API
![Page 35: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/35.jpg)
BUT what about the server-side?
![Page 36: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/36.jpg)
Lots of really difficult problems
•Scalable, spatial database – CRUD records, find nearby•Data management – database of places, street information•Forward geo-coding: address ⇒ lat/lon
•Reverse geo-coding: lat/lon ⇒ address
•Maps•Directions
Easier to use Geo-aaS
![Page 37: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/37.jpg)
Examples of Geo-aaS
Beware the terms of service
• Maps• Forward and reverse geocoding• Directions• Elevation• Places
• Freely available geographic database
• Various APIs including reverse geocoding
• Business+review database• Neighborhood database
• Places database• Reverse geocoding
![Page 38: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/38.jpg)
VOTEMEETEAT & Geo
trait FriendService { def addOrUpdate(request : AddOrUpdateUserRequest) def findNearbyFriends(request : NearbyFriendsRequest) :
FindNearbyFriendsResponse}
trait RestaurantService { def findNearbyRestaurants(location: Location) :
FindNearbyRestaurantResponse}
![Page 39: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/39.jpg)
Implementing the friends database
![Page 40: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/40.jpg)
MongoDB
• Document-oriented database
• Very fast, highly scalable and available
• Rich query language that supports location-based queries
• Provided by CloudFoundry.com
![Page 41: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/41.jpg)
MongoDB server
Database: VoteMeetEatCollection: friendRecord
Storing friends in MongoDB
{ "_id": "+15105551212", "name": "Chris R.", "location": { "x": -122.25206103187264, "y": 37.847427441773796 }}
![Page 42: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/42.jpg)
Spring Data for MongoDB
• Provides MongoTemplate
• Analogous to JdbcTemplate
• Hides boilerplate code
• Domain object ↔ Document mapping
![Page 43: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/43.jpg)
Using Spring data: creating an index on location attribute
@Componentclass MongoFriendService extends FriendService {
@Autowired var mongoTemplate: MongoTemplate = _
@PostConstruct def createGeoIndex { val dbo = new BasicDBObject dbo.put("location", "2d") mongoTemplate.getCollection("friendRecord").ensureIndex(dbo) }
Create geospatial 2d index
Collection name
![Page 44: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/44.jpg)
Using Spring Data: adding record@Componentclass MongoFriendService extends FriendService {
override def addOrUpdate(request: AddOrUpdateUserRequest) = { val name = request.name val phoneNumber = request.phoneNumber val fr = new FriendRecord(phoneNumber, name, new Point(request.longitude, request.latitude)) mongoTemplate.save(fr) }
case class FriendRecord(id : String, name : String, location : Point)
![Page 45: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/45.jpg)
Using Spring Data: finding nearby friends
@Componentclass MongoFriendService extends FriendService {
override def findNearbyFriends(request: NearbyFriendsRequest) = { val location = new Point(request.longitude, request.latitude) val distance = new Distance(3, Metrics.MILES) val query = NearQuery.near(location).maxDistance(distance) val result = mongoTemplate.geoNear(query, classOf[FriendRecord])
val nearby = result.getContent.map(_.getContent) FindNearbyFriendsResponse(nearby.map(f => FriendInfo(f.name, f.id))) }
![Page 46: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/46.jpg)
MongoDB and Cloud Foundry
$ vmc create-service mongodb vme-mongo
![Page 47: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/47.jpg)
$ vmc push vme-user --path web/target/Application Deployed URL [cer-spring.cloudfoundry.com]: Detected a Java SpringSource Spring Application, is this correct? [Yn]: Memory Reservation (64M, 128M, 256M, 512M, 1G) [512M]:
Creating Application: OKWould you like to bind any services to 'vme-user'? [yN]: y
Would you like to use an existing provisioned service? [yN]: yThe following provisioned services are available
1: vme-mongo2: mysql-135e0Please select one you wish to use: 1
Binding Service [vme-mongo]: OKUploading Application:
Checking for available resources: OK Processing resources: OK
Packing application: OK Uploading (12K): OK
Push Status: OK
Binding a service to an application
Would you like to bind any services to 'vme-user'? [yN]: yWould you like to use an existing provisioned service? [yN]: yThe following provisioned services are available1: vme-mongo2: mysql-135e0Please select one you wish to use: 1Binding Service [vme-mongo]: OK
![Page 48: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/48.jpg)
Connecting to MongoDB <bean id="mongoTemplate"
class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg ref="mongoFactory" /> </bean>
<beans profile="default"> <mongo:db-factory id="mongoFactory" dbname="surveygeo" /> </beans>
<beans profile="cloud"> <cloud:mongo-db-factory id="mongoFactory" /> </beans>
Outside of Cloud Foundry
Inside Cloud Foundry
![Page 49: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/49.jpg)
Implementing the restaurant database
![Page 50: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/50.jpg)
Using Factual
• Geographic database as a Service
• Including 800,000 restaurants in the US
• Pricing: 10K calls day free, pay per use
![Page 51: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/51.jpg)
Factual API
• RESTful/JSON interface
• Uses 2-legged OAuth 1.0.
• Geo and text filters
• Pagination
• Libraries for various languages
![Page 52: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/52.jpg)
Restaurant Service@Serviceclass FactualRestaurantService extends RestaurantService {
@Value("${factual_consumer_key}") var consumerKey: String = _ @Value("${factual_consumer_secret}") var consumerSecret: String = _
var factual: ThreadLocal[Factual] = _
@PostConstruct def initialize { factual = new ThreadLocal[Factual] { override def initialValue() = new Factual(consumerKey, consumerSecret, true) } }
override def findNearbyRestaurants(location: Location) = { val restaurants = factual.get.fetch("restaurants-us", new Query().within(new Circle(location.lat, location.lon, 1000)).limit(5))
val rs = for (map <- restaurants.getData) yield { RestaurantInfo(map.get("name").asInstanceOf[String]) }
FindNearbyRestaurantResponse(rs.toList)
}...
Not thread-safe
5 restaurants within 1km
![Page 53: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/53.jpg)
Agenda
• Why use cloud services?
• Developing location-based applications
• Building SMS and telephony enabled applications
• Developing robust, fault tolerant applications
![Page 54: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/54.jpg)
The telephony and SMS are important
http://blog.nielsen.com/nielsenwire/online_mobile/new-mobile-obsession-u-s-teens-triple-data-usage/
7/ waking hr !
Nielsen
![Page 55: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/55.jpg)
Reporting traffic light problems in London
![Page 56: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/56.jpg)
Google 2-Factor authentication
![Page 57: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/57.jpg)
VoteMeetEat.com & Telephony
• Handling registration SMS
• Sending SMS notifying users to vote
• Handling incoming voice call from voters:
• Text-to-speech of restaurants options
• Collecting digits entered via keypad
• Sending SMS notification of voting results
![Page 58: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/58.jpg)
DIY telephony = Difficult
• Difficult to setup and operate
• Expensive
• Complex SMS protocols
• …Bette
r to use S
MS/Telepho
ny-aaS:
![Page 59: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/59.jpg)
Telephony/SMS - aaS
• SMS• Inbound and outgoing calls• Recording and transcription
• SMS• Inbound and outgoing calls• Recording and transcription• Twitter• IM
![Page 60: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/60.jpg)
Twilio - Telephony and SMS as a service
• REST API• Allocate phone numbers• Make and receive phone calls• Send and receive SMS messages
• Pay per use:• Phone calls - per-minute • SMS – per SMS sent or received• Phone number – per month
• Examples• OpenVBX is a web-based, open source phone system• StubHub – notifies sellers of a pending sale via phone• SurveyMonkey – interactive polling• Salesforce – SMS-based voting for 19,000 conference attendees
![Page 61: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/61.jpg)
Using Twilio
Twilio Your Application
TwiML doc
HTTP GET/POST
REST API
Manage resourcesSend SMS
Initiate voice calls
Handle incoming SMS and voice callsRespond to user input
VoiceSMS
Phone number ⇒
SMS URL + VOICE URL
![Page 62: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/62.jpg)
Handling SMS registration
5551212
![Page 63: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/63.jpg)
Handling SMS registration
TwilioSMS
REGISTRATION
HTTP POST http://≪smsUrl≫?From=≪PhoneNumber≫
<Response> <Sms>To complete registration please go to http://... </Sms></Response>
SMS
![Page 64: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/64.jpg)
Handling SMS registration
TwiML document describing the
response
![Page 65: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/65.jpg)
Inviting users to vote
5551212
![Page 66: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/66.jpg)
Inviting users to vote
POST /2010-04-01/Accounts/≪AccountSID≫/SMS/Messages From=+15105551212&To=+14155551212&Body=≪MESSAGE≫Authorization: Basic ....
Basic auth using Twilio AccountSid+AuthToken
![Page 67: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/67.jpg)
Sending SMS using the Spring REST Template
@Componentclass TwilioService {
def sendSms(recipient : String, message : String) = { val response = postToTwilio("SMS/Messages", Map("From" -> twilioPhoneNumber, "To" -> recipient, "Body" -> message)) (response \ "SMSMessage" \ "Sid").text }
![Page 68: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/68.jpg)
Sending SMS using the Spring REST Template
TODO
@Componentclass TwilioService {
def postToTwilio(resourcePath : String, requestParams : Map[String, String]) = { val entity = makeEntity(requestParams)
try { val response = restTemplate.postForObject(twilioUrl +
"/Accounts/{accountSid}/{resource}", entity, classOf[String],
accountSid, resourcePath) XML.loadString(response) } catch { case e : HttpClientErrorException if e.getStatusCode == HttpStatus.BAD_REQUEST => val body = e.getResponseBodyAsString() val xmlBody = XML.loadString(body) val code = Integer.parseInt((xmlBody \\ "Code").text) val message = (xmlBody \\ "Message").text throw new TwilioRestException(message, code) }}
![Page 69: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/69.jpg)
Voting
555 1212
![Page 70: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/70.jpg)
Voting
Twilio
Survey Management<Response> <Say> Chris would like to meet and eat. </Say> <Gather action="handleresponse.html"
method="POST" numDigits="1"> <Say>Press 1 for ....</Say> <Say>Press 2 for ....</Say> </Gather></Response>
HTTP POST http://≪voiceUrl≫?From=≪PhoneNumber≫
Call
![Page 71: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/71.jpg)
Voting
Twilio
Survey Management
<Response> <Say>Thank you for choosing. The most popular place so far is ... </Say> <Pause/> <Say>You will hear from us soon. Good bye</Say> <Hangup/></Response>
HTTP POST http://....handleresponse.html?From=≪PhoneNumber≫&Digits=≪...≫
Digits
![Page 72: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/72.jpg)
Voting code 1@Controllerclass TwilioController { @Autowired var surveyManagementService: SurveyManagementService = _
@RequestMapping(value = Array("/begincall.html")) @ResponseBody def beginCall(@RequestParam("From") callerId: String) = { surveyManagementService.findSurveyByCallerId(callerId) match { case None => <Response> <Say>Sorry don't recognize your number</Say> <Hangup/> </Response> case Some(survey) => <Response> <Say>{ survey.prompt }</Say> <Gather action="handleresponse.html" method="POST" numDigits="1"> { for ((choice, index) <- survey.choices zipWithIndex) yield <Say>Press { index } for { choice }</Say> } </Gather> <Say>We are sorry you could not decide</Say> <Hangup/> </Response> } }
![Page 73: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/73.jpg)
Voting code 2class TwilioController { ... @RequestMapping(value = Array("/handleresponse.html")) @ResponseBody def handleUserResponse(@RequestParam("From") callerId: String,
@RequestParam("Digits") digits: Int) = { val survey = surveyManagementService.recordVote(callerId, digits) <Response> <Say>Thank you for choosing. The most popular place so far is
{ survey.map(_.mostPopularChoice) getOrElse "oops" } </Say> <Pause/> <Say>You will hear from us soon. Good bye</Say> <Hangup/> </Response> }}
![Page 74: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/74.jpg)
Agenda
• Why use cloud services?
• Developing location-based applications
• Building SMS and telephony enabled applications
• Developing robust, fault tolerant applications
![Page 75: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/75.jpg)
The need for parallelism
Service A
Service B
Service C
Service D
b = serviceB()
c = serviceC()
d = serviceD(b, c)
Call in parallel
![Page 76: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/76.jpg)
Java Futures are a great concurrency abstraction
http://en.wikipedia.org/wiki/Futures_and_promises
![Page 77: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/77.jpg)
Akka’s composable futures are even better
![Page 78: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/78.jpg)
Using Akka futurestrait FriendService { def findNearbyFriends(request : NearbyFriendsRequest) :
Future[FindNearbyFriendsResponse]}
trait RestaurantService { def findNearbyRestaurants(location: Location) :
Future[FindNearbyRestaurantResponse]}
val friendsRequest = NearbyFriendsRequest.fromLocation(vmeRecord.location)for ( (nearbyFriends, nearbyRestaurants) <-
friendsService.findNearbyFriends(friendsRequest) zip restaurantService.findNearbyRestaurants(vmeRecord.location)
) {
.... }} Two calls execute in parallel
![Page 79: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/79.jpg)
Using external web services = Distributed system
VoteMeetEat
TwilioMongoDB
Factual.Com
MobilePhone
![Page 80: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/80.jpg)
Internally = Distributed System
Survey management
VMEmanagement
Registration SMS
Registrationweb app
VME web app
Usermanagement
RabbitMQ
![Page 81: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/81.jpg)
Handling failure
Service A Service B
Errors happen in distributed systems
![Page 82: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/82.jpg)
About Netflix
> 1B API calls/day
1 API call ⇒ average 6 service calls
Fault tolerance is essential
http://techblog.netflix.com/2012/02/fault-tolerance-in-high-volume.html
![Page 83: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/83.jpg)
Use timeouts and retries
Never wait forever
Errors can be transient ⇒ retry
http://techblog.netflix.com/2012/02/fault-tolerance-in-high-volume.html
![Page 84: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/84.jpg)
Service A
Service B
Use per-dependency bounded thread pool
http://techblog.netflix.com/2012/02/fault-tolerance-in-high-volume.html
Runnable 1
Runnable 2
Runnable ...
bounded queue
Task 1
Task 2
Task ...
bounded thread pool
Limits number of outstanding requests
Fails fast if service is slow or down
![Page 85: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/85.jpg)
Use a circuit breaker
High error rate ⇒ stop calling temporarily
Down ⇒ wait for it to come back up
Slow ⇒ gives it a chance to recover
http://techblog.netflix.com/2012/02/fault-tolerance-in-high-volume.html
Closed Open
Half open
errors
successtimeout
fail
![Page 86: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/86.jpg)
On failure
http://techblog.netflix.com/2012/02/fault-tolerance-in-high-volume.html
AvoidFailing
Return cached data
Return default data
Fail fast
![Page 87: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/87.jpg)
WorkerActor
Aspects + Actors
CallerDependency
InvokerAspect
DependencyStub
CircuitBreakerActor
WorkerActor
Implements circuit
breaker state machine
Equivalent of thread pool
![Page 88: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/88.jpg)
@DependencyProxy annotation
@Service@DependencyProxy(circuitBreaker = "factualCircuitBreaker", timeoutInMilliseconds=750)class FactualRestaurantService extends RestaurantService { ...}
trait RestaurantService { def findNearbyRestaurants(location: Location) : Future[FindNearbyRestaurantResponse]}
![Page 89: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/89.jpg)
Aspect-based Async Execution
@Aspectclass DependencyInvokingAspect {
@Pointcut("execution(* (@DependencyProxy *).*(..))") def dependencyProxyMethods {}
@Around("dependencyProxyMethods()") def invoke(jp: ProceedingJoinPoint) = { val a = AnnotationUtils.findAnnotation(jp.getTarget.getClass, classOf[DependencyProxy]) val actor = findActor(a) val timeout = Timeout(a.timeoutInMilliseconds milliseconds) actor.ask(InvokeDependency( () => jp.proceed())) (timeout) }
}
Ask actor to invoke jp.proceed() and return Future
![Page 90: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/90.jpg)
See
https://github.com/cer/votemeeteat
for the Actor code
![Page 91: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/91.jpg)
Summary
Cloud services are highly scalable services developed and operated by a 3rd party
Let’s you focus on your core business problem
Risk: provider is acquired and stops offering service
Developing an application that reliably consumes cloud services requires careful design
![Page 92: Developing applications with Cloud Services #javaone 2012](https://reader037.vdocuments.mx/reader037/viewer/2022110306/554f47cab4c905b9508b4658/html5/thumbnails/92.jpg)
Questions?
@crichardson [email protected]://slideshare.net/chris.e.richardson/
Sign up for CloudFoundry.com using promo code cfjavaone