Sunday, May 13, 2018

Salesforce Streaming API


Introduction
It’s a procedure which observe data changes in Salesforce based on the SOQL query result and sends notifications to all the subscriber. These notifications, called as Push Notifications, can be received from a VF page, a server and Java client etc.
Streaming API uses the Bayeux protocol and the CometD messaging library. This is used for providing an asynchronous message by HTTP. Also, known as Long polling.


Setup Streaming API

1. Define PushTopic
Create a record for the “PushTopic” object, which is a standard object. A PushTopic enables you to define the object, fields, and criteria you’re interested in receiving event notifications for. These Push topic records also known as Channel. There is no OOB screen to create these record, it has to be created via code. Below is the code to create a PushTopic for custom Product object.



2. Connect to the PushTopic channel (Subscribe)
Connect to the PushTopic channel by utilizing JavaScript or Java library which can be downloaded from http://cometd.org/. At a time, you can subscribe to several PushTopic channels from one client.

Step By Step Guide For Java Client
https://developer.salesforce.com/docs/atlas.en-us.api_streaming.meta/api_streaming/code_sample_java_client_intro.htm

GitHub Resource
  1. https://github.com/forcedotcom/EMP-Connector/
  2. https://github.com/developerforce/SalesforceDurableStreamingDemo
  3. https://github.com/developerforce/StreamingReplayClientExtensions

Sample Response received at subscriber client


3. Sending Notification from the Server
Condition evaluation will take place every time the record of the object PushTopic query is referring to is created/updated or deleted.


Message Durability
As of API version 37.0, Salesforce stores events that match PushTopic queries, even if no one is subscribed to the PushTopic. The events are stored for 24 hours, and you can retrieve them at any time during that window.
Each event notification contains a field called replayId. The replay ID is unique for the org and channel. When you replay an event, you’re retrieving a stored event from a location in the stored stream. You can either retrieve a stream of events starting after the event specified by a replay ID, or you can retrieve all stored events.























Considerations & Limitations
  1. The SELECT statement’s field list must include Id.
  2. There is only one entity that can be referred for one query. A relation query is not supported.
  3. Aggregation query, COUNT, LIMIT, ORDER BY, GROUP BY, OFFSET and TYPEOF cannot be used. Also, a formula field can be specified in a SELECT phrase but not in a WHERE phrase.
  4. Long Text area and Rich text area field can’t be specified in Select statement though changes in such fields could still be tracked by setting pushTopic.NotifyForFields to “All”.  It means Long Text area and Rich text area field can’t be a part of Payload.
  5. For delete operation, salesforce streaming API doesn’t sends the full data of record in payload, it just sends Salesforce record Id. This makes the delete operation difficult at subscriber side if the external schema doesn’t stores the salesforce Id (which is less likely).


Streaming API Allocations
These default allocations are for basic consumers of Streaming API.

If your application exceeds these allocations, or you have scenarios for which you need to increase the number of concurrent clients, contact Salesforce.



References:
  1. https://trailhead.salesforce.com/en/modules/api_basics/units/api_basics_streaming
  2. https://developer.salesforce.com/docs/atlas.en-us.api_streaming.meta/api_streaming/limits.htm
  3. https://developer.salesforce.com/docs/atlas.en-us.api_streaming.meta/api_streaming/using_streaming_api.htm















Wednesday, October 5, 2016

Encrypt HTTP Request using MD5 in Apex:

 A typical enterprise uses many applications and many (most) of them don't work with each other directly. But, Once all related application are integrated, they produces the higher efficiency and greater level of operational consistencies.  Application provider need to invest time and money to built User interfaces, APIs, Security mechanism and many other background stuff so their applications could be integrated with others.

When it comes to Salesforce, its pretty rich to work with external system.

We came across an integration, where client wanted to integrate external system with Salesforce using restful Api which application vendors had already built.

This is the statement what we got from vendor:

To send a valid API signature, the user will need to perform a MD5 hash on both the API key, the API secret message, and the current Unix timestamp (in seconds). The key and secret are provided to the user. For example, in PHP, this can be accomplished thusly:

$signature = md5($api_key . $api_secret . time());


This is the code sample which shows, how MD5 digest could be generated in apex and used in integration.




Happy Integrations :)

Saturday, March 12, 2016

Idea object and relationship between its Zone and Record type:

Idea object in Salesforce is one of the most powerful object when it comes to collaboration and if we need employee/customers feedback for any new strategies & Implementations. For Idea implementation, please go through this guide:


Although this guide describe it nicely to setup the idea in org but it could be confusing and time consuming if we want any information at API level for any custom development. We did this in one of the project so wanted to list down all of the objects at API level which were involved in it.

Idea: It stores the body, file attachment, status, category and Zone and related Votes. 

IdeaComment: it stores all the information related to comments on any Idea record. 

Zone: This is a way to logically separate the Idea implementation in any org. Based on Zone we can decide the different values of Categories and Status fields. Often also referred as community. 

 VoteThis represents the user endorsements for idea and its comments. Now it could be +ve or -ve which could be identified by Type field of it. Same object is used to endorse Idea/Idea comment etc. So to get the specific type of votes we can use parent.type filter in query. E.g {{Parent.Type = 'IdeaComment'}}

 IdeaTheme: This is to collect the idea for any topic among the community members or employees. All the ideas which are submitted under any theme will be a child of it and associated via {{IdeaThemeID}} field of idea object. 

