Sunday, October 30, 2022

How to use @HttpGet annotation with parameters in URL in salesforce?

 Below is an example of webservice which need id or any unique identifier as a parameter in request and it will return record associated with it.

@RestResource(urlMapping='/getAccountOnExternalIdtofetchsinglerecord/*')

global with sharing class getAccounttoSingleRecord {

      @Httpget

      global static String fettringchAccount(){

      Account obj=new Account();

      RestRequest req = RestContext.request;

      RestResponse res = Restcontext.response;

      string accId = req.requestURI.substring(req.requestURI.lastIndexOf('/')+1);

      obj=[Select id , name from Account where id=:accId];

      string serializeResponse=JSON.Serialize(obj);

      return serializeResponse;

      }

   }

  • The above web service will be accessible at below URL with GET method from external system after successful authentication.

'https://instance.salesforce.com/services/apexrest/getAccountOnExternalIdtofetchsinglerecord/' + externalAccId;

Now, what if we want to pass more than one parameter in request URL.

In this case we can use params variable of RestRequest class.

The params returns the parameters that are received by the request.

The return type is of Type: Map<String, String>.

 Below is an example of webservice which need email and phone as a parameter in request and it will return contact record associated with it.

@RestResource(urlMapping='/getContactFromEmailAndPhone/*')

   global with sharing class getContactRecord {

        @Httpget

      global static Contact fetchContact(){

        Contact obj=new Contact();

        RestRequest req = RestContext.request;

        RestResponse res = Restcontext.response;

        Map<String, String> requestParam = req.params;

        String conEmail=requestParam.get('email');

        String conPhone=requestParam.get('phone');

        obj=[Select id,lastname,email,phone from contact where email=:conEmail and phone=:conPhone];

       /***Modify the HTTP status code that will be returned to external system***/

        res.statuscode=201;

       /***Modify the HTTP status code that will be returned to external system***/

        return obj;

      }

   }

The above webservice will be accessible at,

/services/apexrest/getContactFromEmailAndPhone?email=testemail2@gmail.com&phone=123

Let's try to test the webservice from workbench as shown below and let's see the result.

How to use @HttpGet annotation with parameters in URL in salesforce?

Saturday, October 29, 2022

Apex trigger to avoid insertion of duplicate contact in salesforce

 In this blog we will learn how to prevent insertion of duplicate contact in salesforce when a contact already exist in salesforce with same email.

TriggerHandler class.

An interface is a class where we create method signatures but body of the method is not
defined.

public interface TriggerHandler {

    void beforeInsert(List<SObject> newRecordsList);

    void beforeUpdate(List<SObject> oldRecordsList, List<SObject> newRecordsList, Map<ID, SObject> oldRecordsMap, Map<ID, SObject> newRecordsMap);

    void beforeDelete(List<SObject> oldRecordsList, Map<ID, SObject> oldRecordsMap);

    void afterDelete(List<SObject> oldRecordsList, Map<ID, SObject> oldRecordsMap);

    void afterInsert(List<SObject> newRecordsList, Map<ID, SObject> newRecordsMap);

    void afterUpdate(List<SObject> oldRecordsList, List<SObject> newRecordsList, Map<ID, SObject> oldRecordsMap, Map<ID, SObject> newRecordsMap);

    void afterUndelete(List<SObject> newRecordsList, Map<ID, SObject> newRecordsMap);

}


The handler class will implement the above interface.

Trigger Handler Class:

