Sunday, 17 June 2018

Einstein Bots | How to Setup Einstein Bot | Summer 18



Recently we did one online session on "Einstein Bots". If you are looking for recording you can check here. To use Einstein Bots you need to enable Live Agent. If you have not done it yet, read this Post for Live Agent.


Let see how to configure the same.

Step 1) Enable the Einstein Bot.
Click on Setup->Service -> Service Cloud Einstein -> Einstein Bot Then Enable it.



Step 2) Accept Term and Condition .


Step 3) Enable Live Agent Option.
Click on "Deployment Channels"


click on edit button and enable the bot for Live Agent.


Step 4) Create a new Bot.
Click on "New" button from My Bots section.



And then follow below step :-



Step 5) Lets create Dialogs.

Click on Dialog Menu from the Einstein Bots Builder.



Then Click on + button to create "New Dialogs".


All Set . Now Create a question


Click on Question icon and enter your question like below screen.


Then add new Slot.


Add some more question :)


NOTE:- Add some Choice this time. Click on "Add Choice" button.


Lets Create some rule to Response to end user. Click on Rule button from below screen.


Add Condition and action

NOTE:- I created one more Dialog "Pizza Restaurants". You can create the one more rule for Chinese as well.

Save your changes after click on save button


Step 6) Now set Dialogs in welcome bots.
Click on "Welcome" option from Einstein Bots Builder.


Step 7) Save and Activate.



Now you can test your Einstein Bot from Live Agent.





If you want to see the recording of out Apex Hour click here. Thanks Shruti for a great Demo in Salesforce Apex Hours.


Capture.JPG  @amit_sfdc    #SalesforceApexHours    @ApexHours

Thanks
Amit Chaudhary

Friday, 1 June 2018

Trigger.OperationType | System.TriggerOperation Enum | Salesforce Summer ’18 Release Notes

System.TriggerOperation Enum
This enum has the following values, which correspond to trigger events.
  • AFTER_DELETE
  • AFTER_INSERT
  • AFTER_UNDELETE
  • AFTER_UPDATE
  • BEFORE_DELETE
  • BEFORE_INSERT
  • BEFORE_UPDATE

Recently i created a post on Swtich Statement. Let see how we can use Swtich Statement and Enum in Trigger:-

trigger AccountTrigger1 on Account ( before Insert ,Before Update , After Insert, After Update) {
       switch on Trigger.OperationType  {
            when BEFORE_INSERT
            {
                System.debug('BEFORE_INSERT------>' + Trigger.OperationType );
                System.debug(Trigger.OperationType +'-Before Insert-->'+Trigger.isInsert+'--->'+Trigger.isBefore);
            }
            when AFTER_INSERT
            {
                System.debug('AFTER_INSERT ------->' +Trigger.OperationType );
                System.debug(Trigger.OperationType +'-After Insert-->'+Trigger.isInsert+'--->'+Trigger.isAfter);
            }
            when BEFORE_UPDATE, AFTER_UPDATE
            {
                System.debug('BEFORE_UPDATE or AFTER_UPDATE----->' +Trigger.OperationType );
            }
        }
}


Thanks,
Amit Chaudhary 

Friday, 25 May 2018

Switch Statement in Salesforce | Salesforce Summer ’18 Release Notes


Simplify Your Code with the Apex Switch Statement




Finally Swtich Statement is available in Salesforce with Summer 18.


Sample Code:-
public class  SwitchExample { 
    public static void testSwitchCase() {
        Integer i = 2;
        switch on i {
            when 1
            {
                System.debug('One------>');
            }
            when 2
            {
                System.debug('Two------->');
            }
            when else
            {
                System.debug('default----->');
            }
        }
    }
}
NOTE:- Please set the Apex code version as 43. 

 (This Image is from Salesforce documentation)


 Thanks
Amit Chaudhary

Thursday, 24 May 2018

Callouts from a Visualforce Page | Continuation | Asynchronous callouts from VF page




Most of the time got the requirement to do callout from VF page button. We can do the same with the help of Continuation method. An asynchronous callout is a callout that's made from a Visualforce page for which the response is came back through a callback methodology. An asynchronous callout is additionally referred to as a continuation.







(This Image is from Salesforce documentation)


Apex Class:-

public class AnimalsCallouts {

    // Unique label corresponding to the continuation
    public String requestLabel;
    public String result {get;set;}
    public List<Object> animals {get;set;}
    
    public AnimalsCallouts(){ 
        animals =new List<Object>();
    }

    
    public Object  makeGetCallout() {
        Continuation con = new Continuation(40);
        con.continuationMethod='processResponse';
    
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint('https://th-apex-http-callout.herokuapp.com/animals');
        request.setMethod('GET');
    
        // Add callout request to continuation
        this.requestLabel = con.addHttpRequest(request);
        // Return the continuation
        return con; 
    }
    
