2. Cloud-to-Intranet
messaging in Force.com
• HTTP callout / Outbound Messaging
- Open inbound HTTP port on firewall
(Almost impossible for usual companies)
• API Polling
- Not realtime / Consumes a lot of API quotas
• Force.com Streaming API
- No need to open inbound port on firewall
- Almost realtime
3. Force.com Streaming API
• Enables push notification from Server
to subscribed client(s)
• GA in Spring ’12
• Standard based (Bayeux protocol)
- Client libraries available in various
languages
4. Message flow
for generic request clients
1. SecureConnect request client creates a record which includes
request message to Intranet resource server
2. Force.com publishes a notification to its request channel
subscribers (= SecureConnect resource server)
3. Resource server processes the request and access to the
resource data behind the firewall
4. Resource server returns response by updating the request
record
5. Force.com publishes a notification to its response channel
subscribers (= SecureConnect request client), and
SecureConnect request client receives response
6. Callout from Apex
• On submitting request, register an object
which implements ResponseListener
interface
- Both request message and response listener
object are serialized and inserted as a record
• Registered response listener is callbacked
by Apex trigger when the response arrived
7. Callout from Apex
3. resource
access
4. response
1. request
Apex Class
Resource
Response
Listener 5. trigger Server
2. Streaming
Request Client
8. Sample code
/**
* An example client which link opportunity information to intranet system via SecureConnect
*/
public class OpportunitySynchronizer {
public static void linkToExternalSystem(Opportunity opp) {
String oppJson = JSON.serialize(opp);
SecureConnect.request('opps/link', opp.Id, new PropagateResponseListener(opp.Id));
}
/**
* Callbacked when the response arrived from intranet server
*/
public class LinkResponseListener implements SecureConnect.ResponseListener {
public Id oppId { get; set; }
public LinkResponseListener(Id oppId) {
this.oppId = oppId;
}
public Type getClassType() {
return LinkResponseListener.class;
}
public void onResponse(String responseCode, String responseData) {
if (responseCode == 'success') {
String extId = responseData;
Opportunity opp = new Opportunity(Id=this.oppId, ExtId__c=extId);
update opp;
}
}
}
}