Schedule multiple batch classes using single Schedule class

Schedule multiple batch classes using single Schedule class

Hi all,
Today we are going to discuss how we can schedule different batch classes for different time using single Schedule class. Till now I was creating new schedule class for each of my batch class.


/* Name : GlobalScheduler Date : 30 march 2018 Author : Arpit vijayvergiya Description : We are creating this class as global scheduler. So multiple batchclass can be scheduled with single scheduler. */ public class GlobalScheduler implements Schedulable{ public Database.Batchable<sObject> batchToBeSchedule; public Integer batchSize; public GlobalScheduler(Database.Batchable<sObject> batchToBeSchedule , Integer batchSize){ this.batchToBeSchedule = batchToBeSchedule; this.batchSize = batchSize; } public void execute(SchedulableContext sc){ Database.executeBatch(batchToBeSchedule,batchSize); } }


/* Name : AccountBatch Date : 30 march 2018 Author : Arpit vijayvergiya Description : We create this batch class to test GlobalScheduler class. */ global class AccountBatch implements Database.Batchable<sObject>{ global Database.QueryLocator start(Database.BatchableContext dbc){ return Database.getQueryLocator([SELECT Id,Name FROM Account LIMIt 10]); } global void execute(Database.BatchableContext dbc, List<SObject> listOfAccount) { system.debug('Account'+ listOfAccount); } global void finish(Database.BatchableContext dbc){ System.debug('Account batch finish'); } }


/* Name : ContactBatch Date : 30 march 2018 Author : Arpit vijayvergiya Description : We create this batch class to test GlobalScheduler class. */ global class ContactBatch implements Database.Batchable<sObject>{ global Database.QueryLocator start(Database.BatchableContext dbc){ return Database.getQueryLocator([SELECT Id,lastName FROM Contact LIMIt 10]); } global void execute(Database.BatchableContext dbc, List<SObject> listOfContact) { system.debug('Contact '+ listOfContact); } global void finish(Database.BatchableContext dbc){ System.debug('contact batch finish'); } }
How to schedule: We can not schedule this class using standard Salesforce UI. This is the only disadvantage I found till now. We need to schedule it using Apex code. We need to make a proper cron expression for that. There are some online tools available for creating cron expression. ie. CronMaker.

If you scheduled a batch class using this scheduler class and then again you need to schedule another batch class at the same time or different time. It will not affect any of our scheduled jobs.

Here is the snippets for scheduling single scheduler multiple time with multiple batches.

AccountBatch accBatch = new AccountBatch(); // Batch Class Name GlobalScheduler scheduler = new GlobalScheduler(accBatch,100); String sch = 00 + ' ' + 57 + ' ' + 15 + ' * * ?'; // this cron schedule batch class to be run at 3 pm 57 minute on daily basis System.schedule('Account Batch Scheduler', sch, scheduler); ContactBatch conBatch = new ContactBatch(); // Batch Class Name GlobalScheduler scheduler1 = new GlobalScheduler(conBatch,200); String sch1 = 00 + ' ' + 56 + ' ' + 15 + ' * * ?'; // this cron schedule batch class to be run at 3 pm 56 minute on daily basis System.schedule('Contact Batch Scheduler', sch1, scheduler1);


Platform Cache In Salesforce

Platform Cache In Salesforce

Hello All,

Thanks to all of you to give a great response to my last blog Release Notes Spring 18.
Today we are going to discuss Platform Cache in salesforce.So let’s start.

Why use cache:

To store data statically, that is being used frequently in our application.

Do not need to query data again and again. Or do not need to make API call, If we fetch data from a Third party API.

What is Platform Cache: Platform cache is a layer in which you store data to be accessed later in our application. Use of platform cache, make our application much faster. Before using platform cache, we need to create a partition and allocate space to it.

Type Of Platform Cache: There is two type of cache in salesforce.
1. Org Cache: It stores data org-wide. Anyone can access data in Org. Following classes are used to retrieve and put data if we use Org Cache.

2. Session Cache: Session cache stores data for an individual user and is tied to that user’s session. The maximum life of a session is 8 hours. Following classes are used to retrieve and put data, if we use Session Cache.

Where We can use Platform Cache: Platform Cache can be used everywhere in your code, where you use same data over and over. In the following case, Platform cache can be useful.

  • Want to hold temporary data, do not want to save it in the database but want to use on various pages.
  • Making expensive calculation (same calculation on same data) on every page.
  • User’s Shopping cart in the shopping site.

Cache Allocation By Editions:

Developer Edition (0 MB by Default), But can get 10 MB as a trial.

Enterprise Edition (10 MB by default)

Unlimited Edition (30 MB by default)

Performance Edition (30 MB by default)

