Sunday, November 18, 2012

Batch Classes in Salesforce

This post related to batch covers following points mentioned below:--
     
  •          Introduction to Batch Apex
  •          How to delete contact records through batch
  •          How to execute a batch through custom button
  •          How to get status of Errors
  •          How to get success and error count for records 
  •          How to send user a Email having success and error count

Introduction to Batch Apex:--

A developer can now employ batch Apex to build complex, long-running processes
on the Force.com platform. For example, a developer could build an archiving:--

Using Batch Apex solution that runs on a nightly basis, looking for records past a certain date and
understanding Apex Managed Sharing adding them to an archive. Or a developer could build a data cleansing operation that goes through all Accounts and Opportunities on a nightly basis and reassigns
them if necessary, based on custom criteria.

Batch Apex is exposed as an interface that must be implemented by the developer. Batch jobs can be programmatically invoked at runtime using Apex.

You can only have five queued or active batch jobs at one time. You can evaluate your current count by viewing the Scheduled Jobs page in Salesforce or programmatically using the Force.com Web services API to query the AsyncApexJob object.

To use batch Apex, you must write an Apex class that implements the Salesforce-provided interface Database.Batchable and then invoke the class programmatically.

Implementing the Database.Batchable Interface

The Database.Batchable interface contains three methods that must be implemented:

• start method

global (Database.QueryLocator | Iterable<sObject>) start(Database.BatchableContext bc) {}

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. This method returns either a Database.QueryLocator object or an iterable that contains the records or objects being passed into the job.

• execute method:

global void execute(Database.BatchableContext BC, list<P>) {}

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

global void finish(Database.BatchableContext BC){}

The finish method is called after all batches are processed. Use this method to send confirmation emails or execute post-processing operations.


How to delete Contact records using Batch:---


/*
* Description   : This is Batch to Perform delete operation on Contact Records.
* 
* Created By    : Abhinav Sharma
*
* Created Date  : 11/18/2012
*
* Version       : v1.0 - Create 
*/
//Batch Class
global class Batch_DeleteContact implements Database.Batchable<sObject>,Database.stateful {
  
  //Variable to count Success and Error Records
    public Integer successCounter = 0;
    public Integer failureCounter = 0; 
         
    //Start Method 
    global Database.QueryLocator start(Database.BatchableContext BC) { 
    
        //Query to Fetch Records
        return Database.getQueryLocator([SELECT ID FROM Contact]);
   
    }
    
    //Execute Method
    global void  execute(Database.BatchableContext BC, List<Contact> scope) {
      
    //Delete the Records those are in Contexts
        Database.DeleteResult[] delresults = Database.delete((scope),false);
        
        //Loop through records giong to be deleted
        for(Database.DeleteResult dr : delResults){
        
            //If record is not successfully deleted
            if(!dr.isSuccess()){
            
                //List to hold Error
                Database.Error[] errs = dr.getErrors();
                
                //Loop through list of Error
                for(Database.Error err : errs) {
                    
                    //Debug to get Error Status
                    System.debug('$#$#$#$' + err.getStatusCode() + ' - ' + err.getMessage());
                    
                    //Debug to get Error Message
                    System.debug('ErrorMessage##########'+ err.getMessage());
                }
                
                //Increase counter for Failure
                 failureCounter++;
            }
            
            else {
            
                successCounter++;
            }
        }      
    }
    
    //Finish Method
    global void finish(Database.BatchableContext BC){
      
      // Query the AsyncApexJob object to retrieve the current job's information.
        AsyncApexJob a = [SELECT Id, Status, NumberOfErrors, JobItemsProcessed,
        TotalJobItems, CreatedBy.Email
        FROM AsyncApexJob WHERE Id = :BC.getJobId()];
        
        // Send an email to the Apex job's submitter notifying of job completion.
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        String[] toAddresses = new String[] {a.CreatedBy.Email};
        mail.setToAddresses(toAddresses);
        mail.setSubject('Apex Job ' + a.Status);
        mail.setPlainTextBody
        ('Apex job has been completed.There were total' + a.TotalJobItems 
              + ' batches with ' + successCounter + ' success and ' + failureCounter
              + 'failures.');
        Messaging.sendEmail(new Messaging.SingleEmailMessage[]{mail});
    }
}

Apex class which is further call by Custom List Button for execution of Batch :---


