Wednesday, 8 February 2017

Relationship between Opportunity,OpportunityLineItems and Price books

Opportunity
  • Opportunity object stores data of potential sales and pending sales.
  • One opportunity can only have one pricebook.
  • One opportunity can contain one or many line items.
Product
  • Product object is a catalogue of items or services for sales.
  • A product may contain one or more different sets of prices (PriceBookEntry).
OpportunityLineItem
  • List of products that link with opportunity containing data on types of products and respective prices.
  • One opportunity line item can only be linked to one opportunity.
  • One opportunity line item can only be linked to one price book entry.
PricebookEntry
  • PricebookEntry object is a product entry in a pricebook.
  • This object allows products to be linked to standard price book or custom price book.
  • One price book entry is linked to only one product.
  • One price book entry can only appear in one pricebook.
  • One price book entry can be used in multiple line items. This also further creates flexibility for users to set their own prices.
Pricebook
  • Pricebook object store a list of products and services for sale.
  • A pricebook can be used in one or more different opportunities.
  • A pricebook has one or more different price entries.

Tuesday, 7 June 2016

What is Exception handling in Apex?

Exceptions note errors and other events that disrupt the normal flow of code execution. throw statements can be used to generate exceptions, while try, catch, and finally can be used to gracefully recover from an exception.

When an exception occurs, code execution halts and any DML operations that were processed prior to the exception are rolled back and aren’t committed to the database. Exceptions get logged in debug logs. For unhandled exceptions, that is, exceptions that the code doesn’t catch, Salesforce sends an email to the developer with the organization ID and user ID of the running user, as well as the exception message.


If you run into an exception that occurred in Apex code while using the standard user interface, an error message appears on the page showing you the text of the unhandled exception as shown below:



Throw Statements

A throw statement allows you to signal that an error has occurred. To throw an exception, use the throw statement and provide it with an exception object to provide information about the specific error. For example:

throw exceptionObject;

Try, Catch, and Finally Statements

Apex uses try, catch and finally statements to handle exceptions. Here is an example of what these statements look like and the order in which they should be written.

try {
// Perform some database operations that
// might cause an exception.
} catch(DmlException e) {
// DmlException handling code here.
} catch(Exception e) {
// Generic exception handling code here.
} finally {
// Perform some clean up.
}

The try statement identifies a block of code in which an exception can occur. If you have code that you think could generate an exception, wrap this section of your code in a try block, and add a catch block after it. Only exceptions thrown from the code wrapped in the try block are handled by the catch block.

The catch statement identifies a block of code that handles a particular type of exception. In the previous example, notice that there are two catch statements. You can have as many catch statements as you like, one for each exception type you want to catch.

The finally statement is optional and gets executed after the catch block executes. Code in the finally block always executes regardless of the type of exception that was thrown and handled. You can add any final clean-up code here.

Built-In Exceptions

Apex provides a number of exception types that the runtime engine throws if errors are encountered during execution.

DmlException :-Any problem with a DML statement, such as an insert statement missing a required field on a record.

ListException :- Any problem with a list, such as attempting to access an index that is out of bounds.Try out some code that does some things on purpose to cause this exception to be thrown. Execute the following:

try {
List<Integer> li = new List<Integer>();
li.add(15);
// This list contains only one element,
// but we're attempting to access the second element
// from this zero-based list.
Integer i1 = li[0];
Integer i2 = li[1]; // Causes a ListException
} catch(ListException le) {
System.debug('The following exception has occurred: ' + le.getMessage());
}

In the previous code snippet, we create a list and add one element to it. Then, we attempt to access two elements, one at index 0, which exists, and one at index 1, which causes a ListException because no element exists at this index. This exception is caught in the catch block. The System.debug statement in the catch block writes the following to the debug log: The following exception has occurred: List index out of bounds: 1.

NullPointerException:- Any problem with dereferencing a null variable.

Try out some code that does some things on purpose to cause this exception to be thrown. Execute the following:

try {
String s;
Boolean b = s.contains('abc'); // Causes a NullPointerException
} catch(NullPointerException npe) {
System.debug('The following exception has occurred: ' + npe.getMessage());
}

we create a String variable named s but we don’t initialize it to a value, hence, it is null. Calling
the contains method on our null variable causes a NullPointerException. The exception is caught in our catch block and this is what is written to the debug log: The following exception has occurred: Attempt to de-reference a null object.

QueryException :-Any problem with SOQL queries, such as assigning a query that returns no records or more than one record to a singleton sObject variable.

SObjectException :-Any problem with sObject records, such as attempting to change a field in an update statement that can only be changed during insert.

try {
Merchandise__c m = [SELECT Name FROM Merchandise__c LIMIT 1];
// Causes an SObjectException because we didn't retrieve
// the Total_Inventory__c field.
Double inventory = m.Total_Inventory__c;
} catch(SObjectException se) {
System.debug('The following exception has occurred: ' + se.getMessage());
}

