function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Mohammed AyyubMohammed Ayyub 

Best Practice of Using Try and Catch in Apex code

Hi All,

 

1. What is the best way of using try and catch in apec code?

2. What is disadvantage of putting whole code in try catch ? for example --

 

public class Demo{

try{

 

 

 /**here put all code

 

 

}catch(exception e){}

 

 

}

 

Thanks in Advance

CloudMaster

 

 

Vinita_SFDCVinita_SFDC

Hello,

 

There is no harm in putting entire code in one Try block but make sure you catch all possible exceptions in different Catch block. Also make sure your code takes care of governor limits.

 

For further details refer following links:

 

http://www.salesforce.com/us/developer/docs/apex_workbook/Content/apex7_2.htm

 

http://wiki.developerforce.com/page/An_Introduction_to_Exception_Handling

sfdcfoxsfdcfox

Try-catch blocks should be used only sparingly, because poorly designed blocks can hide problems that would otherwise not be present.

 

Consider this trigger:

 

trigger createAccounts on Contact (before insert) {
    try {
        map<integer, account> accounts = new map<integer, account>();
        for(integer idx = 0; idx < trigger.new.size(); idx++)
            if(trigger.new[idx].accountid==null)
                accounts.put(idx, new account(name=trigger.new[idx].lastname));
        insert accounts.values();
        for(intger idx: accounts.keyset())
            trigger.new[idx].accountid=accounts.get(idx).id;
    } catch(exception e) {
    }
}

 

In this trigger, if 200 records are inserted at once without an account, and one of the accounts fails, none of the 200 contacts will have an account. Worse, the user won't notice the error, because none was reported, and the logic has been averted.

 

In contrast, if you instead catch the errors, you can then report them accurately. This trigger is bulk-safe:

 

trigger createAccounts on contact (before insert) {
    account[] accounts = new account[0];
    map<integer, integer> indices = new map<integer, integer>();
    for(Integer idx = 0; idx < Trigger.new.size(); idx++) {
        if(Trigger.new[idx].accountid == null) {
            indices.put(accounts.size(), idx);
            accounts.add(new account(name=trigger.new[idx].lastname));
        }
    }    
    database.saveresult[] results = database.insert(accounts, false);
    for(integer idx = 0; idx < results.size(); idx++) {
        if(results[idx].isSuccess()) {
            Trigger.new[indices.get(idx)].AccountId = accounts[idx].Id;
        } else {
            Trigger.new[indices.get(idx)].AccountId.addError('Failed to create account for this contact: '
                + results[idx].getErrors()[0].getMessage());
        }
    }
    
}

In this case, we fail contacts that fail because of a validation rule/exception/etc without failing records that pass or failing to ensure business logic. Note that no try-catch block was necessary at all.

 

On the other hand, when we know we'll get direct errors back to the user, it may be okay to try-catch the entire method. Here's an example:

 

public ApexPages.Pagereference saveData() {
    System.SavePoint sp = System.setSavePoint();
    PageReference ref;
    try {
        insert assets;
        insert someData;
        update accounts;
        update orders;
        ref = Page.reviewOrderData;
        ref.getParameters().put('id', someData.Id);
    } catch(dmlexception e) {
apexpages.addmessages(e); for(asset record: assets) asset.id = null; someData.Id = null; Database.rollback(sp); } return ref; }

In this case, any DML errors will be reported to the user; this process was considered indivisible, so I want to fail the entire transaction if any step fails. This prevents the need to check each dml operation individually, relying on the system to report any errors to the user correctly. Validation rules and other errors will also appear correctly on the records with no extra effort on my part. Note that I perform minimal processing in the try-catch block itself-- I want to just update all my data. Also, this specific example also shows that you may need to perform clean up in a catch block.

 

Proper error exception almost always requires more code than using a simple try-catch, but is necessary when you need to ensure business logic. In particular, you should probably avoid try-catch blocks in triggers and utility functions as much as possible, because try-catch isn't easy to make bulk-safe-- either you'll ignore the wrong errors, or cause failures that should have been successful. Also, it's incredibly easy to write a try-catch block that will make unreportable errors, which in turn make troubleshooting difficult.

 

In summation, use try-catch blocks to catch all errors for an indivisible process that you generally intend to fail, and use other, more appropriate methods when you need to be precise. The larger the try-catch block, the more errors you may be masking, so use try-catch only to catch exceptions, and try to keep them as small as possible. For example, if you're trying to parse date values, it may be okay to catch an exception to note that a date wasn't in a parseable format.

 

 

JaniiiiJaniiii
ANS