Code Way You to start with creating a Salesforce custom notification, enable Lightning Experience & Mobile App notifications!!
Custom Notification is very important to send alerts on desktop and/or mobile & keep your users in the know when important. Sometimes it is necessary to use custom Apex code instead using Process Builder or Flow.
Here I tried to write code with schedular to run autonomously as cron job by Apex Schedular Class.
This Example will show how to trigger Alert to an Opportunity owner in day to Opportunity Closing date , or this class can be reused for any objects with custom message with minimum required re coding. I have in Included Test Class too .
Before you send a custom notification, you must first create a notification type:
How to create a Notification Type :
To send custom notifications via a process in Process Builder, a Flow in Flow Builder, or invocable action API you must Create notification types.
Supported REST HTTP Methods
* This object is available in API version 46.0 and later.
- URI
- /vXX.X/actions/standard/customNotificationAction
- Formats
- JSON, XML
- HTTP Methods
- GET, HEAD, POST
- Authentication
- Authorization: Bearer token
Inputs
Input Details customNotifTypeId - The ID of the Custom Notification Type being used for the notification.
recipientIds - The ID of the recipient or recipient type of the notification.
- UserId — The notification will be sent to this user, if this user is active.
- Values can be combined in a list up to the maximum of 500 values.
senderId - The User ID of the sender of the notification.
title - The title of the notification, as it will be seen by recipients. Maximum characters: 250.
body - body of the notification, as it will be seen by recipients. Maximum characters: 750.
targetId - The Record ID for the target record of the notification.
Sample Output:
Class CustNotify will get Notification Type Id, Generate JSON and call REST API to Trigger Bulk/single Notification for Object Owner !!
- String NotifTypeID = [SELECT Id FROM CustomNotificationType WHERE DeveloperName = :NotifiDeveloperName].Id;
above SOQL will get Notification Type Id by passing Notification Developer Name.
- Here is the Code Example :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public with sharing class CustNotify { | |
public static void (String NotifiDeveloperName, list<sObject> lstObjects, String NotifTitle, String NotifBody) { | |
String NotifTypeID = | |
[SELECT Id FROM CustomNotificationType WHERE DeveloperName = :NotifiDeveloperName].Id; | |
if(!lstObjects.isEmpty()) { | |
JSONGenerator jsAttr = JSON.createGenerator(true); | |
jsAttr.writeStartObject(); | |
jsAttr.writeFieldName('inputs'); | |
jsAttr.writeStartArray(); | |
for(sObject obj : lstObjects) { | |
jsAttr.writeStartObject(); | |
jsAttr.writeStringField('customNotifTypeId', NotifTypeID); | |
jsAttr.writeFieldName('recipientIds'); | |
jsAttr.writeStartArray(); | |
jsAttr.writeId((Id)obj.get('OwnerId')); | |
jsAttr.writeEndArray(); | |
jsAttr.writeStringField('title', (String)obj.get('Name') + NotifTitle); | |
jsAttr.writeStringField('body', (String)obj.get('Name') + NotifBody); | |
jsAttr.writeStringField('targetId', (String)obj.get('Id')); | |
jsAttr.writeEndObject(); | |
} | |
jsAttr.writeEndArray(); | |
jsAttr.writeEndObject(); | |
String strJson = jsAttr.getAsString(); | |
String strPOSTURL = 'actions/standard/customNotificationAction'; | |
String strPostResponse = httpRequest(strPOSTURL, 'POST', strJson); | |
} | |
} | |
//HTTP Call out | |
public static String httpRequest(String strResourceName, String strMethod, String strBody) { | |
String response; | |
String strEndPonitURL = URL.getSalesforceBaseUrl().toExternalForm() + '/services/data/v46.0/' + strResourceName; | |
if(String.isNotBlank(strResourceName)) { | |
HttpRequest httpRequest = new HttpRequest(); | |
httpRequest.setMethod(strMethod); | |
httpRequest.setHeader('Authorization', 'OAuth ' + UserInfo.getSessionId()); | |
httpRequest.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionID()); | |
if(String.isNotBlank(strBody)) { | |
httpRequest.setBody(strBody); | |
httpRequest.setHeader('Content-Type', 'application/json'); | |
httpRequest.setHeader('Accept', 'application/json'); | |
} | |
httpRequest.setEndpoint(strEndPonitURL); | |
try { | |
Http http = new Http(); | |
HttpResponse httpResponse = http.send(httpRequest); | |
if (httpResponse.getStatusCode() == 200 ) { | |
response = httpResponse.getBody(); | |
} | |
else { | |
throw new CalloutException(httpResponse.getBody()); | |
} | |
} | |
catch(Exception ex) { | |
throw ex; | |
} | |
} | |
return response; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public with sharing class CustNotifyScheduledCron implements Schedulable{ | |
public static void execute(SchedulableContext SC) { | |
list<Opportunity> listOpps = [SELECT Id, Name, OwnerId FROM Opportunity WHERE CloseDate =:Date.today()]; | |
CustNotify.sendCustomNotification | |
('Custom_Notification_on_Date_Ending', listOpps, ' Opportunity Closed Date is Today ' , ' Closed Date '+Date.today()); | |
} | |
} |
- And my use case was to execute Every Midnight to schedule to Notify Opportunity Owners .
System.schedule('Scheduled CustNotify', '0 0 0 * * ?', new CustNotifyScheduledCron ());
Here is the Test Class
- Ref:
- https://developer.salesforce.com/docs/atlas.en-us.api_action.meta/api_action/actions_obj_custom_notification.htm
- https://help.salesforce.com/articleView?id=notif_builder_custom_type.htm&type=5
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@isTest | |
public with sharing class TestCustNotify { | |
@TestSetup | |
static void insertNewOpportunity() { | |
Account objAccount = new Account(Name = 'Test Acc1', BillingCity = 'Test City', BillingState = 'Test State', | |
BillingStreet = 'Test Street', BillingPostalCode = '12345', | |
BillingCountry = 'Test Country', Phone = '123456'); | |
insert objAccount; | |
Opportunity objOpp = new Opportunity(Name = 'Test Opp', AccountId = objAccount.Id, StageName = 'Verbal Confirmation', CloseDate = Date.today()); | |
insert objOpp; | |
} | |
@IsTest | |
static void methodTest() { | |
Test.startTest(); | |
SchedulableContext sc = null; | |
try { | |
CustNotifyScheduledCron.execute(sc); | |
}catch(Exception e) { | |
} | |
Test.stopTest(); | |
} | |
} |
Very helpful content for SF developers. Thanks for sharing.
ReplyDeleteThanks for sharing Zakir.
ReplyDeleteShall we try this without target id.I would like to send a notifications to admin users about my appexchange app release info.
also, is body field is supported to html body?
Please help me.
Hi Ramugadu,
DeleteThanks for your findings .. However your requirements might not support right now but once I have any outcomes I’ll let you know.
targetId is a Required. The Record ID for the target record of the notification.
And the notification not supported html content.
Your can send email notification for your Use Case.