Exception Methods
Some exception types, such as DmlException, have specific exception methods that apply to only them:
getDmlFieldNames(Index of the failed record): Returns the names of the fields that caused the error for the specified failed record.

getDmlId(Index of the failed record): Returns the ID of the failed record that caused the error for the specified failed record

getDmlMessage(Index of the failed record): Returns the error message for the specified failed record

getNumDml: Returns the number of failed records.

Merchandise__c m1 = new Merchandise__c(
Name='Coffeemaker',
Description__c='Kitchenware',
Price__c=25,
Total_Inventory__c=1000);
// Missing the Price and Total_Inventory fields
Merchandise__c m2 = new Merchandise__c(
Name='Coffeemaker B',
Description__c='Kitchenware');
// Missing all required fields
Merchandise__c m3 = new Merchandise__c();
Merchandise__c[] mList = new List<Merchandise__c>();
mList.add(m1);
mList.add(m2);
mList.add(m3);
try {
insert mList;
} catch (DmlException de) {
Integer numErrors = de.getNumDml();
System.debug('getNumDml=' + numErrors);
for(Integer i=0;i<numErrors;i++) {
System.debug('getDmlFieldNames=' + de.getDmlFieldNames(i));
System.debug('getDmlMessage=' + de.getDmlMessage(i));
}
}

Creating Custom Exceptions
Since you can’t throw built-in Apex exceptions but can only catch them, you can create custom exceptions to throw in your methods. That way, you can also specify detailed error messages and have more custom error handling in your catch blocks. To create your custom exception class, extend the built-in Exception class and make sure your class name ends with the word Exception. Append extends Exception after your class declaration as follows.

public class MyException extends Exception {}

EX:-

Public class ContactException extends Exception{}

public class ContactUtility {
   public static void mainProcessing() {
       try {
           insertContact();
       } catch(ContactException me) {
           System.debug('Message: ' + me.getMessage());    
           System.debug('Cause: ' + me.getCause());    
           System.debug('Line number: ' + me.getLineNumber());    
           System.debug('Stack trace: ' + me.getStackTraceString());    
       }
   }
   
   public static void insertContact() {
       try {
           // Insert Contact without required fields
           Contact m = new Contact();
           insert m;
       } catch(DmlException e) {
           // Something happened that prevents the insertion
           // of Contact objects, so throw a more
           // specific exception.
           throw new ContactException(
               'Contact could not be inserted.', e);
       }
   }
}

Sunday, 29 May 2016

HOW TO WRITE BATCH CLASS IN SALESFORCE.COM APEX

In order for us to write batch classes in apex, let us 1st understand what is batch class , when and where it should be used? This is an extensive blog going into details.
Main sections of this post are
  1. What is batch Apex
  2. When to use batch apex
  3. Advantages of using batch apex
  4. Batch Apex Governor limits
  5. Sample Code


What is Batch Apex ?

Batch as the name suggests, is used when a large data (bulk) volume is involved and it has to be redundantly processed using a particular logic.
The Batch apex, can be used to conveniently perform time to time task and some real complex job ranging from data cleansing, archiving the data to the other quality improvements.  

When to use Batch Apex?

The typical use of batch apex is when you want to do a bulk job, but if you do it in a regular apex you’re bound to hit the governor limits. Batch Classes process the set of records you pass to it in batches of maximum 200 per batch. To  learn more about the governor limits go here