Zone and Record type:

Although both are different as they belongs to different object itself but somehow they are related to each other. The hint which tells us that they are related is, setting the idea picklist values based on Zone setup. However, for any other (or most of the) objects in Salesforce, it could be done only for record types. If we query any Idea record and see its recordTypeId, its certainly not same as its communityId(ZoneId).

We worked on a requirement, where we were supposed to show the list of idea on VF and they could be filtered based on Zone, Categories and Status picklist. Now there is no direct way to get the dependent options of picklist based on Zone selection.

Here comes the metadata API handy and allow us to describe the layout and get the results what we need. This is the working example of VF which gives the results in console. As shown in console image, within record type mapping the name what we are getting is Zone Name. So finally we had created an array of objects {{FinalResult}} which had the name as Zone name and all other picklist values as other nodes.



P.S. In this example it has been shown to get the Idea picklist values based on record type, although this could be used in general for any object when we build some custom application where can't be used. 

Custom HTML Attributes on Visualforce and usage of its for Dynamic Id

Although this is one of the old feature which Salesforce released a while ago but I think less explored one. As explained in this link, now we can use standard VF components E.g outPutpanel, inputText, selectList and use the custom attributes with them whenever needed. They are mostly useful when we use some external Jquery or angular libraries to have the expected behavior.

However, I used this to solve one of the common issue we faced when we are in  and we can't assign a dynamic Id to standard VF components because of known error:

Literal value is required for attribute id.

This is the VF page code with example of it,



I intentionally didn't make it complex so we can see the usage of custom attributes. Many a time situation comes where we are bind to use VF tags in and want to track the interaction with individual element and do some action based on which element we have interacted with. The most important part of it would be to get the Id. This example shows, how we can fetch the panel Id when we click on it using simple JS which works in all browser.

element.getAttribute(attrName);

with this custom attribute usage, we were able to assign the dynamic Id on {{did}} attribute and were able to fetch it.

The most common use case for this could be, multi edit page in salesforce. Where in each row, which are related to Saleforce record, one or other column need to be shown based on calculation of other columns. E.g total price of quote = quantity * Unit price.




Chatter:follow, its limitation and Hacky solution:

Building an Intranet application in Salesforce is one of my favourite areas and so far I have worked on more than 4 projects where we built a nice looking responsive Intranet application. Few clients decided to go fully custom and few decided to have the native look & feel with minimal code. For any Intranet, collaboration is the key and Salesforce gives us Chatter for it. Chatter is Facebook for Salesforce users and in last few years it got enhanced with addition of many new features.

To get in touch and stay connected in Intranet, we need to follow people or record so we know what's happening with them. Salesforce gives us standard VF component {{chatter:follow}} for it. The issue with this component is, we can't use it more than once on a page for same entity and that's the rude one when you build an Intranet page which had many components and contents are dynamically driven.

E.g In a page we have two widgets which shows, Upcoming Birthdays and Recent Recruits list. Now both the widgets could display same user and if standard {chatter:follow} component is being used, it will throw an error as:

Error: Multiple chatter:follow components are referring the same entity. 

To overcome this issue, one approach is to go fully custom and build own chatter follow component using custom styles(image/icons) and Apex handler method to create/delete EntitySubscription record. However, this would allow us to use it more than once on a page for same entity but create another issue of syncing. If you used this twice or more on same page, all references of same entity need to be in sync. For any entity, there would be two state Follow and Unfollow. If user presses a Follow button on one place then all references on the same page should get turned into Unfollow now. There is a way to do this by creating a JavaScript event broadcast & listener but that's too costly solution for it. To solve the core issue and avoid costly solutions, I created a custom component using Salesforce standard methods and elements what they use themselves. However, it’s a hack and could be broken, possibly, when Salesforce decides to change its own implementation but as of now this had been used in many projects and still working. Below is the code:


Above component will work even with standardStylesheets="false",showHeader="false" and this could be used multiple times without any issue of syncing as Salesforce handles that syncing part. These are three attributes of this component which need to be set while using it:
  • entityId = This would be Id of User/Record which need to be followed. E.g 00590000004OupA
  • networkId = This would be the Id of the network in which the container page would be running. For internal Salesforce it should be set as 000000000000000 and for community their Network Id should be passed.  
  • activityType = This need to be set on load and then rest would be taken care by component. Possible value is follow or unfollow. This could be decided by querying the EntitySubscription object for the entity in context. 

Here is the code example of using it.


Now the one important part is, to make this hack work we should have any one of the standard chatter component present on the page. This requires to instantiate {{SfdcApp.Chatter}} class so {{SfdcApp.Chatter.SubscribeButton}} method will work. We can simply add one place holder (any chatter standard component) with some realistic entityId and make that block display none. P.S. All Ids are of my Dev org Ids, you need to replace them with actual while using it. This hack might not work in Lightning experience as it has not been tested there. Other hacks: - Similarly custom screen could be built for for Join/leave the chatter group with hacks using SfdcApp.ChatterGroupMembership.join() and SfdcApp.ChatterGroupMembership.leave(). - Similar way, we have a method for like/unlike Feed post or Feed comment as well. Try to see them using inspect element :)