public without sharing class ContactTriggerHandler implements TriggerHandler {

   ContactTriggerHelper helperClass = new ContactTriggerHelper();

    public void beforeInsert(List<Contact> newConList) {

        helperClass.methodToHandleBeforeInsert(newConList);

    }

    public void beforeUpdate(List<Contact> oldConList, List<Contact> newConList, Map<ID, SObject> oldConMap, Map<ID, SObject> newConMap) {

         helperClass.methodToHandleBeforeUpdate();

    }

    public void beforeDelete(List<Contact> oldConList, Map<ID, SObject> oldConMap) {

        helperClass.methodToHandleBeforeDelete();

    }

    public void afterDelete(List<Contact> oldConList, Map<ID, SObject> oldConMap) {

        helperClass.methodToHandleAfterDelete();

    }

    public void afterInsert(List<Contact> newConList, Map<ID, SObject> newConMap) {

        helperClass.methodToHandleAfterInsert();

    }

    public void afterUpdate(List<Contact> oldConList, List<Contact> newConList, Map<ID, SObject> oldConMap, Map<ID, SObject> newConMap) {

      helperClass.methodToHandleAfterUpdate();

    }

    public void afterUndelete(List<Contact> newConList, Map<ID, SObject> newConMap) {

      helperClass.methodToHandleAfterUndelete();

    }

}

Now, Let's define our helper class.

Trigger Helper Class:

public without sharing class ContactTriggerHelper {

    public void methodToHandleBeforeInsert(List<Contact> newConList) {

        System.debug('Inside methodToHandleBeforeInsert');

        Set<string> emailOfIncomingContacts = new Set<String>();

        // Storing incoming contact email in set of string

        Set<string> existingConCheckFromDatabaseWithIncomingEmail = new Set<string>();

        for(Contact con:newConList){

        emailOfIncomingContacts.add(con.email);

        }

        // Querying contact from database to check if any contact exist with incoming email

        for(Contact con2:[SELECT id,email from Contact where email in:emailOfIncomingContacts]){

        existingConCheckFromDatabaseWithIncomingEmail.add(con2.email);

        }

             // Preventing duplicate contact from getting inserted in database.

        for(Contact con3:newConList){

           if(existingConCheckFromDatabaseWithIncomingEmail.contains(con3.email)){

           con3.addError('Contact already exists in database with email'+con3.email);

           }

        }

    }

    public void methodToHandleBeforeUpdate() {

        System.debug('Inside methodToHandleBeforeUpdate');

    }

    public void methodToHandleBeforeDelete() {

        System.debug('Inside methodToHandleBeforeDelete');

    }

    public void methodToHandleAfterDelete() {

        System.debug('Inside methodToHandleAfterDelete');

    }

    public void methodToHandleAfterInsert() {

 

        System.debug('Inside methodToHandleAfterInsert');

    }

    public void methodToHandleAfterUpdate() {

        System.debug('Inside methodToHandleAfterUpdate');

    }

    public void methodToHandleAfterUndelete() {

        System.debug('Inside methodToHandleAfterUndelete');

    }

}


Below is the list of contact in my database,

Apex trigger to avoid duplicate contact in salesforce

Now, let's try to insert 10 contact out of which 2 will have the email which is already existing in database.

CSV file is shown below.

Trigger to avoid duplicates in Salesforce


Now, let's try to insert the above 1o contact list from workbench and see the result as shown below.

Apex trigger to avoid duplicate contact in salesforce

Saturday, October 15, 2022

Lightning-progress-indicator in lwc with example

 In this blog post we will learn about "Lightning-progress-indicator in lwc".

A lightning-progress-indicator component displays steps horizontally. It indicates the number of steps in a given process, the current step, as well as prior steps which is completed.

Steps are created using lightning-progress-step component along with label and value attributes. The current step is specified using the current-step attribute, The current step must match one of the value attributes on a lightning-progress-step component as shown below.

  • Set type="base" to create a component that implements the progress indicator blueprint in the Lightning Design System. 

          A progress indicator component communicates to the user the progress of a particular process.
     

  • Set type="path" to create a component that implements the path blueprint in the Lightning Design System. 
          The Path communicates to the user the progress of a particular process.

  • If the type is not specified, the default type base is used. 

<template>

    <lightning-progress-indicator type="path" current-step="account">

        <lightning-progress-step label="Account" value="account">

        </lightning-progress-step>

        <lightning-progress-step label="Contact" value="contact">

        </lightning-progress-step>

        <lightning-progress-step label="Opportunity" value="opportunity">

        </lightning-progress-step>

    </lightning-progress-indicator>

