Thursday 5 October 2017

                   Batch example scenario

Consider two fields x and y. we have already uploaded or inserted so many  Account records. At that time we haven't written any trigger or we were not aware of the future requirement.

Requirement:  If the x  value is  1  we have to update 10 in DB, if x value is  2 we have to update 20 and so on [code is self-explanatory].  

we might have a huge number of records with these unique values (1,2,3,4) and while processing in DB should be mapped to corresponding values like 20,30,40,50.

As of know, only 4 unique numbers starting from 1. 

for example:
x ---->y
1---->20
2---->30
3---->40
4---->50



Best approach is batch class

global class MapConceptUpdate implements Database.Batchable<sObject>{
    global Database.QueryLocator start(Database.BatchableContext BC)  {
        string query='select id,x_value__c,y_value__c from Account';
        return database.getqueryLocator(query);
    }
    global void execute(Database.BatchableContext BC,List<Account> scope){
        map<double,double> mapval=new map<double,double>();
        mapval.put(1,20);
        mapval.put(2,30);
        mapval.put(3,40);
        mapval.put(4,50);
       
        List<Account> aclist=new List<Account>();
        for(account ac:scope){
            if(ac.x_value__c!=null && !mapval.isEmpty()&& mapval.containsKey(ac.x_value__c)&&mapval.get(ac.x_value__c)!=null){ 
               ac.y_value__c=mapval.get(ac.x_value__c);
               aclist.add(ac);
            }   
        }
        if(!aclist.isEmpty()){
             update aclist; 
        }
       
    }
    
    global void finish(Database.BatchableContext BC) {
        
    }
}

               System.debug  is not showing in debug logs


step 1:
                  In your debug level check in Apex code debug is set
                setup--->debuglevel--->Apexcode-->debug set
Step 2:
               Debug log size if its 2MB <= then SF skip the Debug statement in that case set all unwanted flag to none so that it will reduce your debug size and then you can see the debug.

                                     Batch Apex

------------------------------------------------------------------------------------------------------------------------
Batch Apex is used to run large jobs (think thousands or millions of records!) that would exceed normal processing limits. Using Batch Apex, you can process records asynchronously in batches (hence the name, “Batch Apex”) to stay within platform limits. If you have a lot of records to process, for example, data cleansing or archiving, Batch Apex is probably your best solution.


Start method:
       The start method is called at the beginning of a batch Apex job. Use the start method to collect the records or objects to be passed to the interface method execute.

Execute Method:
      The execute method is called for each batch of records passed to the method. Use this method to do all required processing for each chunk of data.

Finish Method
  The finish method is called after all batches are processed. Use this method to send confirmation emails or execute post-processing operations.
       Each execution of a batch Apex job is considered a discrete transaction. For example, a batch Apex job that contains 1,000 records and is executed without the optional scope parameter from Database.executeBatch is considered five transactions of 200 records each.
The Apex governor limits are reset for each transaction. If the first transaction succeeds but the second fails, the database updates made in the first transaction are not rolled back.

--------------------------------------------------------------------------------------------------------------------------
Useful Links:

1. http://www.infallibletechie.com/2012/05/apex-scheduler.html

2. https://trailhead.salesforce.com/en/modules/asynchronous_apex/units/async_apex_batch

3. http://blog.shivanathd.com/2013/01/how-to-write-batch-class-in.html
-------------------------------------------------------------------------------------------------------------------------

global class BatchAccountUpdate implements Database.Batchable<sObject> {
   global Database.QueryLocator start(Database.BatchableContext BC) {
        String query = 'SELECT Id,Name FROM Account';
        return Database.getQueryLocator(query);
    }
 
    global void execute(Database.BatchableContext BC, List<Account> scope) {
         for(Account a : scope)
         {
             a.Name =  a.Name+'Salesforce King';
           
         }
     
         update scope;
    } 
 
    global void finish(Database.BatchableContext BC) {
    }
}
--------------------------------------------------------------------------------------------------------------------------
global class BatchScheduleAccount {
    global void execute(SchedulableContext sc)
    {
        // Implement any logic to be scheduled
     
        // We now call the batch class to be scheduled
        BatchAccountUpdate b = new BatchAccountUpdate ();
     
        //Parameters of ExecuteBatch(context,BatchSize)
        database.executebatch(b,200);
    }
}
------------------------------------------------------------------------------------------------------------------------

Test class for Batch Apex:
@isTest
public class BatchAccountUpdate_Test {
    public static testmethod void batchMethod(){
        List<Account> aclist=new List<Account>();
        for(integer i=0;i<=200;i++){
            Account ac=new Account();
            ac.name='TEST'+i;
            aclist.add(ac);
        }
        insert aclist;
     
        Test.startTest();
        BatchAccountUpdate b=new BatchAccountUpdate();
        // database.executeBatch(b);
        Database.QueryLocator ql = b.start(null);
        b.execute(null,aclist);
        b.Finish(null);
        Test.stopTest();
    }
 
}
--------------------------------------------------------------------------------------------------------------------------
Test class for scheduler class:
@isTest
public class BatchScheduleAccount_Test {
    public static testmethod void batchMethod(){
        test.startTest();
        BatchScheduleAccount  ac=new BatchScheduleAccount();
        ac.execute(null);
        test.stopTest();
    }

}
------------------------------------------------------------------------------------------------------------------------

Tuesday 3 October 2017

    Setting Read-Only Mode for an Entire Page

   To display a page in read-only mode you can use page attribute as follows:

<apex:page controller="myController" readOnly="true">
<apex:page>

Other advantage is query limit is getting increased from 50,000 rows to 1,000,000 rows.
In addition to querying many more rows, the readOnly attribute also increases the maximum number of items in a collection that can be iterated over using components such as <apex:dataTable><apex:dataList>, and <apex:repeat>. This limit increased from 1,000 items to 10,000. 
Special Note: 
https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/pages_controller_readonly_context_methodlevel.htm