global with sharing class Batch_ExectionController {
//This method is to get the view mode  
webservice static ID executeBatchForDeletionOfContact() {            
Id batchProcessId;                
//Calling Constructor for Batch Execution      
Batch_DeletePropertyOpportunities dc = new Batch_DeletePropertyOpportunities();  
batchProcessId = Database.executeBatch(dc);        
System.debug('Returned batch process ID:@@@@@@@@@@@@@@@@@@ ' + batchProcessId);          return batchProcessId;  
}
}
Custom List Button Code:-- (Location:-- List view Page - Contact) {!REQUIRESCRIPT("/soap/ajax/10.0/connection.js")} {!REQUIRESCRIPT("/soap/ajax/10.0/apex.js")}
//Calling Class and Method var contextUser = sforce.apex.execute("Batch_ExectionController", "executeBatchForDeletionOfContact", {});
window.alert('Now Please check Debug logs');
Once user click on list button it ultimate call that class which have execution code for batch and as a result of this once batch completed successfully all max possible contacts get deleted and an email will be there on user mail box having success and error count. Governor limits always play an important role in case of Batch Apex therefore always keep these limits in mind.
Enjoy Coding.....

Friday, October 5, 2012

How to Play with Custom Labels in Salesforce


How to Play with Custom Labels

Introduction

Custom Labels are custom text values, up to 1,000 characters, that can be accessed from Apex Classes or VisualForce Pages. If Translation Workbench has been enabled for your organization, these labels can then be translated into any of the languages salesforce.com supports. This allows developers to create true multilingual apps by presenting information to users - for example, help text or error messages - in their native language. You can create up to 5,000 custom labels.

Steps for using custom labels with apex class and page:-

1)    Create Custom Labels

Home --> Setup --> Create --> Custom Labels

Click on New Custom Label Button

 Populate all input fiels required for custom label

Great, Now I can see a new custom label with above mentioned label and value.



Step2:- Create New Apex Class

 Save new apex class with code given below:--

 public class CustomLabelGlobalVariableCon {

    //String to hold the value for custom label

    public String myLabel {get; set;}

  

    //Calling Constructor

    public CustomLabelGlobalVariableCon () {

  

        myLabel = 'Account_Label';   //Provide custom label name as you have.

    }

}



Step 3:- Create VisualForce Page

Save new page with code given below:--

<apex:page Controller="CustomLabelGlobalVariableCon">

    <apex:outputText > {!$Label[mylabel]} </apex:outputText>

</apex:page>



Step 4:- Run the Page by inserting proper URL in the browser for getting result.


So, from above discussion use of custom label with apex class and page is now quite clear and even we can use custom labels directly in page without referring  any custom controller as mentioned below:-

<apex:page >

     <apex:pageMessage severity="info"  strength="1"  summary="{!$Label.Account_Label}"/>

</apex:page>

 

How to show Custom Error Message through Custom Controller

We can show a custom message on page through use of custom labels. To demonstrate  this I am creating a apex trigger on account object for ensuring that Account Number field populated with values or not and If this field do not have any value then a error message will be there on page with my custom label “Account_Label” value.

Code for Apex Trigger

 trigger Trigger_Account on Account (before insert, before update) {

    

      //Check for Request Type

    if(Trigger.isBefore) {

  

        //Check for Event Type

        if(Trigger.isInsert || Trigger.isUpdate) {

      

            //Loop through Account

            for(Account account : Trigger.New) {

                

             //Logic for showing custom label message on page in absence of Account Number

               if(account.AccountNumber == Null)

                   account.addError(label.Account_Label);

            }

        }

    }

}

 

Now null value case for Account Number field for account object error message will surely have custom label value with it. Finally, this is the mantra to play with custom labels in Salesforce.

Enjoy Coding...

Sunday, September 9, 2012

PageReference in Salesforce

A PageReference is a reference to an instantiation of a page. Among other attributes, PageReferences consist of a URL and a set of query parameter names and values.
Use a PageReference object:
  • To view or set query string parameters and values for a page
  • To navigate the user to a different page as the result of an action method

Instantiation


