Summer 18 release notes my favorite


Summer 18 release notes my favorite

Hi, all today I am going to discuss some cool and new features provided by Salesforce in Summer 18 release notes. At the time of writing this blog, Summer18 release was in preview mode so we are not sure that all these will work exactly after full release.

  1. Switch Statement: Now apex provides the switch statement. The syntax is very much similar to Java.

Syntax: 

switch on expression {
    when value1 { // when block 1
        // code block 1
    }
    when value2 { // when block 2
        // code block 2
    }
    when value3 { // when block 3
        // code block 3
    }
    when else {   // when else block, optional
        // code block 4
    }
}

We can also use multiple values for a single block.
Ex.
When value1,value2{
//code block executes
}

If no when value match with expression then else block is executed, if no else block then no execution.

There is no break for the switch just like java. When a code block is executed, the switch block is automatically exit.

Apex switch statement expressions can be one of the following types.
Integer
Long
sObject
String
Enum

Example :
Integer age = 10;
switch on age {
   when 10 {
       System.debug('when age 10');
   }
   when 18 {
       System.debug('when age 18');
   }
   when else {
       System.debug('default');
   }
}


2.Apex code size limit increased:
The total amount of code you can use in your org is going to be increased from Summer 18, it will be 6 MB instead of 3 Mb. If your org was already approved for 6 MB then it will remain unchanged.

3.Speed up Apex Test Runs: Now we can speed up apex test runs if we do not want to collect the code coverage information during the test run.
It can be helpful in such case we are running our test class to check wheater it passes or fails for a condition.

What we need to do.
From Setup, search for Apex Test Execution. Choose Select Tests, and select Skip Code Coverage.
From the Developer Console, select Test | New Run | Settings | Skip Code Coverage.

4.The SOQL Count() Function Doesn’t Count (As Much) Toward Limits: In apex, we have governer limits against the total number of records we can retrieve in a query. Before Summer18 release, each individual record matches with count and count(fieldname) function was counted against the apex query row limit.
But From summer18 salesforce is going to simplify it. From now if a query using these functions returns an Integer, It will be counted as 1 query row for governer limit.
Let's understand with some examples.

Integer noOfContacts = [SELECT COUNT() FROM Contact WHERE Account.Name = 'iBirds Services'];

Before Summer18 the no of records matched by the query was counted towards query row limit. But now it will be counted as single query row.

Integer noOfContacts = [SELECT COUNT() FROM Contact WHERE Account.Name = 'iBirds Services'];

If a query with COUNT(fieldName) function contains a GROUP BY clause, only the number of resulting AggregateResult objects count toward the limit. For example, in the query in the following 

example, only one item per aggregated result is counted toward the limit.

List<AggregateResult> listOfAgrResult = [SELECT COUNT(id) FROM Contact GROUP BY AccountId];

5.Enable Debug mode for a user who really need it: As we know that Salesforce is slow in debug mode.In the previous release debug mode was an org-wide setting. But from summer18 we can enable debug mode for the particular user.

To enable debug mode for users in your org, go to the new Debug Mode Users page in Setup. Find the relevant users in the list, check the box next to their name, and click Enable. To turn debugging off, click Disable.






6.Component CSS Class Names Updated: This will affect the lightning component. The class name that uses double dash now uses single underscore instead of a double dash. ie.slds-p-around--small becomes slds-p-around_small.

7.lightning:insertImageButton : This component required minimum API version 43.0. This component adds an image button in the toolbar of lightning:inputRichText. You can use this component only as a sub-component of lightning:inputRichText component.


8.lightning:recordForm: Instead of using lightning:recordViewForm and lightning:recordEditForm , now we can use lightning:recordForm.  We can set ‘mode’ attribute to view, edit or read-only to specify for which purpose we are using this form.

Ex. if we use mode= “edit” form will be like this.



9.Lightning:datatable supports mass inline editing: As we all know that lightning:datatable is a very powerful component to display record in a tabular format. Now it supports mass inline editing. We need to set editable property as true for a cell. 10.Enable Access to Metadata Without Enabling Access to Data(beta): If a user needs access to modify the metadata but not to access data. We can access Modify Metadata permission . Currently, this permission is not available in developer edition. Modify Metadata is enabled automatically when the Deploy Change Sets permission is selected . Let’s see an example: Previously a user need deploy change set and modify all data permission to deploy a change set. Now he does not need to modify all data permission. 11.Enter Internal Comments When Closing a Case: This is available in lightning experience only.While closing a case or creating a new one we can add internal comments.



12. Time field type is now generally available:  time field type can be used when you just want to store time not date. i.e. Want to store hotel check in and check out time.

In lightning experience and salesforce1 mobile app , it displays as picklist.

Time field can be converted in Text and number.

Consideration before using a time field type.
You can’t add the field to records in automated flows created in Cloud Flow Designer or processes designed in Process Builder.
It isn’t supported in Schema Builder.
The time field type doesn’t support the creation of custom indexes for SOQL queries.

13.Rename Your My Domain When You Want: Yes now you can change my domain in salesforce without contacting to salesforce. How we can change my Domain: From Setup, enter My Domain in the Quick Find box, then select My Domain. Under My Domain Settings, select Edit. Enter a new domain name. Select Check for availability, and if the domain is available, select Save.

Thanks,

Don't forget to share your views in comment section.





Apex Less Lightning Component


APEX Less Lightning Component




Hi all, as we know Salesforce is providing a lot of feature for lightning developers. I am going to discuss some of them with you.

Display Record Data:
Yes, now we can create a lightning component to view the data of a record without writing a  single line of a controller (Apex And JS Both).

