As documented in the Salesforce Summer 14 Release Notes, there are a number of activities that send a Salesforce1 notification to a user (assuming they haven’t disabled any), but all of these require manual actions to be taken via chatter. While playing around with some code to notify the owner of a Salesforce system that a new user had been created in their system, I wanted to be able to send a notification programmatically.
The least intrusive mechanism looked to be a post to my profile, with a mention to the user in question - “Keir Chatter” in my case. My first attempt at this was to simply create a FeedPost instance and set the body of the post to ‘@[Keir Chatter] a new user has been created’. Unfortunately, this simply placed the raw text ‘@[Keir Chatter]’ into the feed and didn’t get picked up as a mention at all.
After a little research, I realised that I needed to use the Chatter Connect API, specifically the version of the postFeedItem method that takes a ConnectApi.FeedItemInput as a parameter, as the documentation makes clear (the bold is mine):
postFeedItem(String, ConnectApi.FeedType, String, ConnectApi.FeedItemInput, ConnectApi.BinaryInput)
Adds a feed item to the specified feed from the context user Use this method to post rich text, including @mentions and hashtags, and to attach a file to a feed item. You can also use this method to share a feed item and add a comment.
Generating a FeedItemInput is a little more complex than simply adding a body property to a post - the mention and the message have to be constructed separately as segments and then attached. As I wanted this to be reusable, I created a utility method that would take a user id and message and take care of all the heavy lifting (the utility method also excludes attempts to notify yourself - i.e. to post an @mention to yourself on your own chatter feed):
ConnectApi.MessageBodyInput messageInput =
new ConnectApi.MessageBodyInput();
messageInput.messageSegments =
new List<ConnectApi.MessageSegmentInput>(); // create and add the mention segment ConnectApi.MentionSegmentInput mentionSegment =
new ConnectApi.MentionSegmentInput(); mentionSegment.id = userId; messageInput.messageSegments.add(mentionSegment); // create and add the message body segment ConnectApi.TextSegmentInput textSegment; textSegment = new ConnectApi.TextSegmentInput(); textSegment.text = message; messageInput.messageSegments.add(textSegment); // create the FeedItemInput and add the messageInput to it ConnectApi.FeedItemInput input =
new ConnectApi.FeedItemInput();
input.body = messageInput; // finally, post to the current user's feed ConnectApi.ChatterFeeds.postFeedItem(null,
ConnectApi.FeedType.News, 'me', input, null);
I then created a simple trigger to notify the user whose name begins with ‘keir.chatter’ when a new user is added to the system - note that this is a chatter free user - the user doesn’t need a full Salesforce license as the post isn’t associated with a Salesforce record:
trigger user_ai on User (after insert) { User notifyUser=[select id from User where username like 'keir.chatter%']; MentionUtils.NotifyUser(notifyUser.Id, ' a new user has been created - ' + trigger.new[0].username); }
Note that the trigger is set up to handle a single record at a time, purely for the purposes of this post. This does show up one weakness of this technique though, as there is no way to bulk post a number of messages at the time of writing (September 2014). If I needed to handle multiple records in this case I’d just post a large message containing information about all of the users that had been added. If I needed to notify a different user per record, I’d have to use some asynchronous processing (either @future or batch Apex) to avoid breaching governor limits.
Adding a new user to the system:
sends a notification to my chatter user:
accessing Salesforce1 shows the red bell indicating I’ve received a notification:
tapping the bell shows a summary of the post:
and finally, click on the notification takes me to the full post:
I’ve added this utility class and unit test to my SF1Utils github repository and unmanaged package that I created for an earlier post.
Interesting approach, going to try it soon. Though I believe this should be a native Apex api (with usual limits), how about posting it as a new idea ?
ReplyDeleteJust an update to this post, it appears that bulk has become much easier with the addition of ConnectApi.BatchInput: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/connectapi_examples_post_feed_element_batch.htm
ReplyDelete