Tweet |
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):
1 2 | ConnectApi.MessageBodyInput messageInput = new ConnectApi.MessageBodyInput(); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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(); |
1 2 3 4 5 | 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:
1 2 3 4 5 6 7 8 | 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