Lightning Provide us a Component name lightning:recordViewForm.  This component requires API Version 41.0 and later.
This component takes recordId and done rest of things internally. It also takes care of Field-Level-Security and Sharing for you. So user see data only they have access.

Here is the code snippet
<aura:component implements="force:hasRecordId,lightning:actionOverride"> <lightning:card variant="brand" title="Contact" iconName="standard:contact"> <p class="slds-p-horizontal_small"> <lightning:recordViewForm recordId="{!v.recordId}" objectApiName="Contact"> <div class="slds-grid"> <div class="slds-col slds-size_1-of-2"> <lightning:outputField fieldName="Name"></lightning:outputField> </div> <div class="slds-col slds-size_1-of-2"> <lightning:outputField fieldName="Email"></lightning:outputField> </div> </div> <div class="slds-grid"> <div class="slds-col slds-size_1-of-2"> Account <lightning:outputField fieldName="AccountId" variant="label-hidden"></lightning:outputField> </div> <div class="slds-col slds-size_1-of-2"> <lightning:outputField fieldName="Phone" ></lightning:outputField> </div> </div> <div class="slds-grid"> <div class="slds-col slds-size_1-of-2"> <lightning:outputField fieldName="Birthdate"></lightning:outputField> </div> <div class="slds-col slds-size_1-of-2"> <lightning:outputField fieldName="MailingAddress"></lightning:outputField> </div> </div> </lightning:recordViewForm> </p> </lightning:card> </aura:component>

Let’s Have a look at the code we have written.

force:hasRecordId:  This interface helps us to read the id from the browser’s URL. Internally it adds an aura:attribute into over component which name is recordId.

lightning:actionOverride: It makes our component visible into override window.



lightning: recordViewForm: This is wrapper component that accepts recordId and objectApiName and displays one or more field value with the help of lightning:outputField. recordId and objectApiName are required.



lightning:outputField: It accepts the fieldName and display the field value in the correct format according to data type. We need to wrap this inside the lightning:recordViewForm tag. User’s locale setting helps to display format for number, date etc.


Consideration before using lightning:outputField:  Lookup values are rendered as text. Linking and hover overlays on the field value are not supported till now.



Edit a record or Create new Record:  Yes we can edit and create a record without writing a single line of the apex. We can use lightning:recordEditForm tag.

This tag is very much similar to lightning:recordViewForm tag. As it accepts recordId and objectApiName to work. And also manage Field-Level-Security and sharing.

It has some cool feature regarding save a record or update its value. If a lightning:button component with type=”submit” is used inside the lightning:recordEditForm then it automatically saves the changes to salesforce.



If we provide value for recordId then this component works for edit that record(Override component on the edit button of Object). But if recordId is not available then it acts for creating a new record(override component for the new button of the object). It automatically handle the errors in saving record, we must include lightning:message component inside the lightning:recordEditForm.

It also accepts recordTypeId, So if we have multiple recordTypes and do not have a default one, we can pass record Type Id for the form.

Some other attribute for lightning:recordEditForm.

onerror: The action triggered when there is an error on form submission.
onload: The action triggered when the form data is loaded.
onsubmit: The action triggered when the form is submitted.
onsuccess: The action triggered when the form is saved.

onerror action returns the ‘error’ parameter.  It contains the following properties.
errorCode
message

onsuccess action returns the ‘response’ parameter. It contains the following properties.
apiName: API name of the object. Such as Contact, Account.
childRelationships: The child relationship data for this record.
fields: The field data for this record, matching the requested layout.
id: The ID of this record.
recordTypeInfo: The record type info for this record, if any.



Code Snippets:
Lightning Component:
<aura:component implements="force:hasRecordId,lightning:actionOverride"> <lightning:card title="Contact" iconName="standard:contact" class="slds-p-around_medium"> <lightning:recordEditForm recordId="{!v.recordId}" objectApiName="Contact" onsuccess="{!c.recordSaved}"> <lightning:messages /> <div class="slds-grid"> <div class="slds-col slds-size_1-of-2 slds-p-around_medium"> <lightning:inputField fieldName="FirstName"></lightning:inputField> </div> <div class="slds-col slds-size_1-of-2 slds-p-around_medium"> <lightning:inputField fieldName="LastName"></lightning:inputField> </div> </div> <div class="slds-grid"> <div class="slds-col slds-size_1-of-2 slds-p-around_medium"> <lightning:inputField fieldName="Email"></lightning:inputField> </div> <div class="slds-col slds-size_1-of-2 slds-p-around_medium"> <lightning:inputField fieldName="Phone"></lightning:inputField> </div> </div> <div class="slds-grid"> <div class="slds-col slds-size_1-of-2 slds-p-around_medium"> <lightning:inputField fieldName="AccountId"></lightning:inputField> </div> </div> <lightning:button type="submit" label="Save" variant="brand"></lightning:button> </lightning:recordEditForm> </lightning:card> </aura:component>


Controller(JS):
({ recordSaved : function(component, event, helper) { var params = event.getParams(); //alert('record Is Saved with id '+params.response.id); console.log(params.response.childRelationships); console.log(params.response.fields); console.log(params.response.recordTypeInfo); console.log(params.response.id); } })
Thanks,





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.

GlobalScheduler:

/* 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); } }

AccountBatch:

/* 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'); } }


ContactBatch:

/* 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);

Thanks,



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; this.name = 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="{!objWrap.name}"/> </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'); } }


CacheExampleNextPage:

<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="{!objWrap.name}"/> </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.