Apex Day Lab Exercises

Contents

Objectives

The objective for the Apex Day labs is to experience first hand the power of Apex Code and to introduce the basic concepts of triggers and classes.

In this hands-on lab, you will learn the fundamental concepts, architecture, and features of Apex Code. The first exercise is building and testing the Apex version of “Hello World”. Building on the first exercise, the second exercise involves building and testing a simple trigger that prevents duplicate leads from being entered based on very simple logic. The third and final exercise extends the previous exercise by creating a task for the user when a new Lead is successfully entered. All exercises can be completed by following this step-by-step guide and using the Force.com IDE.

Prerequisites

This hands-on lab assumes you have some basic knowledge or programming experience on the following technologies, but is not required.

  • Java
  • Force.com API

Lab Setup Instructions

To complete this lab your environment must meet the following criteria:

  • Force.com Developer Edition (Apex Code enabled)
  • Software requirements:
1. Web Browser
2. Eclipse 3.2
3. Force.com IDE Image:Key_icon.gif

Lab Exercises:

This lab is made of the 3 exercises each of which takes between 5 to 10 minutes each. Please proceed through the lab by doing the exercises in sequence.

  • Exercise 1: Hello World (~8 minutes)
  • Exercise 2: Lead duplicate prevention (~10 minutes)
  • Exercise 3: Create related records (~7 minutes)


Exercise 1:Hello World

(~8 minutes)

Introduction:

Every good introductory programming lab should have a Hello World application and Apex Code is no different. In this exercise you are going to build a simple trigger that is executed when a Lead record is saved. The sample code for each exercise is provided in its complete form in the “Apex Day” snippets group in Eclipse. You view the snippets by selecting Window/Show View/Other and selecting Snippets from the General category.

Steps to follow:

  • Create an Apex project in eclipse.
  • Create a new Trigger for the Lead object
  • Build the Trigger code
  • Test your new Trigger

Step 1: Create Apex project in eclipse.

1. Launch Eclipse using the shortcut on your desktop.
2. Click File/New/Project from the Eclipse main menu.
3. In the wizard, find and expand the Apex group.
4. Select “Apex Project” and click next.
5. The Force.com IDE interacts frequently with the data in you salesforce.com account. Because of this you will be required to enter the information required to gain access.
5.1. Enter a name for you new project.
5.2. Enter your salesforce.com username.
5.3. Enter your salesforce.com password.
5.4. Leave the remaining options set to their defaults.
5.5. Click the “Finish” button.
6. You now have an Apex project and can continue with the next step. If you don’t see a folder named “Triggers” or “Classes” in your project then you have not had Apex enabled for this account.

Step 2: Create a new Trigger for the Lead object

1. Right-click the Triggers folder of you Apex project in the Class Explorer and select New/Other.
2. In the wizard begin typing the word “Apex” in the Wizards: text box to filter the list below it.
3. Select Apex Trigger then click the “Next >” button.
4. Enter a descriptive name for the Trigger name such as “LeadTutorial”.
5. The dropdown list below the Trigger name box displays all the objects that are in your salesforce.com account. Find and select Lead.
6. Triggers can be fired on any combination of the events shown in the Trigger Operations section. For our exercise place a click in the “Before Insert” choice and click the “Finish” button.
7. You now have a Trigger whose code will run each time a Lead is saved.

Step 3: Build the Trigger code

1. In the Apex Code editor type the following line of code below the Trigger declaration. This line demonstrates access the Object that fired the trigger and simply creates a variable reference to it.
private Lead[] newLead = Trigger.new;
2. Next we will access one of the fields on the Lead object, the FirstName field, to demonstrate how to access an object’s data.
newLead[0].FirstName = 'Hello World ' + newLead[0].FirstName;
3. The final Trigger should look like the code below:
trigger LeadTutorial on Lead(before insert) {
	private Lead[] newLead = Trigger.new;
	newLead[0].FirstName = 'Hello World ' + newLead[0].FirstName;	
}
4. Now we can compile and save our trigger by either clicking the Save button on the toolbar, entering ctrl-s or by selecting File/Save from the main menu.

NOTE: If the Trigger cannot compile you will see a red marker next to the line of code that is in error. To determine what the problem is, you can hover you mouse over the marker for a couple of seconds and a popup will appear indicating the text of the error, or open the Problems view using Window/Show View/Problems.

Step 4: Test your new Trigger

  • Using your browser, log in to your Developer Edition account using the same credentials that you supplied during the creation of your Apex Project.
  • Create a new Lead entering “Sam” for the first name, “Jones” for the last name and “ACME” for the company.
  • Click the Save button and observe the results.
  • Notice that the text “Hello World ” is prepended to the FirstName field.

This concludes Exercise 1.

Exercise 2:Lead duplicate prevention

(10 minutes)

Introduction

In this exercise, you are going to create a new Trigger that will check for duplicates before allowing a new record into the database, for this sample we are checking email address.

Steps to follow:

  • Create a new Trigger
  • Insert the code
  • Test the modified Trigger

