Month: February 2018

Future Method in Apex

Future Apex is used to run processes in a separate thread, at a later time when system resources become available.

You use the @future annotation to identify methods that run asynchronously.

Future methods are typically used for:

  • Callouts to external Web services. If you are making callouts from a trigger or after performing a DML operation, you must use a future or queueable method. A callout in a trigger would hold the database connection open for the lifetime of the callout and that is a “no-no” in a multitenant environment.
  • Operations you want to run in their own thread, when time permits such as some sort of resource-intensive calculation or processing of records.
  • Isolating DML operations on different sObject types to prevent the mixed DML error.

Syntax of Future Method :-


global class futureClass {
@future
public static void myFutureMethod(List recordIds) {
List accounts = [Select Id, Name from Account Where Id IN :recordIds];
// process account records to do something
}
}
  • Future method must be static and return type is void always.
  • Parameters must be primitive data types, arrays of primitive data types, or collections of primitive data types.
  •  Future methods can’t take standard or custom objects as arguments.
  • A common pattern is to pass the method a List of record IDs that you want to process asynchronously.

Note

The reason why objects can’t be passed as arguments to future methods is because the object can change between the time you call the method and the time that it actually executes. Remember, future methods are executed when system resources become available. In this case, the future method may have an old object value when it actually executes, which can cause all sorts of bad things to happen.

  • Future methods are not guaranteed to execute in the same order as they are called.
  • If you need this type of functionality then Queueable Apex might be a better solution.

Callout Using Future

To make a Web service callout to an external service or API, you create an Apex class with a future method that is marked with (callout=true).

public class SMSUtils {
// Call async from triggers, etc, where callouts are not permitted.
@future(callout=true)
public static void sendSMSAsync(String fromNbr, String toNbr, String m) {
String results = sendSMS(fromNbr, toNbr, m);
System.debug(results);
}

// Call from controllers, etc, for immediate processing
public static String sendSMS(String fromNbr, String toNbr, String m) {
// Calling 'send' will result in a callout
String results = SmsMessage.send(fromNbr, toNbr, m);
insert new SMS_Log__c(to__c=toNbr, from__c=fromNbr, msg__c=results);
return results;
}
}

 Test Class for Future Method Class – 

To test future methods, enclose your test code between the startTest and stopTest test methods. The system collects all asynchronous calls made after the startTest. When stopTest is executed, all these collected asynchronous processes are then run synchronously. You can then assert that the asynchronous call operated properly.

Note : Test code cannot actually send callouts to external systems, so you’ll have to ‘mock’ the callout for test coverage.

@isTest
global class SMSCalloutMock implements <strong>HttpCalloutMock</strong> {
global HttpResponse respond(HttpRequest req) {
// Create a fake response
HttpResponse res = new HttpResponse();
res.setHeader('Content-Type', 'application/json');
res.setBody('{"status":"success"}');
res.setStatusCode(200);
return res;
}
}
@IsTest
private class Test_SMSUtils {

@IsTest
private static void testSendSms() {
<strong>Test.setMock(HttpCalloutMock.class, new SMSCalloutMock());</strong>
Test.startTest();
SMSUtils.sendSMSAsync('111', '222', 'Greetings!');
Test.stopTest();
// runs callout and check results
List logs = [select msg__c from SMS_Log__c];
System.assertEquals(1, logs.size());
System.assertEquals('success', logs[0].msg__c);
}
}

Important Points – 

Future methods are a great tool, but with great power comes great responsibility. Here are some things to keep in mind when using them:

  • Methods with the future annotation must be static methods, and can only return a void type.
  • The specified parameters must be primitive data types, arrays of primitive data types, or collections of primitive data types; future methods can’t take objects as arguments.
  • Future methods won’t necessarily execute in the same order they are called. In addition, it’s possible that two future methods could run concurrently, which could result in record locking if the two methods were updating the same record.
  • Future methods can’t be used in Visualforce controllers  in  getMethodName(),   setMethodName(), nor in the constructor.
  • You can’t call a future method from a future method. Nor can you invoke a trigger that calls a future method while running a future method.
  • The getContent() and getContentAsPDF() methods can’t be used in methods with the future annotation.
  • You’re limited to 50 future calls per Apex invocation, and there’s an additional limit on the number of calls in a 24-hour period. For more information on limits, see the link below.

All about SOQL Aggregate function

Aggregate functions in SOQL, such as SUM() and MAX(), allow you to roll up and summarize your data in a query.

You can use aggregate functions without using a GROUP BY clause. For example, you could use the AVG() aggregate function to find the average Amount for all your opportunities.

AggregateResult[] groupedResults  = [SELECT AVG(Amount)aver FROM Opportunity];
Object avgAmount = groupedResults[0].get('aver');