Advantages of using Batch Apex?


  • Higher Governor Limits
  • Can be used to process in batches
  • Can be scheduled to run at different time. (read more)
  • Work around to other governor limits e.g. Send More than 10 E-mails blog by Ankit Arora

  • here is the governor limit difference in using batch
    Area
    Normal Context
    Batch Context
    SOQL queries100 SOQL per cycle200 SOQL per cycle
    records retrieved by SOQL queries50,00050,000,000 (getQueryLocator)
    executed code statements200,0001,000,000 (Winter '14)
    Heap size6 MB12 MB


    Batch Apex Governor Limits

    These are the governor Limits you need to keep in mind when dealing with Batch Apex
    • Up to five queued or active batch jobs are allowed for Apex.
    • A user can have up to 50 query cursors open at a time. For example, if 50 cursors are open and a client application still logged in as the same user attempts to open a new one, the oldest of the 50 cursors is released. Note that this limit is different for the batch Apex startmethod, which can have up to five query cursors open at a time per user. The other batch Apex methods have the higher limit of 50 cursors. Cursor limits for different Force.com features are tracked separately. For example, you can have 50 Apex query cursors, 50 batch cursors, and 50 Visualforce cursors open at the same time.
    • A maximum of 50 million records can be returned in the Database.QueryLocator object. If more than 50 million records are returned, the batch job is immediately terminated and marked as Failed.
    • If the start method returns a QueryLocator, the optional scope parameter ofDatabase.executeBatch can have a maximum value of 2,000. If set to a higher value, Salesforce chunks the records returned by the QueryLocator into smaller batches of up to 2,000 records. If the start method returns an iterable, the scope parameter value has no upper limit; however, if you use a very high number, you may run into other limits.
    • If no size is specified with the optional scope parameter of Database.executeBatch, Salesforce chunks the records returned by the start method into batches of 200, and then passes each batch to the execute method. Apex governor limits are reset for each execution of execute.
    • The startexecute, and finish methods can implement up to 10 callouts each.
    • Batch executions are limited to 10 callouts per method execution.
    • The maximum number of batch executions is 250,000 per 24 hours.
    • Only one batch Apex job's start method can run at a time in an organization. Batch jobs that haven’t started yet remain in the queue until they're started. Note that this limit doesn't cause any batch job to fail and execute methods of batch Apex jobs still run in parallel if more than one job is running.


    Sample Code

    Batch Class :
       global class ExampleBatchClass implements Database.Batchable<sObject>{
    
            global ExampleBatchClass(){
                       // Batch Constructor
            }
           
            // Start Method
            global Database.QueryLocator start(Database.BatchableContext BC){
             return Database.getQueryLocator(query);
            }
          
          // Execute Logic
           global void execute(Database.BatchableContext BC, List<sObject>scope){
                  // Logic to be Executed batch wise      
         
           }
         
           global void finish(Database.BatchableContext BC){
                // Logic to be Executed at finish
           }
        }
    


    Call the Batch Class : 

    ?
    1
    2
    3
    ExampleBatchClass b = new ExampleBatchClass();
    //Parameters of ExecuteBatch(context,BatchSize)
    database.executebatch(b,10);
    Note : if batch size is not mentioned it is 200 by default. 

    For More About Batch Job: For More Info's:

    Saturday, 28 May 2016

    Visualforce Form Tags with Examples

    Good Link Study all VF Tags

    http://sfdcsrini.blogspot.com/2014/06/visualforce-form-tags-with-examples.html

    Import csv file using apex visualforce

    Import csv file using apex visualforce

    Normally we use Apex data loader to import data in salesforce from CSV file. Now a days some other tools are also available to load data in salesforce like Jitterbit data loader. But sometime there is requirement when end users do not want to use Apex Data loader. They want some custom page to load data in salesforce. Then in that case we can use custom code to load data in salesforce from csv file.
    Also sometime using single CSV file we want to load data in multiple objects. Then in that case we can not use data loader to load data. In that case we can use custom code to load data in salesforce.
    In the example below we are loading data from CSV file for account objects.
    First of all we need CSV file format. Click here to download CSV file. You can modify CSV file to insert or import account records. CSV file attached has following format:
    Import csv file using apex visualforce
    Now we need to write code in Apex and visualforce which will  read csv file and insert records in account object.
    Click on choose file, then select csv file and then click on ‘Import Account’ button. All records from csv file will be inserted on account records. I have commented insert account line. So this example will only show account records on visualforce page. You can uncomment insert account list line in below code if you want to insert account list.
    Import csv file using apex visualforce
    Visualforce Page:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <apex:page controller="importDataFromCSVController">
        <apex:form >
            <apex:pagemessages />
            <apex:pageBlock >
                <apex:pageBlockSection columns="4">
                      <apex:inputFile value="{!csvFileBody}"  filename="{!csvAsString}"/>
                      <apex:commandButton value="Import Account" action="{!importCSVFile}"/>
                </apex:pageBlockSection>
            </apex:pageBlock>
            <apex:pageBlock >
               <apex:pageblocktable value="{!accList}" var="acc">
                  <apex:column value="{!acc.name}" />
                  <apex:column value="{!acc.AccountNumber}" />
                  <apex:column value="{!acc.Type}" />
                  <apex:column value="{!acc.Accountsource}" />
                  <apex:column value="{!acc.Industry }" />
            </apex:pageblocktable>
         </apex:pageBlock>
       </apex:form>
    </apex:page>
    Apex Code:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    public class importDataFromCSVController {
    public Blob csvFileBody{get;set;}
    public string csvAsString{get;set;}
    public String[] csvFileLines{get;set;}
    public List<account> acclist{get;set;}
      public importDataFromCSVController(){
        csvFileLines = new String[]{};
        acclist = New List<Account>();
      }
      
      public void importCSVFile(){
           try{
               csvAsString = csvFileBody.toString();
               csvFileLines = csvAsString.split('\n');
                
               for(Integer i=1;i<csvFileLines.size();i++){
                   Account accObj = new Account() ;
                   string[] csvRecordData = csvFileLines[i].split(',');
                   accObj.name = csvRecordData[0] ;            
                   accObj.accountnumber = csvRecordData[1];
                   accObj.Type = csvRecordData[2];
                   accObj.AccountSource = csvRecordData[3];  
                   accObj.Industry = csvRecordData[4];                                                                            
                   acclist.add(accObj);  
               }
            //insert acclist;
            }
            catch (Exception e)
            {
                ApexPages.Message errorMessage = new ApexPages.Message(ApexPages.severity.ERROR,'An error has occured while importin data Please make sure input csv file is correct');
                ApexPages.addMessage(errorMessage);
            
      }
    }