Limitation of Platform Cache Salesforce :

  • Data is not persisted, So There is No guarantee of data loss.
  • Data is not encrypted in the cache.
  • Org Cache support concurrent read and write. So data can be overwritten. For example if a user put data in Org cache with key name and value is ‘Arpit’ and start using in application. But during this time period another user come and put value ‘Navin’ for key name. Then this value will be changed for both user.
  • Session cache can store value upto 8 Hours (or until session is lost)
  • Org cache can store value upto 48 Hours.
  • Maximum size of a single cached item (for put() methods) 100 KB

Create Partition :

Before starting to work on platform cache, we need to make a Partition of Platform Cache. Partitions allow us to distribute cache space, so we can better use it for our application. Caching data in specific partition ensures that data is not overwritten by another application.

Each partition has one session cache and one org cache segment and you can allocate separate capacity to each segment. Session cache can be used to store data for individual user sessions, and org cache is for data that any users in an org can access.

To create partitions Search Platform Cache in quick find box.

In developer edition, We have 0MB space. But it can be increased by using Request Trial Capacity button.

Once you get a confirmation mail. You are ready to create Partition. Click on New Platform Cache Partition.

Click on save to save the partitions.Values on Session Cache allocation and Org Cache allocation can be changed later also.

Now Let’s Put and retrieve data using platform cache.

To call Partition in apex code we use namespace.partitionName . ‘local’ as namespace can be used in both scenario if you have namespace enabled or not enable in your org.

In my case I have iarpit as namespace , In my code i am using local.ibirds and iarpit.ibirds both. (Here ibirds is name of partition we created)

I am doing a very simple example (Just like a Wizard page)  just to implement Platform cache.

I created 2 Visualforce page , and 2 different controller for them.

On the first page we take input in wrapper list and on another page we show that data. We do not insert data in database.

On CacheExample page we fill the data in wrapper list.

On next button click, we will display this data on CacheExampleNextPage.

