API Streaming
API Streaming
names and marks. Other marks appearing herein may be trademarks of their respective owners.
Table of Contents
Table of Contents
Getting Started with Force.com Streaming API.....................................................................................3 Chapter 1: Introducing Streaming API........................................................................................3
Push Technology Overview...........................................................................................................................................4 Bayeux Protocol, CometD, and Long Polling...............................................................................................................4 Streaming API Terms...................................................................................................................................................4 Message Reliability........................................................................................................................................................5
Table of Contents Event Notification Rules.............................................................................................................................................31 Events..............................................................................................................................................................31 Notifications....................................................................................................................................................31 Bulk Subscriptions.......................................................................................................................................................37 Deactivating a Push Topic...........................................................................................................................................37
ii
Chapter 1
Introducing Streaming API
Use Streaming API to receive notifications for changes to Salesforce data that match a SOQL query you define, in a secure and scalable way. These events can be received by: Pages in the Salesforce application. Application servers outside of Salesforce. Clients outside the Salesforce application. Note: Streaming API is part of a pilot program. To enable Streaming API for your organization, contact salesforce.com.
The sequence of events when using Streaming API is as follows: 1. 2. 3. 4. Create a PushTopic based on a SOQL query. This defines the channel. Clients subscribe to the channel. A record is created or updated (an event occurs). The changes to that record are evaluated. If the record changes match the criteria of the PushTopic query, a notification is generated by the server and received by the subscribed clients.
Streaming API is useful when you want notifications to be pushed from the server to the client based on criteria that you define. Consider the following applications for Streaming API: Applications that poll frequently Applications that have constant polling action against the Salesforce infrastructure, consuming unnecessary API calls and processing time, would benefit from Streaming API which reduces the number of requests that return no data. General notification Use Streaming API for applications that require general notification of data changes in an organization. This enables you to reduce the number of API calls and improve performance. Note: You can use Streaming API with any organization as long as you enable the API. This includes both Salesforce and Database.com organizations.
See Also:
Introducing Streaming API
If youre not familiar with long polling, Bayeux, or CometD, review the following resources: CometD documentation: http://cometd.org/documentation Bayeux protocol documentation: http://cometd.org/documentation/bayeux Bayeux protocol specification: http://cometd.org/documentation/bayeux/spec
See Also:
Introducing Streaming API
Message Reliability
Description Either the creation of a record or the update of a record. Each event may trigger a notification. A message in response to an event. The notification is sent to a channel to which one or more clients are subscribed. A record that you create. The essential element of a PushTopic is the SOQL query. The PushTopic defines a Streaming API channel.
See Also:
Introducing Streaming API
Message Reliability
Streaming API doesnt guarantee durability and reliable delivery of notifications. Streaming servers dont maintain any client state and dont keep track of whats delivered. The client may not receive messages for a variety of reasons, including: When a client first subscribes or reconnects, it doesnt receive messages that were processed while it wasnt subscribed to the channel. If a client disconnects and starts a new handshake, it may be working with a different application server, so it receives only new messages from that point on. Some events may be dropped if the system is being heavily used. If an application server is stopped, all the messages being processed but not yet sent are lost. Any clients connected to that application server are disconnected. To receive notifications, the client must reconnect and subscribe to the topic channel.
See Also:
Introducing Streaming API
Chapter 2
Quick Start Using Workbench
This quick start shows you how to get started with Streaming API by using Workbench. This quick start takes you step-by-step through the process of using Streaming API to receive notification when a record is updated. Prerequisites Step 1: Create an Object Step 2: Create a PushTopic Step 3: Subscribe to the PushTopic Channel Step 4: Test the PushTopic Channel
Prerequisites
You need access and appropriate permissions to complete the quick start steps. Access to a Developer Edition organization. If you are not already a member of the Force.com developer community, go to http://developer.force.com/join and follow the instructions for signing up for a Developer Edition organization. Even if you already have Enterprise Edition or Unlimited Edition, use Developer Edition for developing, staging, and testing your solutions against sample data to protect your organizations live data. This is especially true for applications that insert, update, or delete data (as opposed to simply reading data). The API Enabled permission enabled for your Developer Edition organization. This permission is enabled by default, but may have been changed by an administrator. Access to Streaming API. While Streaming API is in pilot, you must register for access to it by contacting salesforce.com, inc.. The Streaming API permission enabled. Note: To verify that the API Enabled and Streaming API permissions are enabled in your organization, go to My Name > Setup > Customize > User Interface. The logged-in user must have Create permission on the PushTopic standard object to create and manage PushTopic records. The logged-in user must have Read permission on the PushTopic standard object to receive notifications. The logged-in user must have Author Apex permissions to create a PushTopic by using the System Log.
3. Click Save. 4. Add a Status field. a. b. c. d. Scroll down to the Custom Fields & Relationships related list and click New. For Data Type, select Picklist and click Next. In the Field Label field, type Status. Type the following picklist values in the box provided, with each entry on its own line.
Open Closed Negotiating Pending
e. Select the checkbox for Use first value as default value. f. Click Next. g. For field-level security, select Read Only and then click Next. 5. Now create an optional Description field. a. b. c. d. In the Data Type field, select Text Area and click Next. In the Field Label and Field Name fields, enter Description. Click Next, accept the defaults, and click Next again. Click Save to go the detail page for the Invoice Statement object.
3. In the Enter Apex Code window, paste in the following Apex code, and click Execute.
PushTopic pushTopic = new PushTopic(); pushTopic.Name = 'InvoiceStatementUpdates'; pushtopic.Query = 'SELECT Id, Name, Status__c, Description__c FROM Invoice_Statement__c'; pushTopic.ApiVersion = 24.0; pushTopic.NotifyForOperations = 'All'; pushTopic.NotifyForFields = 'Referenced'; insert pushTopic;
Because NotifyForOperations is set to All, Streaming API evaluates records that are created or updated and generates a notification if the record matches the PushTopic query. Because NotifyForFields is set to Referenced, Streaming API will use fields in both the SELECT clause and the WHERE clause to generate a notification. Whenever the fields Name, Status__c, or Description__c are updated, a notification will be generated on this channel.
Note: If the user that makes an update to a record and the user thats subscribed to the channel dont share records, then the subscribed user wont receive the notification. For example, if the sharing model for the organization is private. 2. 3. 4. 5. 6. Click data > Insert. For Object Type, select Invoice_Statement__c. Ensure that the Single Record field is selected, and click Next. Type in a value for the Description__c field. Click Confirm Insert. Switch over to your Streaming Push Topics browser window. Youll see a notification that the invoice statement was created. The notification returns the Id, Status__c, and Description__c fields that you defined in the SELECT statement of your PushTopic query. The message looks something like this:
{ "channel": "/topic/InvoiceStatementUpdates", "data": { "event": { "type": "created", "createdDate": "2011-11-14T17:33:45.000+0000" }, "sobject": { "Name": "INV-0004", "Id": "a00D0000008oLi8IAE", "Description__c": "Test invoice statement", "Status__c": "Open" } } }
CODE EXAMPLES
Chapter 3
Example: Visualforce Page
This code example shows you how to implement Streaming API from a Visualforce page. When you run the page, it subscribes to the channel and receives notifications. Prerequisites Step 1: Create an Object Step 2: Create a PushTopic Step 3: Create the Static Resources Step 4: Create a Visualforce Page Step 5: Test the PushTopic Channel
Prerequisites
You need access and appropriate permissions to complete the code example. Access to a Developer Edition organization. If you are not already a member of the Force.com developer community, go to http://developer.force.com/join and follow the instructions for signing up for a Developer Edition organization. Even if you already have Enterprise Edition or Unlimited Edition, use Developer Edition for developing, staging, and testing your solutions against sample data to protect your organizations live data. This is especially true for applications that insert, update, or delete data (as opposed to simply reading data). The API Enabled permission enabled for your Developer Edition organization. This permission is enabled by default, but may have been changed by an administrator. Access to Streaming API. While Streaming API is in pilot, you must register for access to it by contacting salesforce.com. The Streaming API permission enabled. Note: To verify that the API Enabled and Streaming API permissions are enabled in your organization, go to My Name > Setup > Customize > User Interface. The logged-in user must have Create permission on the PushTopic standard object to create and manage PushTopic records. The logged-in user must have Read permission on the PushTopic standard object to receive notifications.
10
The logged-in user must have Author Apex permissions to create a PushTopic by using the System Log.
3. Click Save. 4. Add a Status field. a. b. c. d. Scroll down to the Custom Fields & Relationships related list and click New. For Data Type, select Picklist and click Next. In the Field Label field, type Status. Type the following picklist values in the box provided, with each entry on its own line.
Open Closed Negotiating Pending
e. Select the checkbox for Use first value as default value. f. Click Next. g. For field-level security, select Read Only and then click Next. 5. Now create an optional Description field. a. b. c. d. In the Data Type field, select Text Area and click Next. In the Field Label and Field Name fields, enter Description. Click Next, accept the defaults, and click Next again. Click Save to go the detail page for the Invoice Statement object.
11
1. Select Your Name > Developer Console. 2. On the Logs tab, click Execute. 3. In the Enter Apex Code window, paste in the following Apex code, and click Execute.
PushTopic pushTopic = new PushTopic(); pushTopic.Name = 'InvoiceStatementUpdates'; pushtopic.Query = 'SELECT Id, Name, Status__c, Description__c FROM Invoice_Statement__c'; pushTopic.ApiVersion = 24.0; pushTopic.NotifyForOperations = 'All'; pushTopic.NotifyForFields = 'Referenced'; insert pushTopic;
Because NotifyForOperations is set to All, Streaming API evaluates records that are created or updated and generates a notification if the record matches the PushTopic query. Because NotifyForFields is set to Referenced, Streaming API will use fields in both the SELECT clause and the WHERE clause to generate a notification. Whenever the fields Name, Status__c, or Description__c are updated, a notification will be generated on this channel.
To extract the .tgz file in the Windows environment, youll need a utility such as PowerArchiver, 7zip, or Winzip. To extract the cometd.js file you can use a compression utility or run shell commands similar to the following:
cd cometd-2.2.0/cometd-javascript/common/target jar xvf cometd-javascript-common-2.2.0.war org/cometd.js
3. Select Your Name > Setup > Develop > Static Resources to add the extracted files with the following names: File Name
cometd.js jquery-1.5.1.js json2.js jquery.cometd.js
12
13
2. Create or modify an InvoiceStatement in a different browser. You should see the event notification appear on the Visualforce page.
14
Chapter 4
Example: Java Client
This code example shows you how to implement Streaming API from a Java client. When you run the Java client, it subscribes to the channel and receives notifications. Example: Java Client Prerequisites Step 1: Create an Object Step 2: Create a PushTopic Step 3: Download the JAR Files Step 4: Add the Source Code
Prerequisites
You need access and appropriate permissions to complete the code example. Access to a Developer Edition organization. If you are not already a member of the Force.com developer community, go to http://developer.force.com/join and follow the instructions for signing up for a Developer Edition organization. Even if you already have Enterprise Edition or Unlimited Edition, use Developer Edition for developing, staging, and testing your solutions against sample data to protect your organizations live data. This is especially true for applications that insert, update, or delete data (as opposed to simply reading data). The API Enabled permission enabled for your Developer Edition organization. This permission is enabled by default, but may have been changed by an administrator. Access to Streaming API. While Streaming API is in pilot, you must register for access to it by contacting salesforce.com. The Streaming API permission enabled. Note: To verify that the API Enabled and Streaming API permissions are enabled in your organization, go to My Name > Setup > Customize > User Interface. The logged-in user must have Create permission on the PushTopic standard object to create and manage PushTopic records. The logged-in user must have Read permission on the PushTopic standard object to receive notifications. The logged-in user must have Author Apex permissions to create a PushTopic by using the System Log.
15
3. Click Save. 4. Add a Status field. a. b. c. d. Scroll down to the Custom Fields & Relationships related list and click New. For Data Type, select Picklist and click Next. In the Field Label field, type Status. Type the following picklist values in the box provided, with each entry on its own line.
Open Closed Negotiating Pending
e. Select the checkbox for Use first value as default value. f. Click Next. g. For field-level security, select Read Only and then click Next. 5. Now create an optional Description field. a. b. c. d. In the Data Type field, select Text Area and click Next. In the Field Label and Field Name fields, enter Description. Click Next, accept the defaults, and click Next again. Click Save to go the detail page for the Invoice Statement object.
16
3. In the Enter Apex Code window, paste in the following Apex code, and click Execute.
PushTopic pushTopic = new PushTopic(); pushTopic.Name = 'InvoiceStatementUpdates'; pushtopic.Query = 'SELECT Id, Name, Status__c, Description__c FROM Invoice_Statement__c'; pushTopic.ApiVersion = 24.0; pushTopic.NotifyForOperations = 'All'; pushTopic.NotifyForFields = 'Referenced'; insert pushTopic;
Because NotifyForOperations is set to All, Streaming API evaluates records that are created or updated and generates a notification if the record matches the PushTopic query. Because NotifyForFields is set to Referenced, Streaming API will use fields in both the SELECT clause and the WHERE clause to generate a notification. Whenever the fields Name, Status__c, or Description__c are updated, a notification will be generated on this channel.
3. Download the compressed archive file from the following URL: http://dist.codehaus.org/jetty-hightide-7.4.4/jetty-hightide-7.4.4.v20110707.tar.gz. Jetty Hightide is a distribution of the Jetty open source Web container. For more information, see the Jetty Hightide documentation. 4. Extract the following JAR files from jetty-hightide-7.4.4.v20110707.tar.gz.
jetty-hightide-7.4.4.v20110707/lib/jetty-client-7.4.4.v20110707.jar jetty-hightide-7.4.4.v20110707/lib/jetty-http-7.4.4.v20110707.jar jetty-hightide-7.4.4.v20110707/lib/jetty-io-7.4.4.v20110707.jar jetty-hightide-7.4.4.v20110707/lib/jetty-util-7.4.4.v20110707.jar
17
import org.eclipse.jetty.client.ContentExchange; import org.eclipse.jetty.client.HttpClient; import import import import java.net.MalformedURLException; java.net.URL; java.util.HashMap; java.util.Map;
/** * This example demonstrates how a streaming client works * against the Salesforce Streaming API. **/ public class StreamingClientExample { // // // // This URL is used only for logging in. The LoginResult returns a serverUrl which is then used for constructing the streaming URL. The serverUrl points to the endpoint where your organization is hosted.
static final String LOGIN_ENDPOINT = "https://login.salesforce.com"; private static final String USER_NAME = "[email protected]"; private static final String PASSWORD = "change_this_to_your_testpassword"; // NOTE: Putting passwords in code is not a good practice and not recommended. // Set this to // against the private static private static true only when using this client Summer'11 release (API version=22.0). final boolean VERSION_22 = false; final boolean USE_COOKIES = VERSION_22;
// The channel to subscribe to. Same as the name of the PushTopic. // Be sure to create this topic before running this sample. private static final String CHANNEL = VERSION_22 ? "/InvoiceStatementUpdates" : "/topic/InvoiceStatementUpdates"; private static final String STREAMING_ENDPOINT_URI = VERSION_22 ? "/cometd" : "/cometd/23.0"; // The long poll duration. private static final int CONNECTION_TIMEOUT = 20 * 1000; // milliseconds private static final int READ_TIMEOUT = 120 * 1000; // milliseconds public static void main(String[] args) throws Exception { System.out.println("Running streaming client example...."); final BayeuxClient client = makeClient(); client.getChannel(Channel.META_HANDSHAKE).addListener (new ClientSessionChannel.MessageListener() { public void onMessage(ClientSessionChannel channel, Message message) { System.out.println("[CHANNEL:META_HANDSHAKE]: " + message); boolean success = message.isSuccessful(); if (!success) { String error = (String) message.get("error"); if (error != null) { System.out.println("Error during HANDSHAKE: " + error); System.out.println("Exiting..."); System.exit(1);
18
} Exception exception = (Exception) message.get("exception"); if (exception != null) { System.out.println("Exception during HANDSHAKE: "); exception.printStackTrace(); System.out.println("Exiting..."); System.exit(1); } } } }); client.getChannel(Channel.META_CONNECT).addListener( new ClientSessionChannel.MessageListener() { public void onMessage(ClientSessionChannel channel, Message message) { System.out.println("[CHANNEL:META_CONNECT]: " + message); boolean success = message.isSuccessful(); if (!success) { String error = (String) message.get("error"); if (error != null) { System.out.println("Error during CONNECT: " + error); System.out.println("Exiting..."); System.exit(1); } } } }); client.getChannel(Channel.META_SUBSCRIBE).addListener( new ClientSessionChannel.MessageListener() { public void onMessage(ClientSessionChannel channel, Message message) { System.out.println("[CHANNEL:META_SUBSCRIBE]: " + message); boolean success = message.isSuccessful(); if (!success) { String error = (String) message.get("error"); if (error != null) { System.out.println("Error during SUBSCRIBE: " + error); System.out.println("Exiting..."); System.exit(1); } } } });
client.handshake(); System.out.println("Waiting for handshake"); boolean handshaken = client.waitFor(10 * 1000, BayeuxClient.State.CONNECTED); if (!handshaken) { System.out.println("Failed to handshake: " + client); System.exit(1); }
19
client.getChannel(CHANNEL).subscribe(new MessageListener() { @Override public void onMessage(ClientSessionChannel channel, Message message) { System.out.println("Received Message: " + message); } }); System.out.println("Waiting for streamed data from your organization ..."); while (true) { // This infinite loop is for demo only, // to receive streamed events on the // specified topic from your organization. } }
private static BayeuxClient makeClient() throws Exception { HttpClient httpClient = new HttpClient(); httpClient.setConnectTimeout(CONNECTION_TIMEOUT); httpClient.setTimeout(READ_TIMEOUT); httpClient.start(); String[] pair = SoapLoginUtil.login(httpClient, USER_NAME, PASSWORD); if (pair == null) { System.exit(1); } assert pair.length == 2; final String sessionid = pair[0]; String endpoint = pair[1]; System.out.println("Login successful!\nEndpoint: " + endpoint + "\nSessionid=" + sessionid); Map<String, Object> options = new HashMap<String, Object>(); options.put(ClientTransport.TIMEOUT_OPTION, READ_TIMEOUT); LongPollingTransport transport = new LongPollingTransport( options, httpClient) { @Override protected void customize(ContentExchange exchange) { super.customize(exchange); exchange.addRequestHeader("Authorization", "OAuth " + sessionid); } }; BayeuxClient client = new BayeuxClient(salesforceStreamingEndpoint( endpoint), transport); if (USE_COOKIES) establishCookies(client, USER_NAME, sessionid); return client; } private static String salesforceStreamingEndpoint(String endpoint) throws MalformedURLException { return new URL(endpoint + STREAMING_ENDPOINT_URI).toExternalForm(); } private static void establishCookies(BayeuxClient client, String user, String sid) { client.setCookie("com.salesforce.LocaleInfo", "us", 24 * 60 * 60 * 1000); client.setCookie("login", user, 24 * 60 * 60 * 1000); client.setCookie("sid", sid, 24 * 60 * 60 * 1000); client.setCookie("language", "en_US", 24 * 60 * 60 * 1000); } }
20
Static Resource Name Username of the logged-in user Password for the USER_NAME (or logged-in user)
/topic/InvoiceStatementUpdates https://test.salesforce.com (Only if you are using a sandbox. If you are in a
3. Add the following code to a Java source file named SoapLoginUtil.java. This code sends a username and password to the server and receives the session ID. Important: Never handle the usernames and passwords of others. Before using in a production environment, delegate the login to OAuth.
package demo; import import import import import import import import import import java.io.ByteArrayInputStream; java.io.IOException; java.io.UnsupportedEncodingException; java.net.MalformedURLException; java.net.URL; org.eclipse.jetty.client.ContentExchange; org.eclipse.jetty.client.HttpClient; org.xml.sax.Attributes; org.xml.sax.SAXException; org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; public final class SoapLoginUtil { // The enterprise SOAP API endpoint used for the login call in this example. private static final String SERVICES_SOAP_PARTNER_ENDPOINT = "/services/Soap/u/22.0/"; private static final String ENV_START = "<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' " + "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' " + "xmlns:urn='urn:partner.soap.sforce.com'><soapenv:Body>"; private static final String ENV_END = "</soapenv:Body></soapenv:Envelope>"; private static byte[] soapXmlForLogin(String username, String password) throws UnsupportedEncodingException { return (ENV_START + " <urn:login>" + " <urn:username>" + username + "</urn:username>" + " <urn:password>" + password + "</urn:password>" + " </urn:login>" + ENV_END).getBytes("UTF-8"); }
21
public static String[] login(HttpClient client, String username, String password) throws IOException, InterruptedException, SAXException, ParserConfigurationException { ContentExchange exchange = new ContentExchange(); exchange.setMethod("POST"); exchange.setURL(getSoapURL()); exchange.setRequestContentSource(new ByteArrayInputStream(soapXmlForLogin( username, password))); exchange.setRequestHeader("Content-Type", "text/xml"); exchange.setRequestHeader("SOAPAction", "''"); exchange.setRequestHeader("PrettyPrint", "Yes"); client.send(exchange); exchange.waitForDone(); String response = exchange.getResponseContent(); SAXParserFactory spf = SAXParserFactory.newInstance(); spf.setNamespaceAware(true); SAXParser saxParser = spf.newSAXParser(); LoginResponseParser parser = new LoginResponseParser(); saxParser.parse(new ByteArrayInputStream( response.getBytes("UTF-8")), parser); if (parser.sessionId == null || parser.serverUrl == null) { System.out.println("Login Failed!\n" + response); return null; } URL soapEndpoint = new URL(parser.serverUrl); StringBuilder endpoint = new StringBuilder() .append(soapEndpoint.getProtocol()) .append("://") .append(soapEndpoint.getHost()); if (soapEndpoint.getPort() > 0) endpoint.append(":") .append(soapEndpoint.getPort()); return new String[] {parser.sessionId, endpoint.toString()}; } private static String getSoapURL() throws MalformedURLException { return new URL(StreamingClientExample.LOGIN_ENDPOINT + getSoapUri()).toExternalForm(); } private static String getSoapUri() { return SERVICES_SOAP_PARTNER_ENDPOINT; } private static class LoginResponseParser extends DefaultHandler { private boolean inSessionId; private String sessionId; private boolean inServerUrl; private String serverUrl; @Override public void characters(char[] ch, int start, int length) { if (inSessionId) sessionId = new String(ch, start, length); if (inServerUrl) serverUrl = new String(ch, start, length); } @Override public void endElement(String uri, String localName, String qName) { if (localName != null) {
22
if (localName.equals("sessionId")) { inSessionId = false; } if (localName.equals("serverUrl")) { inServerUrl = false; } } } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) { if (localName != null) { if (localName.equals("sessionId")) { inSessionId = true; } if (localName.equals("serverUrl")) { inServerUrl = true; } } } } }
4. In a different browser window, create or modify an InvoiceStatement. After you create or change data that corresponds to the query in your PushTopic, the output looks something like this:
Running streaming client example.... Login successful! Endpoint: https://www.salesforce.com Sessionid=00DD0000000FSp9!AQIAQIVjGYijFhiAROTc455T6kEVeJGXuW5VCnp LANCMawS7.p5fXbjYlqCgx7They_zFjmP5n9HxvfUA6xGSGtC1Nb6P4S. Waiting for handshake [CHANNEL:META_HANDSHAKE]: { "id":"1", "minimumVersion":"1.0", "supportedConnectionTypes":["long-polling"], "successful":true, "channel":"/meta/handshake", "clientId":"31t0cjzfbgnfqn1rggumba0k98u", "version":"1.0" } [CHANNEL:META_CONNECT]: { "id":"2", "successful":true, "advice":{"interval":0,"reconnect":"retry","timeout":110000}, "channel":"/meta/connect"} Subscribing for channel: /topic/InvoiceStatementUpdates Waiting for streamed data from your organization ... [CHANNEL:META_SUBSCRIBE]: { "id":"4", "subscription":"/topic/InvoiceStatementUpdates", "successful":true, "channel":"/meta/subscribe" } [CHANNEL:META_CONNECT]: {
23
"id":"3", "successful":true, "channel":"/meta/connect" } Received Message: { "data": { "sobject": { "Name":"INV-0002", "Id":"001D000000J3fTHIAZ", "Status__c":"Pending"}, "event":{"type":"updated", "createdDate":"2011-09-06T18:51:08.000+0000" } }, "channel":"/topic/InvoiceStatementUpdates" } [CHANNEL:META_CONNECT]: { "id":"5", "successful":true, "channel":"/meta/connect" }
24
Chapter 5
Examples: Authentication
You can set up a simple authentication scheme for developer testing. For production systems, use robust authorization, such as OAuth 2.0. Setting Up Authentication for Developer Testing Setting Up Authentication with OAuth 2.0
1. Log in using the Web services SOAP API login() and get the session ID. 2. Set up the HTTP authorization header using this session ID:
Authorization: OAuth sessionId
The CometD endpoint requires a session ID on all requests, plus any additional cookies set by the Salesforce server. For more details, see Step 4: Add the Source Code.
25
Examples: Authentication
Note: The OAuth 2.0 specification uses client instead of consumer. Salesforce supports OAuth 2.0.
The values here correspond to the following values in the sample code in the rest of this procedure:
client_id is the Consumer Key client_secret is the Consumer Secret redirect_uri is the Callback URL.
An additional value you must specify is: the grant_type. For OAuth 2.0 callbacks, the value is authorization_code as shown in the sample. You can pass the access token rather than the session ID to authenticate on calls to Streaming API. If the value of client_id (or consumer key) and client_secret (or consumer secret) are valid, Salesforce sends a callback to the URI specified in redirect_uri that contains a value for access_token. 2. From your Java or other client application, make a request to the authentication URL that passes in grant_type, client_id, client_secret, username, and password . For example:
HttpClient httpclient = new HttpClient(); PostMethod post = new PostMethod(environment); post.addParameter("grant_type", "password"); post.addParameter("client_id", clientId); post.addParameter("client_secret", clientSecret); post.addParameter("username", "[email protected]"); post.addParameter("password", "swordfish");
Important: This method of authentication should only be used in development environments and not for production code.
This example gets the session ID (authenticates), and then follows a resource,
https://instance_name.salesforce.com/id/00Dxxxxxxxxxxxx/005xxxxxxxxxxxx contained in the first
26
Examples: Authentication
// Execute the request System.out.println("POST " + baseUrl); oauthPost.setRequestBody(parametersBody); int code = client.executeMethod(oauthPost); String jsonResponse = oauthPost.getResponseBodyAsString(); System.out.println("HTTP " + String.valueOf(code) + ": " + jsonResponse); }
27
Chapter 6
Working with PushTopics
In this chapter ... PushTopic Queries Event Notification Rules Bulk Subscriptions Deactivating a Push Topic
Each PushTopic record that you create corresponds to a channel in CometD. The channel name is the name of the PushTopic prefixed with /topic/, for example, /topic/MyPushTopic. A Bayeux client can receive streamed events on this channel. Note: Updates performed by the Bulk API wont generate notifications, since such updates could flood a channel. As soon as a PushTopic record is created, the system starts evaluating record updates and creates for matches. Whenever theres a match, a new notification is generated. The server polls for new notifications for currently subscribed channels every three seconds. This time may fluctuate depending on the overall server load. The PushTopic defines when notifications are generated in the channel. This is specified by configuring the following PushTopic fields: Query NotifyForOperations NotifyForFields
28
PushTopic Queries
PushTopic Queries
The PushTopic query is the basis of the PushTopic channel and defines which record create or update events generate a notification. This query must be a valid SOQL query. To ensure that notifications are sent in a timely manner, the following requirements apply to PushTopic queries. The query SELECT clause must include Id. For example: SELECT Id, Name FROM.... Only one entity per query. The object must be valid for the specified API version.
The fields that you specify in the PushTopic SELECT clause make up the body of the notification that is streamed on the PushTopic channel. For example, if your PushTopic query is SELECT Id, Name, Status__c FROM InvoiceStatement__c, then the ID, Name and Status__c fields are included in any notifications sent on that channel. Following is an example of a notification message that might appear in that channel:
{ "channel": "/topic/InvoiceStatementUpdates", "data": { "event": { "type": "updated", "createdDate": "2011-11-03T15:59:06.000+0000" }, "sobject": { "Name": "INV-0001", "Id": "a00D0000008o6y8IAA", "Status__c": "Open" } } }
If you change a PushTopic query, those changes take effect immediately on the server. A client receives events only if they match the new SOQL query. If you change a PushTopic Name, live subscriptions are not affected. New subscriptions must use the new channel name.
If the subscriber doesnt have access to specific fields referenced in the query SELECT clause, then those fields arent included in the notification. If the subscriber doesnt have access to all fields referenced in the query WHERE clause, then they will not receive the notification. For example, assume a user tries to subscribe to a PushTopic with the following Query value:
SELECT Id, Name, SSN__c FROM Employee__c WHERE Bonus_Received__c = true AND Bonus_Amount__c > 20000
29
Supported SOQL
If the subscriber doesn't have access to Bonus_Received__c or Bonus_Amount__c, the subscription fails. If the subscriber doesnt have access to SSN__c, then it wont be returned in the notification. If the subscriber has already successfully subscribed to the PushTopic, but the field-level security then changes so that the user no longer has access to one of the fields referenced in the WHERE clause, no streamed notifications are sent.
Supported SOQL
The standard SOQL operators are all supported in PushTopic queries. Most SOQL statements and expressions are supported, although there are some that arent supported.
Unsupported SOQL
The following SOQL statements are not supported in PushTopic queries. Queries without an Id in the selected fields list Semi-joins and anti-joins Example query: SELECT Id, Name FROM Account WHERE Id IN (SELECT AccountId FROM Contact
WHERE Title = 'CEO')
Error message: INVALID_FIELD, semi/anti join sub-selects are not supported Aggregate queries (queries that use AVG, MAX, MIN, and SUM) Example query: SELECT Id, AVG(AnnualRevenue) FROM Account Error message: INVALID_FIELD, Aggregate queries are not supported
COUNT
Example query: SELECT Id, Industry, Count(Name) FROM Account Error message: INVALID_FIELD, Aggregate queries are not supported
LIMIT
Example query: SELECT Id, Name FROM Contact LIMIT 10 Error message: INVALID_FIELD, 'LIMIT' is not allowed Relationships are not supported, but you can reference an ID: Example query: SELECT Id, Contact.Account.Name FROM Contact Error message: INVALID_FIELD, relationships are not supported Searching for values in Text Area fields.
ORDER BY
Example query: SELECT Id, Name FROM Account ORDER BY Name Error message: INVALID_FIELD, 'ORDER BY' clause is not allowed
GROUP BY
Example query: SELECT Id, AccountId FROM Contact GROUP BY AccountId Error message: INVALID_FIELD, 'Aggregate queries are not supported'
30
Formula fields
NOT
Example query: SELECT Id FROM Account WHERE NOT Name = 'Salesforce.com' Error message: INVALID_FIELD, 'NOT' is not supported To make this a valid query, change it to SELECT Id FROM Account WHERE Name != 'Salesforce.com'. Note: The NOT IN phrase is supported in PushTopic queries.
OFFSET
Example query: SELECT Id, Name FROM Account WHERE City = 'New York' OFFSET 10 Error message: INVALID_FIELD, 'OFFSET' clause is not allowed
Events
Events that may generate a notification are the creation of a record or the update of a record. The PushTopic field NotifyForOperations enables you to specify which events may generate a notification in that PushTopic channel. The NotifyForOperations values are:
NotifyForOperations
Description Evaluate a record to possibly generate a notification whether the record has been created or updated. Evaluate a record to possibly generate a notification only if the record has been created. Evaluate a record to possibly generate a notification only if the record has been updated.
Value
All (default)
Create Update
The NotifyForOperations value together with the NotifyForFields value provides flexibility when configuring when you want to generate notifications using Streaming API.
Notifications
After a record is created or updated (an event), the record is evaluated against the PushTopic query and a notification may be generated. A notification is the message sent to the channel as the result of an event. The notification is a JSON formatted message. The PushTopic field NotifyForFields specifies how the record is evaluated against the PushTopic query. The NotifyForFields values are:
31
Notifications
Description Notifications are generated for all record field changes, provided the values of the fields referenced in the WHERE clause match the values specified in the WHERE clause. Changes to fields referenced in both the SELECT clause and WHERE clause are evaluated. Notifications are generated for all records where a field referenced in the SELECT clause changes or a field referenced in the WHERE clause changes and the values of the fields referenced in the WHERE clause match the values specified in the WHERE clause. Changes to fields referenced in the SELECT clause are evaluated. Notifications are generated for all records where a field referenced in the SELECT clause changes and the values of the fields referenced in the WHERE clause match the values specified in the WHERE clause. Changes to fields referenced in the WHERE clause are evaluated. Notifications are generated for all records where a field referenced in the WHERE clause changes and the values of the fields referenced in the WHERE clause match the values specified in the WHERE clause.
Referenced (default)
Select
Where
The fields that you specify in the PushTopic query SELECT clause are contained in the notification message. NotifyForFields Set to All When you set the value of PushTopic.NotifyForFields to All, a change to any field value in the record causes the Streaming API matching logic to evaluate the record to determine if a notification should be generated. Changes to record field values cause this evaluation whether or not those fields are referenced in the PushTopic query SELECT clause or WHERE clause. Event Record is created Record is updated A notification is generated when The record field values match the values specified in the WHERE clause The record field values match the values specified in the WHERE clause
Result Generates a notification if any field values in the record have changed.
SELECT Id, f1, f2 FROM Generates a notification if any field values in the record have changed and f3 and f4 match InvoiceStatement WHERE the values in the WHERE clause. f3 = 'abc' AND f4 LIKE 'xyz' SELECT Id FROM InvoiceStatement
When Id is the only field in the SELECT clause, a notification is generated if any field values have changed.
SELECT Id FROM Generates a notification if any field values in the record have changed and f3 and f4 match InvoiceStatement WHERE the values in the WHERE clause. f3 = 'abc' AND f4 LIKE 'xyz'
32
Notifications
PushTopic Query
Result
SELECT Id FROM Generates a notification if any field values in the record have changed and the record ID is InvoiceStatement WHERE contained in the WHERE clause IN list. Id IN ('a07B0000000KWZ7IAO', 'e10R0000000KEU9IAO', 'v32B0000000KWZ7YEP') SELECT Id, f1, f2 FROM Generates a notification if any field values in the record have changed and the record ID is InvoiceStatement WHERE contained in the WHERE clause IN list. Id IN ('a07B0000000KWZ7IAO', 'e10R0000000KEU9IAO', 'v32B0000000KWZ7YEP') SELECT Id, f1, f2 FROM Generates a notification if any field values in the record have changed, f3 and f4 match the InvoiceStatement WHERE WHERE clause, and the record ID is contained in the WHERE clause IN list. f3 = 'abc' AND f4 LIKE 'xyz' AND Id IN ('a07B0000000KWZ7IAO', 'e10R0000000KEU9IAO', 'v32B0000000KWZ7YEP')
Caution: Use caution when setting NotifyForFields to All. When you use this value, then notifications are generated for all record field changes as long as the new field values match the values in the WHERE clause. Therefore, the number of generated notifications could potentially be large, and you may hit the daily quota of events limit. In addition, because every record change is evaluated and many notifications may be generated, this causes a heavier load on the system.
NotifyForFields Set to Referenced When you set the value of PushTopic.NotifyForFields to Referenced, a change to any field value in the record as long as that field is referenced in the query SELECT clause or WHERE clause causes the Streaming API matching logic to evaluate the record to determine if a notification should be generated. If the PushTopic.NotifyForFields value is Referenced, then the PushTopic query must have a SELECT clause with at least one field other than ID or a WHERE clause with at least one field other than Id. Event Record is created Record is updated A notification is generated when The record field values match the values specified in the WHERE clause A change occurs in one or more record fields that are specified in the PushTopic query SELECT clause or A change occurs in one or more record fields that are specified in the PushTopic query WHERE clause and The record values of the fields specified in the WHERE clause all match the values in the PushTopic query WHERE clause
33
Notifications
Result Generates a notification if f1, f2, or f3 have changed. Generates a notification if f1, f2, f3, or f4 have changed and f3 and f4 match the values in the WHERE clause.
SELECT Id FROM InvoiceStatement__c Generates a notification if f3 and f4 have changed and f3 and f4 match the WHERE f3 = 'abc' AND f4 LIKE 'xyz' values in the WHERE clause. SELECT Id, f1, f2 FROM InvoiceStatement__c WHERE Id IN ('a07B0000000KWZ7IAO', 'e10R0000000KEU9IAO', 'v32B0000000KWZ7YEP') SELECT Id, f1, f2 FROM InvoiceStatement__c WHERE f3 = 'abc' AND f4 LIKE 'xyz' AND Id IN ('a07B0000000KWZ7IAO', 'e10R0000000KEU9IAO', 'v32B0000000KWZ7YEP')
Generates a notification if f1 or f2 have changed and the record ID is contained in the WHERE clause IN list.
Generates a notification if f1, f2, f3, or f4 have changed, f3 and f4 match the values in the WHERE clause, and the ID is contained in the WHERE clause IN list.
NotifyForFields Set to Select When you set the value of PushTopic.NotifyForFields to Select, a change to any field value in the record as long as that field is referenced in the query SELECT clause causes the Streaming API matching logic to evaluate the record to determine if a notification should be generated. If the PushTopic.NotifyForFields value is Select, then the PushTopic query must have a SELECT clause with at least one field other than ID. Event Record is created Record is updated A notification is generated when The record field values match the values specified in the WHERE clause A change occurs in one or more record fields that are specified in the PushTopic query SELECT clause and The record values of the fields specified in the WHERE clause all match the values in the PushTopic query WHERE clause
Examples
34
Notifications
PushTopic Query
SELECT Id, f1, f2, f3 FROM InvoiceStatement__c SELECT Id, f1, f2 FROM InvoiceStatement__c WHERE f3 = 'abc' AND f4 LIKE 'xyz' SELECT Id, f1, f2 FROM InvoiceStatement__c WHERE Id IN ('a07B0000000KWZ7IAO', 'e10R0000000KEU9IAO', 'v32B0000000KWZ7YEP') SELECT Id, f1, f2 FROM InvoiceStatement__c WHERE f3 = 'abc' AND f4 LIKE 'xyz' AND Id IN ('a07B0000000KWZ7IAO', 'e10R0000000KEU9IAO', 'v32B0000000KWZ7YEP')
Result Generates a notification if f1, f2, or f3 have changed. Generates a notification if f1 or f2 have changed and f3 and f4 match the values in the WHERE clause. Generates a notification if f1 or f2 have changed and ID is contained in the WHERE clause IN list.
Generates a notification if f1 or f2 have changed, f3 and f4 match the values in the WHERE clause, and the ID is contained in the WHERE clause IN list.
NotifyForFields Set to Where When you set the value of PushTopic.NotifyForFields to Where, a change to any field value in the record as long as that field is referenced in the query WHERE clause causes the Streaming API matching logic to evaluate the record to determine if a notification should be generated. If the PushTopic.NotifyForFields value is Where, then the PushTopic query must have a WHERE clause with at least one field other than Id. Event Record is created Record is updated A notification is generated when The record field values match the values specified in the WHERE clause A change occurs in one or more record fields that are specified in the PushTopic query WHERE clause and The record values of the fields specified in the WHERE clause all match the values in the PushTopic query WHERE clause
Result Generates a notification if f3 or f4 have changed and the values match the values in the WHERE clause.
SELECT Id FROM InvoiceStatement__c Generates a notification if f3 or f4 have changed and the values match the WHERE f3 = 'abc' AND f4 LIKE 'xyz' values in the WHERE clause.
35
Notifications
PushTopic Query
SELECT Id, f1, f2 FROM InvoiceStatement__c WHERE f3 = 'abc' AND f4 LIKE 'xyz' AND Id IN ('a07B0000000KWZ7IAO', 'e10R0000000KEU9IAO', 'v32B0000000KWZ7YEP')
Result Generates a notification if f3 or f4 have changed, f3 and f4 match the values in the WHERE clause, and the record ID is contained in the WHERE clause IN list.
Notification Scenarios Following is a list of example scenarios and the field values you need in a PushTopic record to generate notifications. Scenario You want to receive all notifications of all record updates. Configuration You want to receive notifications of all record changes only when the Name or Amount fields change. For example, if youre maintaining a list view. You want to receive notification of all record changes made to a specific record. You want to receive notification only when the Name or Amount field changes for a specific record. For example, if the user is on a detail page and only those two fields are displayed. You want to receive notification for all invoice statement record changes for vendors in a particular state.
MyPushTopic.Query = SELECT Id, Name, Description__c FROM InvoiceStatement MyPushTopic.NotifyForFields = All MyPushTopic.Query = SELECT Id, Name, Amount__c FROM InvoiceStatement MyPushTopic.NotifyForFields = Referenced MyPushTopic.Query = SELECT Id, Name, Amount__c FROM InvoiceStatement WHERE Id='a07B0000000KWZ7IAO' MyPushTopic.NotifyForFields = All MyPushTopic.Query = SELECT Id, Name, Amount__c FROM InvoiceStatement WHERE Id='a07B0000000KWZ7IAO' MyPushTopic.NotifyForFields = Referenced MyPushTopic.Query = SELECT Id, Name, Amount__c FROM InvoiceStatement WHERE BillingState__c = 'NY' MyPushTopic.NotifyForFields = All MyPushTopic.Query = SELECT Id, Name FROM InvoiceStatement WHERE Amount > 999 MyPushTopic.NotifyForFields = Referenced
You want to receive notification for all invoice statement record changes where the invoice amount is $1,000 or more.
36
Bulk Subscriptions
Bulk Subscriptions
You can subscribe to multiple topics at the same time. To do so, send a JSON array of subscribe messages instead of a single subscribe message. For example this code subscribes to three topics:
[ { "channel": "/meta/subscribe", "clientId": "Un1q31d3nt1f13r", "subscription": "/topic/foo" }, { "channel": "/meta/subscribe", "clientId": "Un1q31d3nt1f13r", "subscription": "/topic/bar" }, { "channel": "/meta/subscribe", "clientId": "Un1q31d3nt1f13r", "subscription": "/topic/baz" } ]
37
Chapter 7
Streaming API Considerations
In this chapter ... Clients and Timeouts Clients and Cookies for Streaming API Supported Browsers HTTPS Recommended Debugging Streaming API Applications
Streaming API helps you create near real-time update notifications of your Salesforce data. This chapter covers some client and troubleshooting considerations to keep in mind when implementing Streaming API.
38
See Also:
Streaming API Considerations
39
Supported Browsers
See Also:
Streaming API Considerations
Supported Browsers
Streaming API supports the following browsers: Internet Explorer 8 and greater Firefox 4 and greater
See Also:
Streaming API Considerations
HTTPS Recommended
Streaming API follows the preference set by your administrator for your organization. By default this is HTTPS. To protect the security of your data, we recommend you use HTTPS.
See Also:
Streaming API Considerations
Using these tools, you can look at the requests, headers, body of the post, as well as the results. If you must contact us for help, be sure to copy and save these elements to assist in troubleshooting.
40
The first step for any debugging process is to follow the instructions in the Quick Start Using Workbench on page 6, Example: Visualforce Page on page 10, or Example: Java Client on page 15 and verify that you can implement the samples provided. The next step is to use your debug tool to help isolate the symptoms and cause of any problems.
See Also:
Streaming API Considerations
41
REFERENCE
Chapter 8
PushTopic
Represents a query that is the basis for notifying listeners of changes to records in an organization. This is available from API version 21.0 or later.
Supported Calls
REST: DELETE, GET, PATCH, POST (query requests are specified in the URI) SOAP: create(), delete(), describe(), describeSObjects(), query(), retrieve(), update()
Fields
Field
ApiVersion
Field Type Description double Required. API version to use for executing the query specified in Query. It must be an API version greater than 20.0. If your query applies to a custom object from a package, this value must match the package's ApiVersion. Example value: 24.0 Field Properties: Create, Filter, Sort, Update
CreatedById
ID
System field: ID of the User who created this record. Field Properties: Default on create, Filter, Group, Sort
CreatedDate
dateTime
System field: Date and time when this record was created. Field Properties: Create, Filter, Sort, Update
Description
string
Description of the PushTopic. Limit: 400 characters Field Properties: Create, Filter, Sort, Update
42
PushTopic
Field
ID
Field Type Description ID System field: Globally unique string that identifies a record. Field Properties: Default on create, Filter, Group, idLookup, Sort
isActive
boolean
Indicates whether the record currently counts towards the organization's limit. Field Properties: Create, Default on create, Filter, Group, Sort, Update
IsDeleted
boolean
System field: Indicates whether the record has been moved to the Recycle Bin (true) or not (false). Field Properties: Default on create, Filter, Group, Sort
LastModifiedById
ID
System field: Date and time when this record was last modified by a user. Field Properties: Default on create, Filter, Group, Sort
LastModifiedDate
dateTime
System field: Date and time when this record was last modified by a user. Field Properties: Default on create, Filter, Sort
Name
string
Required. Descriptive name of the PushTopic, such as MyNewCases or TeamUpdatedContacts. Limit: 25 characters. This value identifies the channel. Field Properties: Create, Filter, Group, Sort, Update
NotifyForFields
picklist
picklist
string
Required. The SOQL query statement that determines which record changes trigger events to be sent to the channel. Limit: 1300 characters Field Properties: Create, Filter, Sort, Update
SystemModstamp
dateTime
System field: Date and time when this record was last modified by a user or by a workflow process (such as a trigger). Field Properties: Default on create, Filter, Sort
43
PushTopic
44
Chapter 9
Streaming API Limits
Description Maximum number of topics Maximum number of clients (subscribers) per topic Maximum number of concurrent clients (subscribers) across all topics Maximum number of events per day Socket timeout during connection (CometD session) Timeout to reconnect after successful connection (keepalive) Timeout for session, regardless of activity (maximum CometD session) Maximum length of the SOQL query in the Query field of a PushTopic record Maximum length for a PushTopic name Limit 20 10 10 1,000 for free organizations; 100,000 for all other organizations 110 seconds 40 seconds 3600 seconds 1300 characters 25 characters
Note: To increase the number of clients per topic or the number of concurrent clients across all topics, please contact salesforce.com.
45
Index
Index
A
Authentication 25 using OAuth 2.0 25 using session ID 25
N
Notification rules 31 Notification scenarios 36 Notifications 31 NotifyForFields field 31 NotifyForOperations field 31
B
Bayeux protocol 4 Browsers supported 40 Bulk subscriptions 37
P
Push technology 4 overview 4 PushTopic 2829, 3235, 37 deactivating 37 NotifyForFields value All 32 NotifyForFields value Referenced 33, 35 NotifyForFields value Select 34 queries 29 security 29 working with 28 Object 42 PushTopic object 42
C
Client 39 timeout 39 Clients for Streaming API 39 CometD 4
D
Debugging Streaming API 40
E
Events 31 Example 7, 1013, 1617 Java client Step 1, create an object 7, 11, 16 Java client Step 2, create a PushTopic 7, 11, 16 Java client Step 3, download JAR files 17 Java client Step 4, adding source code 17 Visualforce client introduction 10 Visualforce client prerequisites 10 Visualforce client Step 1, create an object 7, 11, 16 Visualforce client Step 2, create a PushTopic 7, 11, 16 Visualforce client Step 3, create static resources 12 Visualforce client Step 4, create a Visualforce page 13 Visualforce client Step 5, test the PushTopic channel 13
Q
Queries 30 unsupported SOQL 30 Query 30 supported SOQL 30 Query in PushTopic 29 Quick start 6 using workbench 6 Quick Start 68, 11, 16 create an object 7, 11, 16 creating a push topic 7, 11, 16 prerequisites 6 subscribe to a channel 8 testing the PushTopic 8
H
HTTPS 40
S
Security 29 Stateless 5 Streaming API 3, 39 client 39 Getting started 3
J
JSON array for bulk subscriptions 37
L
Limits 45 Long polling 4
T
Terms 4 Timeouts 39
M
Message loss 5
U
Using the Streaming API 38
46