Note that any query that includes an aggregate function returns its results in an array of AggregateResult objects. AggregateResult is a read-only sObject and is only used for query results.

Aggregate functions become a more powerful tool to generate reports when you use them with a GROUP BY clause. For example, you could find the average Amount for all your opportunities by campaign.

AggregateResult[] groupedResults = [SELECT CampaignId, AVG(Amount) FROM Opportunity GROUP BY CampaignId];
for (AggregateResult ar : groupedResults) {
        System.debug('Campaign ID' + ar.get('CampaignId'));
        System.debug('Average amount' + ar.get('expr0'));
}

Any aggregated field in a SELECT list that does not have an alias automatically gets an implied alias with a format expri, where i denotes the order of the aggregated fields with no explicit aliases. The value of i starts at 0 and increments for every aggregated field with no explicit alias.

Use aggregate functions in a GROUP BY clause in SOQL queries. Aggregate functions include AVG(), COUNT(), MIN(), MAX(), SUM().

Trigger to Update Contacts on Account Update

trigger AccountTrigger on Account (before update) {
   Map updateAccMap = new Map();
    List updatedContacts = new List();
   for(Integer i=0; i< trigger.new.size(); i++) {
       if(trigger.old[i].ShippingState != trigger.new[i].ShippingState) {
           updateAccMap.put(Trigger.old[i].id, Trigger.new[i]);
       }
   }
   //for(Contact c : [Select Id, AccountId, Account_Updated__c From Contact where AccountId IN :updateAccMap.keySet()]) {
   for(Contact c : [Select Id, AccountId, Account_Updated__c From Contact where AccountId IN :trigger.old]) {
       Account parentAcc = updateAccMap.get(c.AccountId);
       c.Account_Updated__c = true;
          updatedContacts.add(c);
   }
   if(!updatedContacts.isEmpty())
	update updatedContacts;
}

Difference between list for loop and SOQL for loop in Apex

Apex code to update all accounts with null region field with value ‘CAM’.

Using SOQL List for loop – Create a list of sObject result list first and then loop through the list

List accountList = [Select Id, Name,region__c From Account];
List accUpdateList = new List();

for(Account acc : accountList) {
if(acc.regioon__c == null) {
        Account.region__c = 'CAM';
        accUpdateList.add(acc);
    }
}
if(!accUpdateList.isEmpty())
    update accUpdateList ;

Using SOQL for loop – Use the SOQL query in the for loop

List accUpdateList = new List();
for(Account acc : [Select Id, Name,region__c From Account]) {
    if(acc.regioon__c == null) {
        Account.region__c = 'CAM';
        accUpdateList.add(acc);
    }
}
if(!accUpdateList.isEmpty())
    update accUpdateList

SOQL and SOSL query can retrieve either the count of a query or a number of object records.  SOQL for loop retrieves all sObjects using efficient chunks of call to the query and queryMore methods.

Using both the option developer can check the heap memory, using the 1st option heap size will be considerably more then 2nd option, So to avoid heap size limit error developer should always use a SOQL for loop to process query results that returns many records.

Querying Large Data Sets – 
The total number of records that can be returned by SOQL queries in a request is 50,000. If returning a large set of queries causes you to exceed your heap limit, then a SOQL query for loop must be used instead. It can process multiple batches of records through the use of internal calls to query and queryMore.

All about UserInfo Class in Apex

UserInfo class contains methods to get the LoggedIn User or Context User  information.

All methods in UserInfo class are static method, so you can access the methods using the syntax – ClassName.methodName() like UserInfo.methodName()

getUserId() Method – return the current user Id.

Id currentUserId = UserInfo.getUserId();

getProfileId() Method –  returns the current user profile Id.

Id userProfileId = UserInfo.getProfileId();

getUiTheme() method –  returns the preferred theme of the current user. Use getUiThemeDisplayed() to determine the theme actually displayed to the current user.

getUiThemeDisplayed() method – returns the theme displayed by the current user. Theme here means whether user is using Salesforce Classic or Lightning theme, using this you can identify current theme and do some business requirement.

String currentTheme = UserInfo.getUiThemeDisplayed();

Different them value are –

  • Theme1—Obsolete Salesforce theme
  • Theme2—Salesforce Classic 2005 user interface theme
  • Theme3—Salesforce Classic 2010 user interface theme
  • Theme4d—Modern “Lightning Experience” Salesforce theme
  • Theme4t—Salesforce mobile app theme
  • Theme4u—Lightning Console theme
  • PortalDefault—Salesforce Customer Portal theme
  • Webstore—Salesforce AppExchange theme

getFirstName() – return the current user First Name of String type.

getLanguage() – returns the current user language of String type.

getLastName() – returns the current user Last Name of String type.

getUserName() – returns the current user login name of String type.

getUserRoleId() – returns the current user’s role Id of String Type.