</template>


Let us take an example for detail understanding.

lightningprogressindicator.html

<template>

    <div class="slds-theme_default">

        <div class="slds-p-around_medium">

    <lightning-progress-indicator type="path" current-step={selectedStep}>

        <lightning-progress-step label="Account" value="account" onclick={selectStepAccount}>

        </lightning-progress-step>

        <lightning-progress-step label="Contact" value="contact" onclick={selectStepContact}>

        </lightning-progress-step>

        <lightning-progress-step label="Opportunity" value="opportunity" onclick={selectStepOpportunity}>

        </lightning-progress-step>

    </lightning-progress-indicator>

   

    <div class="slds-m-vertical_medium">

    <lightning-button label="Next" onclick={nextStep}></lightning-button>

    <lightning-button label="Previous" onclick={previousStep}></lightning-button>

</div>

</div>

</div>

</template>


lightningprogressindicator.js

import { LightningElement, track } from 'lwc';

 

export default class Lightningprogressindicator extends LightningElement {

    @track selectedStep ='account';

    nextStep(){

    var moveToNextStep = this.selectedStep;

    if(this.selectedStep == 'contact'){

        alert('Next step is opportunity');

        this.selectedStep = 'opportunity';

    }

    else if(this.selectedStep == 'account'){

        alert('Next step is contact');

        this.selectedStep = 'contact';

    }

    }

    previousStep(){

        var moveToPreviousStep = this.selectedStep;

        if(this.selectedStep == 'contact'){

            alert('Previous step is account');

            this.selectedStep = 'account';

        }

        else if(this.selectedStep == 'opportunity'){

            alert('Previous step is contact');

            this.selectedStep = 'contact';

        }

    }

     selectStepAccount(){

        alert('Selected step is account');

        this.selectedStep = 'account';

    }

     selectStepContact(){

        alert('Selected step is contact');

        this.selectedStep = 'contact';

    }

     selectStepOpportunity(){

        alert('Selected step is opportunity');

        this.selectedStep = 'opportunity';

    }

}


lightningprogressindicator.js-meta.xml

<?xml version="1.0" encoding="UTF-8"?>

<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">

    <apiVersion>55.0</apiVersion>

    <isExposed>true</isExposed>

    <targets>

        <target>lightning__AppPage</target>

        <target>lightning__RecordPage</target>

        <target>lightning__HomePage</target>

    </targets>

</LightningComponentBundle>


Now, let's add it to record page to see the result.

Lightning-progress-indicator in lwc with example

Now, click on "Next" button.


Lightning-progress-indicator in lwc

Wednesday, October 5, 2022

What is RestResponse class in salesforce?

We use the RestResponce class to pass data from an apex RESTful web service method to an HTTP response.

Below are the method available with RestResponse class.

1) responseBody

Returns or sets the body of the response.

The return type is of Type: Blob.

2) headers

Returns the headers to be sent to the response.

The return type is of Type: Map<String, String>.

3) statusCode

Returns or sets the response status code.

The return type is of Type: Integer.

Note: If we set the RestResponse.statusCode property to a value that's not listed in below table then an HTTP status of 500 is returned with the error message “Invalid status code for HTTP response: nnn” where nnn is the invalid status code value.

Status Code  Description

200         OK

201         CREATED

202         ACCEPTED

204         NO_CONTENT

206         PARTIAL_CONTENT

300         MULTIPLE_CHOICES

301         MOVED_PERMANENTLY

302         FOUND

304         NOT_MODIFIED

400         BAD_REQUEST

401         UNAUTHORIZED

403         FORBIDDEN

404         NOT_FOUND

405         METHOD_NOT_ALLOWED

406         NOT_ACCEPTABLE

409         CONFLICT

410         GONE

412         PRECONDITION_FAILED

413         REQUEST_ENTITY_TOO_LARGE