    public Object processResponse() {  
        HttpResponse response = Continuation.getResponse(this.requestLabel);

        // Set the result variable that is displayed on the Visualforce page
        if (response.getStatusCode() == 200) {
            this.result = response.getBody();
            Map<String, Object> results = (Map<String, Object>) JSON.deserializeUntyped(response.getBody());
            animals = (List<Object>) results.get('animals');
        }
        return null;
    }
        
}



NOTE:- Dnt forget to add Remote Site Setting for your URL.

Visual Force Page:-
<apex:page controller="AnimalsCallouts">
    <apex:form >
        <apex:pageBlock >
            <apex:pageBlockButtons >
                <apex:commandButton action="{!makeGetCallout}" value="GetCall" reRender="detail"/>
               
            </apex:pageBlockButtons>
            <apex:pageBlockSection id="detail" columns="1">
                 {!result }
                 <BR></BR>
                 <apex:pageBlockTable value="{!animals }" var="an">
                     <apex:column value="{!an}" headerValue="Response"/>
                 </apex:pageBlockTable>
                
            </apex:PageBlockSection>
       
        </apex:pageBlock>
   
    </apex:form>


</apex:page>


Output


If you want to learn about REST API check below post
http://amitsalesforce.blogspot.in/2017/01/learn-rest-api-in-salesforce-how-to.html





Thanks

Amit Chaudhary
@amit_SFDC


Sunday, 13 May 2018

REST API with XML and JSON | REST API with XML Payload | REST API with Dynamic Response

Issue:-
Recently i got one requirement to create one REST API which should support JSON and XML both. If we will pass JSON request body then response should come in JSON. But if we will send request body in XML then response should come in XML.

Solution:-
So here is solution :)

Global class REST_API_Helper{     public static blob formatResponse(ResponseBase ResponseBaseObj,String contentType){         String response;         String strContectType = contentType.toUpperCase();         if(strContectType.contains('XML')){             response = serializeRespinseBaseXml(ResponseBaseObj);         }             else {             response = JSON.serialize(ResponseBaseObj);         }         return blob.valueOf(response);     }     /*     *************************************************************************     * @description: This function is used to send the response in XML     * @return: string       *************************************************************************     */      public static string serializeRespinseBaseXml(ResponseBase ResponseBaseObj ){         String responseXML = '';         responseXML  += '<response>';         XmlStreamWriter w = new XmlStreamWriter();         w.writeStartElement(null , 'Message', null );         w.writeCharacters(ResponseBaseObj.Message);         w.writeEndElement();                  w.writeStartElement(null , 'Success', null );         w.writeCharacters(String.valueOf(ResponseBaseObj.Success));         w.writeEndElement();         responseXML += '</response>';         String xmlOutput = '<?xml version="1.0" encoding="UTF-8"?>' + '<Response>' + w.getXmlString()              + '</Response>';         w.close();         return xmlOutput ;     }     global class ResponseBase {         global Boolean Success {get;set;}         global String Message  {get;set;}         global ResponseBase(){                 success = true;                 message = 'Records are updated';         }     } }




@RestResource(urlMapping='/api/*/createContact')
global with sharing class RESTAPI_JSON_XML 
{
    @HttpPost 
    global static void doPost(ContactDetail  Detail) {
    
        RestResponse standardResp = RestContext.response;
        REST_API_Helper.ResponseBase  CustomeResponse = new REST_API_Helper.ResponseBase(); 
        ContactDetail reqBodyObj = Detail; 

        RestRequest req = RestContext.request;       
        String ContentType = RestContext.request.headers.get('Content-Type') ;
        
        Contact cont = new Contact();
        cont.FirstName = reqBodyObj.FirstName.trim();   
        cont.LastName  = reqBodyObj.LastName.trim();
        insert cont;
        
        CustomeResponse.Success = true;
        CustomeResponse.Message = 'Contact Created id ='+cont.id;
        standardResp.statusCode = 200;
        standardResp.responseBody = REST_API_Helper.formatResponse(CustomeResponse,ContentType); 
            
    }

    global class ContactDetail{
       global string FirstName {get;set;}
       global string LastName  {get;set;}
       public ContactDetail()  {}
    }
}



Sample JSON Example:-
Method:- Post
URL:- /services/apexrest/api/*/createContact
Request Body
{
   "Detail": {
                "FirstName":"Amit",
                "LastName" :"Chaudhary"
         }
}


Sample XML Example:-
Method:- Post
URL:- /services/apexrest/api/*/createContact
Request Headers:-
Content-Type: application/xml; charset=UTF-8
Accept: application/xml
Request Body
<?xml version="1.0" encoding="UTF-8"?>
<request>
    <Detail>
        <FirstName>566788</FirstName>
        <LastName>V00001397450513</LastName>
    </Detail>
</request>

Response :-
<?xml version="1.0" encoding="UTF-8"?><Response><Message>Contact Created id =0039000002SMSFJAA5</Message><Success>true</Success></Response>




Thursday, 22 March 2018

Big Object in Salesforce | Difference Between Custom Object and Big Object



What is Big Object :-