In a custom controller or controller extension, you can refer to or instantiate a PageReference in one of the following ways:
  • Page.existingPageName
    Refers to a PageReference for a Visualforce page that has already been saved in your organization. By referring to a page in this way, the platform recognizes that this controller or controller extension is dependent on the existence of the specified page and will prevent the page from being deleted while the controller or extension exists.
  • PageReference pageRef = new PageReference('partialURL');
     
    Creates a PageReference to any page that is hosted on the Force.com platform. For example, setting 'partialURL' to '/apex/HelloWorld' refers to the Visualforce page located at http://mySalesforceInstance/apex/HelloWorld. Likewise, setting 'partialURL' to '/' + 'recordID' refers to the detail page for the specified record.
    This syntax is less preferable for referencing other Visualforce pages than Page.existingPageName because the PageReference is constructed at runtime, rather than referenced at compile time. Runtime references are not available to the referential integrity system. Consequently, the platform doesn't recognize that this controller or controller extension is dependent on the existence of the specified page and won't issue an error message to prevent user deletion of the page.

  • PageReference pageRef = new PageReference('fullURL');
     
    Creates a PageReference for an external URL. For example:

    PageReference pageRef = new PageReference('http://www.google.com');
You can also instantiate a PageReference object for the current page with the currentPage ApexPages method. For example:
PageReference pageRef = ApexPages.currentPage();
 
 
PageReference Best Practice 
 


I have seen a lot of coders put the following into their custom Visualforce controllers:

public PageReference close() {

PageReference acctPage = new PageReference ('/' + acct.id};

acctPage.setRedirect(true);

return acctPage;


}


I've decided that I don't like this approach. It feels too much like a URL hack, and though I'm sure that it will always work

(meaning that salesforce.com will never change its way of referring to a record by/), I'd like to suggest a different

method that may use more resources, but will leverage standard controllers, possibly future-proofing the application:


public PageReference close() {


ApexPages.StandardController sc = new ApexPages.StandardController(acct);

PageReference acctPage = sc.view();

acctPage.setRedirect(true);

return acctPage;

}

You can easily get more information about different
PageReference methods in Apex language reference. Enjoy Coding.

 

Monday, August 20, 2012

Difference In Between Apex PageMessage, PageMessages and Message VF Pages Tags in Salesforce

Most of the times on submission of page errors will be there and for showing those error messages different message tags are there in Visualforce Page Reference guide and first time they all are gave a feel that they all are same but some minor differences are there among them and those differences are as given below:-


Apex:PageMessages

apex:PageMessages is a containing component where any messages that have been added to the page will appear.

Apex:PageMessage
apex:pageMessage is a component that adds a single message to the page.

Apex:Message
apex:message allows you to associate a message with a component.


Notes

ApexPages.Message is the class that is used to model a message.  A message isn't associated with a page until it is added via the ApexPages class.

ApexPages is a class that allows you to access the current page (through ApexPages.CurrentPage()) and manage messages for the current page.


As Shown below messages can be of Error type and Custom Type and generally Apex:PageMessages tag comes in use for showing all  the messages.






Saturday, July 21, 2012

Validation Rule dependent on Record Type in Salesforce

Record types allow you to offer different business processes, picklist values, and page layouts to different users based on their profiles. Therefore sometimes requirement arises in which validation's are made on the basis of record types. 

For example in my case I have a Booking(Booking__c) custom field for which I have a custom field of picklist type name  as Status and have values as shown below:-

                                                           
                                                     






Therefore now we have a custom object "Booking' and a Picklist field for this object name as "Status" with values Not Confirmed, Confirmed, Check In, Check Out.

I have a Record Type Name as "Booking Help" for Booking Object as shown below:--




I'm trying to write a validation rule that is dependent on the Record Type.  For example:

Validation is there for ensuring that If record Type is "Booking Help" and New Booking Record is going to be insert in the database then Status should be  Confirmed. if not then it will throw an error "Status should be Confirmed during new booking record insertion".

When I look at my choices for Record Type, I only find Record Type ID, but I can only find the Record Type name in the back-end.
By using that I made a validation as shoen below:--


 
 But when I do testing for this validation then it fails. Now I make some changes in my validation formula and it result me as success.










 
 
Finally If we talk in details then we can say that in case of validation through record type always use formula   $RecordType.Name of global type in place of using reference of Record Types through ID.
Simply by doing this  now you can reference this field in your validation formulas without having to look up and code each RecordTypeID.
 
This is all about Validation on the basis of record types in Salesforce.