To clear cache click on remove button. And reload page . On remove button I used following code.
Cache.SessionPartition orgPart = Cache.Session.getPartition('local.ibirds); orgPart.remove('myList')

CacheExample class:

/* Name : CacheExample Date : 1/02/2018 Author : Description : We are doing this as an example of Cache memor */ public class CacheExample{ public List<CacheWrapper> listOfCacheWrap{get;set;} public CacheExample(){ listOfCacheWrap = new List<CacheWrapper>(); listOfCacheWrap.add(new CacheWrapper(1,'',TRUE)); } public void addRow(){ listOfCacheWrap.add(new CacheWrapper(1,'',false)); } public PageReference nextPage(){ Cache.Session.put('local.ibirds.myList', listOfCacheWrap); return Page.CacheExamplePage1; } public class CacheWrapper{ public Integer index{get;set;} public String name{get;set;} public Boolean isQualified{get;set;} public CacheWrapper(Integer index, String name, Boolean isQualified){ this.index = index; = name; this.isQualified = isQualified; } } }

CacheExample Page:

<apex:page controller="CacheExample"> <apex:form > <apex:pageBlock > <apex:pageBlockButtons > <apex:commandButton value="Next Page" action="{!nextPage}"/> </apex:pageBlockButtons> <apex:pageBlockTable value="{!listOfCacheWrap}" var="objWrap"> <apex:column headerValue="Action"> <apex:commandButton value="Add" action="{!addRow}"/> </apex:column> <apex:column headerValue="Reg No."> <apex:inputText value="{!objWrap.index}"/> </apex:column> <apex:column headerValue="Name"> <apex:inputText value="{!}"/> </apex:column> <apex:column headerValue="Qualified"> <apex:inputCheckbox value="{!objWrap.isQualified}"/> </apex:column> </apex:pageBlockTable> </apex:pageBlock> </apex:form> </apex:page>

CacheExampleNext class:

/* Name : CacheExampleNext Date : 1/02/2018 Author : Arpit vijayvergiya Descriptio : In this class we will get the data from cache memory and display on another page. */ public class CacheExampleNext{ public List<CacheExample.CacheWrapper> newList{get;set;} public CacheExampleNext(){ newList = new List<CacheExample.CacheWrapper>(); // Get partition Cache.SessionPartition orgPart = Cache.Session.getPartition('iarpit.ibirds'); system.debug(orgPart); newList = (List<CacheExample.CacheWrapper>)orgPart.get('myList'); System.debug('newList '+newList); } public void remove(){ Cache.SessionPartition orgPart = Cache.Session.getPartition('local.ibirds); orgPart.remove('myList'); } }


<apex:page controller="CacheExampleNext"> <apex:form > <apex:pageBlock > <apex:pageBlockButtons > <apex:commandButton value="Remove" action="{!remove}"/> </apex:pageBlockButtons> <apex:pageBlockTable value="{!newList}" var="objWrap"> <apex:column headerValue="Reg No."> <apex:outputText value="{!objWrap.index}"/> </apex:column> <apex:column headerValue="Name"> <apex:outputText value="{!}"/> </apex:column> <apex:column headerValue="Qualified"> <apex:outputText value="{!objWrap.isQualified}"/> </apex:column> </apex:pageBlockTable> </apex:pageBlock> </apex:form> </apex:page>

In above Example I used Cache Session. If you want to use Cache Org then use Cache.Org class instead of Cache.Session and Cache.OrgPartition class instead of Cache.SessionPartition.
$Cache.Session Global Variable : Any value stored in Cache Session can directly be accessed on the Visualforce page by using $Cache.Session global Variable.

Here is Snippet of code:

<apex:outputText value="{!$Cache.Session.namespace.partitionName.key}"/>

If key value is List, then we can find size also to use it further on our page. (myList is key)

<apex:outputText value="{!$Cache.Session.namespace.partitionName.myList.size}"/>

Want to delete A Partition you created:  You can see that there is no delete button or link for
partition we created.

So then How we can delete partition if we found that it has no longer use for us.
Let’s click on edit button,Uncheck default checkbox button and save.

Thanks to all.

Spring 18 Release Notes My Favorite

Spring 18 Release Notes My Favorite

Hello Friends , Today I am going to talk about the what new features we are getting in Spring 18 Salesforce Release.

1. No need to set cookies to enable debug log for site guest user: In winter 17 salesforce made some changes, that to store Site guest user’s debug. We need to set the Cookies in browser using console(Browser) . Now it is removed , we do not need to set cookies to enable debug log for site guest user.

2. New Methods in List class :  Now we can check that an element is already exist in a list or not . and also we can find index of an element.

contains method :
List<String> listOfString = new List<String>(); listOfString.add(‘arpit’); system.debug(listOfString.contains(‘arpit’)); Output : True

IndexOf method :
List<String> listOfString = new List<String>(); listOfString.add(‘arpit’); system.debug(listOfString.indexOf(‘arpit’)); Output : 0
3.Einstein Language is now generally available: As Einstein Language is generally available we can analyze text and determine the user’s goals or the sentiment behind text. The Einstein Intent API categorizes unstructured text into user-defined labels for better understanding what users are trying to accomplish. This API can be used to analyze text from emails, chats, or web forms. The Einstein Sentiment API categorize text into positive, negative and neutral classes to understand feelings behind the text. It can be used to analyze social media post, feedbacks for services etc.

4. Use custom metadata type in validation rule formula : Now you can use custom metadata type in formula when create validation rule.


5. Delete Big Object Data(Using SOAP API): In my last post on Big Object In Salesforce , I mentioned that we cannot delete records from the big object. But now In Spring 18, we can delete records from Big objects too using Database.deleteImmediate() Method.
Declare a sObject, that contains all the fields of Big object’s index field. All row  matches with index values will be deleted.

6. Alert Users Before They’re Redirected Outside Salesforce: In quick find box search Session Setting. Under Redirection, Warn users before they are redirected outside of Salesforce. It’s done, when users click on any link inside org that redirect him outside the org, they see a warning that they are leaving the salesforce domain.

7. Upload Files Directly from a Flow : Now we can attach file with flow, with the help of lightning component. forceContent:fileUpload need to use this field and it’s configuration. It works only with lightning flow.

Upload a file from Flow.

8. Verify Community External Users’ Identity: Whenever a community user access community site form a new device or browser, we can verify his identity as an extra measure of security.
In Quick find box search profile, edit profile of external user, under session setting, select Verify identity when external users access Salesforce from new browser or device (device activation).

Profile showing Session Settings area

9. Generate Leads from LinkedIn: Automatically convert data into salesforce linked from LinkedIn Lead Gen advertisements. When prospective customers fill out a form on your LinkedIn ad. You can add up to 500 leads per day from linkedIn. If you exceed the limit, we will mail the additional leads to the default lead creator you defined in Setup.

10. Start Flows Dynamically from Apex : Earlier you could start a flow from apex, but you had to hardcode name of flow. Means for every flow you need to write different method . with createInterview() , you can write single method to call flow.
public void startFlow(String flowName, Map <String, Object> inputs) { Flow.Interview myFlow = Flow.Interview.createInterview(flowName, inputs); myFlow.start(); }

11. Delete Field History and Field Audit Trail Data : Delete from Field History Archive can be enabled now. In Quick find box , Search User Interface, and enable the permission ‘Enable Delete from field history and Delete From Field History Archive User Permission’.
List<FieldHistoryArchive> listOfFieldHistory = new List<sObject>(); listOfFieldHistory.addAll([SELECT FieldHistoryType, ParentId, CreatedDate, HistoryId FROM FieldHistoryArchive WHERE FieldHistoryType = 'Account' AND ParentId = '001d000000Ky3xIAB' AND CreatedDate = '2017-11-28T19:13:36.000z' AND HistoryId = '017D000000ESURXIA5']); Database.delete(listOfFieldHistory);