Step 1: Create a new Trigger

  • From the Class Explorer in Eclipse, right-click the Trigger folder in your Apex project and select New/Other
  • In the wizard begin typing the word “Apex” in the Wizards: text box to filter the list below it.
  • Select Apex Trigger then click the “Next >” button.
  • Enter a descriptive name for the trigger name such as “DuplicateLogic” and click the “Finish” button.
  • Select the object to place the trigger on, specify Lead
  • Check the boxes before insert and before update

Step 2: Build the Trigger duplicate Lead logic

Determining what constitutes a duplicate varies by individual company. To keep our focus on the code, we will define a duplicate as a Lead with the same email address as an existing Lead. When we determine that a Lead is a duplicate, we will indicate that with an Object error that is displayed on the Lead edit page. We will use a function that takes the email address of the proposed Lead as an argument and returns true if another Lead exists with that email address and false if not.

  • Your new trigger should look like this
trigger leadDuplicatePreventer on Lead (before insert, before update) {

}


  • Enter a map declaration to hold records which we will add, this will become a unique map, no duplicate values within it.
	Map<String, Lead> leadMap = new Map<String, Lead>();


  • The next few lines loop across the array of records that are passed into the trigger in bulk fashion from any API or User Interface database operation. The goal of this loop is to ensure that there are no duplicates within the batch that we have received and to gather a list of emails that we will use later
	for (Lead lead : System.Trigger.new) {
	
		/* Make sure we don't treat an email address that
		   isn't changing during an update as a duplicate. */
		if ((lead.Email != null) && (System.Trigger.isInsert || (lead.Email != System.Trigger.oldMap.get(lead.Id).Email))) {
	
			// Make sure another new lead isn't also a duplicate
			if (leadMap.containsKey(lead.Email)) {
				lead.Email.addError('Another new lead has the same email address.');
			} else {
				leadMap.put(lead.Email, lead);
			}
		}
	}


  • Now we have a map of leads with email as a key. We will use this map to detect duplicates in the database. Add the following loop to perform a SOQL query for any email addresses which are IN our map, those are duplicates and will be blocked.


The apex code which performs this check in one single SOQL statement is shown here, add this to your trigger.

 
	/* Using a single database query, find all the leads in
	   the database that have the same email address as ANY
	   of the leads being inserted or updated. */
	for (Lead lead : [SELECT Email FROM Lead WHERE Email IN :leadMap.KeySet()]) {
		Lead newLead = leadMap.get(lead.Email);
		newLead.Email.addError('A lead with this email address already exists.');
	}

At this point you should have a trigger that contains your duplicate detection logic and is ready to test

  • The final trigger should look like this:
/*
  Force.com Cookbook Sample Code
  Chapter 6: Improving Data Quality
  "Preventing Duplicate Records from Saving"

  This Apex trigger prevents leads from being saved if they have a 
  matching Email field.

  Sample code provided by salesforce.com. All rights reserved.
 */
trigger leadDuplicatePreventer on Lead (before insert, before update) {

	Map<String, Lead> leadMap = new Map<String, Lead>();

	for (Lead lead : System.Trigger.new) {
	
		/* Make sure we don't treat an email address that
		   isn't changing during an update as a duplicate. */
		if ((lead.Email != null) && (System.Trigger.isInsert || (lead.Email != System.Trigger.oldMap.get(lead.Id).Email))) {
	
			// Make sure another new lead isn't also a duplicate
			if (leadMap.containsKey(lead.Email)) {
				lead.Email.addError('Another new lead has the same email address.');
			} else {
				leadMap.put(lead.Email, lead);
			}
		}
	}
	
	/* Using a single database query, find all the leads in
	   the database that have the same email address as any
	   of the leads being inserted or updated. */
	for (Lead lead : [SELECT Email FROM Lead WHERE Email IN :leadMap.KeySet()]) {
		Lead newLead = leadMap.get(lead.Email);
		newLead.Email.addError('A lead with this email address already exists.');
	}
}


  • Now you are ready to compile and save your Trigger by either clicking the Save button on the toolbar, entering ctrl-s or by selecting File/Save from the main menu

Step 4. Testing the modified Trigger

  • Using your browser, log in to your Developer Edition account using the same credentials that you supplied during the creation of your Apex Project.
  • Create a new Lead entering “George” for the first name, “Cloney” for the last name, “ACME” for the company and “john@doe.com” for the email address.
  • Click the Save button and observe the results. The lead should be created and you should now be on the Lead detail page.
  • Next click the Clone button at the top of the Lead detail page.
  • Click the Save button
  • Observe the results.
  • You should notice that the text “Duplicate Lead detected with email john@doe.com” that we passed to the newLead.addError() method is displayed at the top of the page.
  • You should also notice that the text “Email in use” that we passed to the newLead.Email.addError() method is displayed directly beneath the email field on the Lead detail page.

This concludes Exercise 2

Exercise 3:Create Related Records

(7 minutes)

Introduction

In this exercise, you are going to create a Task upon successful creation of a new Lead record. The purpose of this exercise is to demonstrate how to use the Data Manipulation Language (DML) feature of Apex code. After a new lead record has been inserted we want to create a new task associated with that Lead.