Object that stores and Manages Massive data values within Salesforce Without affecting performance. Big objects provide consistent performance for a billion records, and are accessible with a standard set of API's to your org or external system.

Custom big objects can be created by the Metadata API. To define a custom big object, you need to create an object file that contains its definition, field's, and index, with a Permission-set to define the permissions for each field, and  package file to define the contents of the object metadata


What Should Consider for Big Object

1) You need to use Metadata API to create Big Object.
2) Max 100 Big objects per org
3) Support's Date Time,Lookup,Number,Text,Long Text Area Field only
4) triggers, flows, processes, and the Salesforce app are unavailable.
5) Async SOQL is included only with the licensing of additional big object capacity
6) Support only object and field permissions
7) Does not Count against org data Storage limit
8) Suffixed with "_b".


Step to Create Big Object:-

You need to create the below three files.

Step 1) Create Big Object Files:-  

1) Create an Object File :- Defines the custom big object’s fields and index, Each custom big object needs its own object file.

My_First_Big_Object__b.object


<?xml version="1.0" encoding="UTF-8"?>
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
    <deploymentStatus>Deployed</deploymentStatus>

    <fields>
        <fullName>MyTextField__c</fullName>
        <label>My Text Field</label>
        <length>16</length>
        <required>false</required>
        <type>Text</type>
        <unique>false</unique>
    </fields>
   
    <fields>
        <fullName>Account_Lookup__c</fullName>
        <label>Account Lookup</label>
        <referenceTo>Account</referenceTo>
        <relationshipName>Account_Lookup</relationshipName>
        <required>true</required>
        <type>Lookup</type>
    </fields>
   
    <fields>
        <fullName>Date_Time__c</fullName>
        <label>Date Time</label>
        <required>true</required>
        <type>DateTime</type>
    </fields>
   
    <fields>
        <fullName>Number_Field__c</fullName>
        <label>Number Field</label>
        <required>false</required>
        <type>Number</type>
        <scale>2</scale>
        <precision>16</precision>
    </fields>

    <indexes>
        <fullName>MyFirstBigIndex</fullName>
        <label>My First Big Index</label>
        <fields>
            <name>Account_Lookup__c</name>
            <sortDirection>DESC</sortDirection>
        </fields>
        <fields>
            <name>Date_Time__c</name>
            <sortDirection>DESC</sortDirection>
        </fields>
    </indexes>
   
    <label>My First Big Object</label>
    <pluralLabel>My First Big Object</pluralLabel>
   
</CustomObject>


2) Create A Permissionset file :- with a Permissionset to define the permissions for each field

My_First_Big_Object.permissionset


<?xml version="1.0" encoding="UTF-8"?>
<PermissionSet xmlns="http://soap.sforce.com/2006/04/metadata">
    
    <fieldPermissions>
        <editable>true</editable>
        <field>My_First_Big_Object__b.MyTextField__c</field>
        <readable>true</readable>
    </fieldPermissions>
        
    <fieldPermissions>
        <editable>true</editable>
        <field>My_First_Big_Object__b.Number_Field__c</field>
        <readable>true</readable>
    </fieldPermissions>
    
    <label>My_First_Big_Object Permission Set</label>
   
</PermissionSet>




3) Create package.xml file :-  file to define the contents of the object metadata

package.xml


<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>*</members>
        <name>CustomObject</name>
    </types>
    <types>
        <members>*</members>
        <name>PermissionSet</name>
    </types>
    <version>41.0</version>
</Package>



Step 2) Deploy big object :-

1) Create the zip file for deployment.
Save all three file in one folder. Create the folder Structure like below



Add My_First_Big_Object__b.object file in Object Folder

Add My_First_Big_Object.permissionset file in permissionset Folder

package.xml file should in root of the folder.

2) Deploy with the help of Workbench or ANT tool.

2.1) Login on workbench
2.2) Click on Migration tool in workbench and select Single Package option like below image.



2.3) Now validate the big object in your Salesforce org.



How to insert a record 



My_First_Big_Object__b obj = new My_First_Big_Object__b();
obj.Account_Lookup__c ='0019000001ukhMF';
obj.Date_Time__c=System.now();
obj.MyTextField__c='hello';
obj.Number_Field__c=10;
database.insertImmediate(obj);


Query a record


 Difference Between Custom Object and Big Object



Custom Object
Big Object
Create
Manual and Metadata
Metadata
API Name
__c
__b
Track Activity
Yes
No Option
Field History Tracking
Yes
No Option
Data Type
All
Text, Date Time, Lookup, Number, Long Text Area
Edit Field
Yes
Yes
Delete Field
Yes
No
Trigger
Yes
No
Report
Yes
No
Storage
It Count Against Storage
It doesn’t count against Storage


Recently we did the session on Big Object in Salesforce Apex Hours.

Recording :- https://www.youtube.com/watch?v=gV1Oviqzry0&t=4691s



Please check below Trailhead module for more detail
1) https://trailhead.salesforce.com/en/modules/big_objects

Thanks
Amit Chaudhary