getUserType() – returns the current user’s type of return type String.

Apex Exception Handling and Built-In methods in Exception

In Apex Exception are handles using try, catch and finally.

try – block of code where an error can occur.

catch – block handles particular type of exception. A single try block can have zero or more exception block.  Each catch block must have unique exception type. Once a particular exception type is caught is one catch block, the remaining catch block will not execute.

finally – this block of code execute always and used for clean up code or sending email. A try block can have zero or one finally block.

try {
// Try block
***Code Block***
} catch (exceptionType variableName) {
// Initial catch block.
// At least the catch block or the finally block must be present.
code_block
} catch (Exception e) {
// Optional additional catch statement for other exception types.
// Note that the general exception type, 'Exception',
// must be the last catch block when it is used.
code_block
} finally {
// Finally block.
// At least the catch block or the finally block must be present.
code_block
}

At least a catch block or a finally block must be present for a try block.   catch  block is not mandatory for a try  block.

Below syntax both are valid and will work fine –

Try-Catch Block

try {
***code_block***
} catch (exceptionType variableName) {
code_block
}
// Optional additional catch blocks

Try-Finally Block

try {
***code_block***
} finally {
code_block
}

The finally block always executes regardless of exception is thrown, and even if no exception is thrown.  Finally block executed after the exception caught.

Built-In Exceptions

Apex provides a different type of built-in exception types that the runtime engine throws if errors are encountered during execution. All exceptions support built-in methods for returning the error message and exception type.

Exception Description
AsyncException Any problem with an asynchronous operation, such as failing to enqueue an asynchronous call.
CalloutException Any problem with a Web service operation, such as failing to make a callout to an external system.
DmlException Any problem with a DML statement, such as an insert statement missing a required field on a record.
EmailException Any problem with email, such as failure to deliver. For more information, see Outbound Email.
ExternalObjectException Any problem with external object records, such as connection timeouts during attempts to access the data that’s stored on external systems.
InvalidParameterValueException An invalid parameter was supplied for a method or any problem with a URL used with Visualforce pages. For more information on Visualforce, see the Visualforce Developer’s Guide.
LimitException A governor limit has been exceeded. This exception can’t be caught.
JSONException Any problem with JSON serialization and deserialization operations. For more information, see the methods of System.JSONSystem.JSONParser, andSystem.JSONGenerator.
ListException Any problem with a list, such as attempting to access an index that is out of bounds.
MathException Any problem with a mathematical operation, such as dividing by zero.
NoAccessException Any problem with unauthorized access, such as trying to access an sObject that the current user does not have access to. This is generally used with Visualforce pages. For more information on Visualforce, see the Visualforce Developer’s Guide.
NoDataFoundException Any problem with data that does not exist, such as trying to access an sObject that has been deleted. This is generally used with Visualforce pages. For more information on Visualforce, see the Visualforce Developer’s Guide.
NoSuchElementException This exception is thrown if you try to access items that are outside the bounds of a list. This exception is used by the Iterator next method. For example, ifiterator.hasNext() == false and you call iterator.next(), this exception is thrown. This exception is also used by the Apex Flex Queue methods and is thrown if you attempt to access a job at an invalid position in the flex queue.
NullPointerException Any problem with dereferencing null, such as in the following code:

String s;
s.toLowerCase(); // Since s is null, this call causes
// a NullPointerException

Any problem with SOQL queries, such as assigning a query that returns no records or more than one record to a singleton sObject variable.
RequiredFeatureMissing A Chatter feature is required for code that has been deployed to an organization that does not have Chatter enabled.
SearchException Any problem with SOSL queries executed with SOAP API search() call, for example, when the searchString parameter contains less than two characters. For more information, see the SOAP API Developer Guide.
SecurityException Any problem with static methods in the Crypto utility class. For more information, see Crypto Class.
SerializationException Any problem with the serialization of data. This is generally used with Visualforce pages. For more information on Visualforce, see the Visualforce Developer’s Guide.
SObjectException Any problem with sObject records, such as attempting to change a field in an updatestatement that can only be changed during insert.
StringException Any problem with Strings, such as a String that is exceeding your heap size.
TypeException Any problem with type conversions, such as attempting to convert the String ‘a’ to an Integer using the valueOf method.
VisualforceException Any problem with a Visualforce page. For more information on Visualforce, see the Visualforce Developer’s Guide.
XmlException Any problem with the XmlStream classes, such as failing to read or write XML.

Exception Methods

Name Return Type Description
getCause Exception Returns the cause of the exception as an exception object.
getLineNumber Integer Returns the line number from where the exception was thrown.
getMessage String Returns the error message that displays for the user.
getStackTraceString String Returns the stack trace as a string.
getTypeName String Returns the type of exception, such as DmlException, ListException, MathException, and so on.