Steps to follow:

  • Add an after insert specifier to the trigger
  • Modify your Lead trigger to separate the before lead insert and after lead insert
  • Add code to create a task for each lead
  • insert the tasks in one (bulk) insert statement
  • Test your changes

Step 1: Add an after insert specifier to the trigger

  • The Trigger needs to be modified to be fired after a new record has been created. Recall that in the previous exercise we created a Trigger for the “before insert” event on the Lead object. The code shown in bold below indicates the changes to make.
  • Change the signature of the trigger to add after insert, this will cause the trigger to be called again after the leads are committed to the database. The trigger declaration now looks like this:
 
trigger leadDuplicatePreventer on Lead (before insert, before update, after insert) {

Step 2: separate the code that will execute before the lead is added from the code we will add to create tasks after lead is created.

  • Add the following if statements
 
  if (Trigger.isBefore) { 

[ body of trigger ] 

  } else if (Trigger.isAfter)  { 
} // end of trigger

in context this looks like the following:

trigger leadDuplicatePreventer on Lead (before insert, before update, after insert) {
  if (Trigger.isBefore) { 
	Map<String, Lead> leadMap = new Map<String, Lead>();

[body deleted...]

 } else if (Trigger.isAfter)  { 
  	// after leads are inserted
  } 

} // end of trigger


  • Now you are ready to compile and save your Class by either clicking the Save button on the toolbar, entering ctrl-s or by selecting File/Save from the main menu

Step 3: Modify your Lead Trigger to create tasks

  • We will use the following loop to create tasks, note we will not insert them until all are ready, they are gathered into a list until that time.
 } else if (Trigger.isAfter)  { 
  	// after leads are inserted
  	List<Task> followupTasks = new List<Task>(); // build list in memory
  	for (Lead lead : System.Trigger.new) {
		Task task = new Task(
		  WhoId = lead.Id, 
		  Description = 'Call this lead.', 
		  Priority = 'High', 
		  ReminderDateTime = System.now().addDays(2), 
		  Status = 'Not Started', 
		  Subject = 'New Lead');
		followupTasks.add(task);   // add to list
  	}

        // insert the entire list
  	insert followupTasks;  // NOTE: this is outside the above loop, only one insert is needed

 } // end of isAfter

}// end of trigger

  • Now you are ready to compile and save your Trigger by either clicking the Save button on the toolbar, entering ctrl-s or by selecting File/Save from the main menu

Step 3: Test your changes

  • Using your browser, log in to your Developer Edition account using the same credentials that you supplied during the creation of your Apex Project.
  • Create a new Lead entering “Jeff” for the first name, “Crow” for the last name and “jane@doe.com” for the email address.
  • Click the Save button and observe the results. The lead should be created and you should now be on the Lead detail page.
  • Next click the Home tab to navigate to your home page.
  • You should now see a new Task in your task list with the Lead name in the name column.

This concludes Exercise 3

For reference, here is the entire trigger after exercise #3

/*
  Force.com Cookbook Sample Code
  Chapter 6: Improving Data Quality
  "Preventing Duplicate Records from Saving"

  This Apex trigger prevents leads from being saved if they have a 
  matching Email field.

  Sample code provided by salesforce.com. All rights reserved.
 */
trigger leadDuplicatePreventer on Lead (before insert, before update, after insert) {
  if (Trigger.isBefore) { 
	Map<String, Lead> leadMap = new Map<String, Lead>();

	for (Lead lead : System.Trigger.new) {
	
		/* Make sure we don't treat an email address that
		   isn't changing during an update as a duplicate. */
		if ((lead.Email != null) && (System.Trigger.isInsert || (lead.Email != System.Trigger.oldMap.get(lead.Id).Email))) {
	
			// Make sure another new lead isn't also a duplicate
			if (leadMap.containsKey(lead.Email)) {
				lead.Email.addError('Another new lead has the same email address.');
			} else {
				leadMap.put(lead.Email, lead);
			}
		}
	}
	
	/* Using a single database query, find all the leads in
	   the database that have the same email address as any
	   of the leads being inserted or updated. */
	for (Lead lead : [SELECT Email FROM Lead WHERE Email IN :leadMap.KeySet()]) {
		Lead newLead = leadMap.get(lead.Email);
		newLead.Email.addError('A lead with this email address already exists.');
	}
  } else if (Trigger.isAfter)  { 
  	// after leads are inserted
  	List<Task> followupTasks = new List<Task>();// build list in memory
  	for (Lead lead : System.Trigger.new) {
		Task task = new Task(
		  WhoId = lead.Id, 
		  Description = 'Call this lead.', 
		  Priority = 'High', 
		  ReminderDateTime = System.now().addDays(2), 
		  Status = 'Not Started', 
		  Subject = 'New Lead');
		followupTasks.add(task);  // add to list
  	}
  	
    // insert the entire list
  	insert followupTasks;  // NOTE: this is outside the above loop, only one insert is needed

 } // end of isAfter

}// end of trigger

Resources

Do not forget to utilize the DFC site - http://developer.force.com as your one-stop site to access related articles, sample code, discussion board, in-depth documentation as well as on-demand sessions.