414         REQUEST_URI_TOO_LARGE

415         UNSUPPORTED_MEDIA_TYPE

417         EXPECTATION_FAILED

500         INTERNAL_SERVER_ERROR

503         SERVER_UNAVAILABLE

Now, let us try to understand with an example.

Let us try to call the below webservice from workbench.

Below is an example of webservice which need id or any unique identifier as a parameter in request and it will return record associated with it.

@RestResource(urlMapping='/getAccountOnExternalIdtofetchsinglerecord/*')

   global with sharing class getAccounttoSingleRecord {

        @Httpget

      global static Account fettringchAccount(){

        Account obj=new Account();

        RestRequest req = RestContext.request;

        RestResponse res = Restcontext.response;

        string accId = req.requestURI.substring(req.requestURI.lastIndexOf('/')+1);

        obj=[Select id , name from Account where id=:accId];

        //string ser=JSON.Serialize(obj);

        return obj;

      }

   }


What is RestResponse class in salesforce?

Click "Execute" button and now click "Show Raw Response".

As we can see as the operation of calling this webservice is successfull the HTTP status code returned is 200 by default and now based on requirement of external system if we want to modify the HTTP status code we can do it by using RestResponse class as shown below.

@RestResource(urlMapping='/getAccountOnExternalIdtofetchsinglerecord/*')

   global with sharing class getAccounttoSingleRecord {

        @Httpget

      global static Account fettringchAccount(){

        Account obj=new Account();

        RestRequest req = RestContext.request;

        RestResponse res = Restcontext.response;

        string accId = req.requestURI.substring(req.requestURI.lastIndexOf('/')+1);

        obj=[Select id , name from Account where id=:accId];

       /***Modify the HTTP status code that will be returned to external system***/

        res.statuscode=201;

       /***Modify the HTTP status code that will be returned to external system***/

        return obj;

      }

   }

Now, Let us try to call the below webservice from workbench.

As we have modified the statuscode to 201 using RestResponse class, we are now able to see the HTTP status code that is returned is 201.

RestResponse class salesforce

What is RestRequest class in salesforce?

We use the RestRequest class to access incoming request in apex rest webservice.

Below are the method available with RestRequest class.

1) headers

Returns the headers that are received by the request.

The return type is of Type: Map<String, String>.

2) httpMethod

Returns one of the supported HTTP request methods.

The return type is of Type: String.

Possible values returned are:

  • DELETE
  • GET
  • HEAD
  • PATCH
  • POST
  • PUT

3) params

Returns the parameters that are received by the request.

The return type is of Type: Map<String, String>.

4) remoteAddress

Returns the IP address of the client making the request.

The return type is of Type: Map<String, String>.

5) requestBody

Returns or sets the body of the request.

The return type is of Type: Blob.

6) requestURI

Returns or sets everything after the host in the HTTP request string.

The return type is of Type: String.

7) resourcePath

Returns the REST resource path for the request.

The return type is of Type: String.

Now, let us try to understand with an example.

Let us try to call the below webservice from workbench.

Below is an example of webservice which need id or any unique identifier as a parameter in request and it will return record associated with it.

I have put system.debug statements in webservice to debug the "headers" and "httpMethod".

@RestResource(urlMapping='/getAccountOnExternalIdtofetchsinglerecord/*')

   global with sharing class getAccounttoSingleRecord {

        @Httpget

      global static Account fettringchAccount(){

        Account obj=new Account();

        RestRequest req = RestContext.request;

        RestResponse res = Restcontext.response;

        System.debug('Request Headers-->'+req.headers);

        System.debug('Request Method-->'+req.httpMethod);

        System.debug('Request Body-->'+req.requestBody);

        string accId = req.requestURI.substring(req.requestURI.lastIndexOf('/')+1);

        obj=[Select id , name from Account where id=:accId];

        //string ser=JSON.Serialize(obj);

        return obj;

      }

   }





What is RestRequest class in salesforce?