MK Partners Apex Code

LinkedIn APIs are now open!!

We just got this email from LinkedIn:

You requested access to the LinkedIn APIs and we wanted you to be the first to know that our APIs are now available.

With the LinkedIn platform, your users can bring their professional identities and networks with them to your site. You’ll be able to provide more engaging experiences and extend your site’s reach.

Visit the LinkedIn Developer Network to learn more about how you can get access to rich professional information and core LinkedIn features.

The race is on for all developers to integrate with LinkedIn!

Batch Apex Demo at nonprofitcrm.org

Our friends at nonprofitcrm.org have put together a great demo of batch Apex. Check it out here.

Since batch Apex is only available in pilot, you may not be that familiar with it. It’s an asynchronous form of Apex that can run over the normal Apex governor limits. It’s very useful for nightly jobs that have to run on all your records and other complex processes.

Validating email addresses in Apex

Warning!!! This post is for the Uber-Apex Programmer and should not be attempted by novices. It may cause headaches, hair-loss, eye-strain and more, but it’s well worth it!

On two different occasions in the last week a client has needed email addresses in salesforce.com validated. The only true form of validation for an email address is to send an email and see if it bounces. This post doesn’t cover that. Instead, we’re focusing on the formatting of the email address.

According to a salesforce.com solution (login required), as of the Winter ‘08 release, salesforce.com validates email addresses as follows:
1. For the local part of the email address we accept the following characters. (The local part is anything before the @ sign.)
abcdefg.hijklmnopqrstuvwxyz!#$%&’*/=?^_+-`{|}~0123456789
Note: The character dot “.” is supported; provided that it is not the first or last character in the local-part
2. For the domain part of the email address we accept. The domain part is anything after the @ in an email address:
0-9 and A-Z and a-z and dash “-“
3. Example email address:
abcdefg.hijklmnopqrstuvwxyz!#$%&’*/=?^_+-`{|}~0123456789@acme-inc.com

Our goal was to perform the same validation via Apex prior to saving the record. This can be done using a lot of String methods and If statements, but really this type of comparison is best done with a Regular Expession.

Apex already has built-in Pattern and Matcher Classes for this purpose, so all we had to do was come up with the right regular expression. Thanks to some tips at www.regular-expressions.info it was actually an easy task to complete. It was so easy, that we’re releasing this code into the wild for all of our customers (and competitors) to use.

String pat = '[a-zA-Z0-9\\.\\!\\#\\$\\%\\&\\*\\/\\=\\?\\^\\_\\+\\-\\`\\{\\|\\}\\~\'._%+-]+@[a-zA-Z0-9\\-.-]+\\.[a-zA-Z]+';
Boolean test = Pattern.matches(pat, email);

Force.com IDE update

This weekend I updated to the latest version of the Force.com IDE, 16.0.0.200906151227 which was released last week. The upgrade process is simple, as always. This release now supports Eclipse 3.4, which based on my non-scientific tests seems to handle memory much better!

More info can be found at developer.force.com.

Composite Application Case Study

The following is a fictitious case study that addresses the need to synchronize data between Salesforce and an external system in near real-time. This case study is intended for Apex developers and managers who would like to understand the potential of the Force.com platform.

Business need:

Custom software producer (Company X) manages very large data sets for their clients (TB+) and wants to tap into the growing Salesforce market with a new AppExchange offering that ties Salesforce data with theirs. Contact data must be synced between their cloud and the Force.com cloud in near real-time. After initial synchronization, changes in Salesforce need to be reflected in their cloud for each client that purchases their product.

Solution:

An AppExchange application is developed to satisfy the business needs. Initial data export from SF involves using the Force.com API but this case study focuses on synchronizing the data once the export has been completed. Ongoing synchronization from Force.com involves database triggers and asynchronous callout methods. A trigger fires on Contact after insert and after update. Trigger instantiates an Apex class (less governor limits than within trigger code) that records data for future synchronization. A separate update class uses a web service or HTTP Post (RESTful) callout, whichever makes more sense for Company X.

I know what you’re all thinking: “That’s IMPOSSIBLE! Even with the reduced governor limits of an Apex class versus an Apex trigger, Salesforce absolutely forbids callouts from anywhere if the initial entry point was a trigger.” Good thinking! This used to be true. However, now you can use the @Future Apex annotation to declare asynchronous callouts that fire when resources are available. You can expose a web service to receive the results when the data is finished processing at Company X.

A few considerations about the @Future keyword:

  • You can have no more than 10 @Future calls per Apex invocation.
  • There is a limit of 200 @Future calls per Salesforce license per 24 hours.
  • @Future parameters must be primitive dataypes, arrays of primitive datatypes, or collections of primitive datatypes.
  • Methods with the future annotation cannot take sObjects or objects as arguments.
  • Methods with the future annotation cannot be used in Visualforce controllers in either getMethodName or setMethodName methods, nor in the constructor.

Considering the limitations of functions leveraging the asynchronous @Future keyword, one possible method to accomplish the goals of this case study is to store all update data that needs to transfer over the web to Company X’s cloud and read it from the Salesforce database in the @Future function. This eliminates the need to pass in sObjects or other complex data to the function. When the insert or update trigger fires the appropriate data is written to the “update” table. Then either a user initiated synchronization can transfer the new/changed records (via Visualforce page button, for example) or a timed based process can fire – such as Company X calling in via a web service and telling the AppExchange program to wake up and send the latest changes. The @Future function might look something like this:

HTTP Callout

This function can be called from a trigger that was fired from a Contact insert/update since the execution happens in the @Future and the parameters passed in are primitive data types.

Dynamic Picklist Creation and Sorting

Here’s a way to dynamically create a Picklist in Apex, pre-sort the list, and present it in a Visualforce page. In Salesforce it’s not possible to dynamically change Picklist values without getting deep into Force.com API programming. If you wanted to prepare a list of all Contact field names and their labels including custom fields with current information, you would need to generate this dynamically with metadata. To accomplish this we can generate it in Apex and present it in a way that looks like a native Salesforce Picklist.

I’ve included usable code for grabbing Contact metadata so we can present the field Labels in the list and return the Value (Name, AccountId, OwnerId, CustomField1__c, CustomField2__c, etc.) The goal is to present the field labels in alphabetical order with “–None–” listed at the top. When selected this list will return the Id or actual name of the field as opposed to the presented field label. With these results you can use DML to get or set values in Contact.

Visualforce element:

<apex:pageBlockSectionItem >
   <apex:outputLabel value="Contact:" for="contactlist"/>
   <apex:selectList id="contactlist" value="{!contactField}" size="1">
      <apex:selectOptions value="{!contactFieldOptions}"/>
   </apex:selectList>
</apex:pageBlockSectionItem>

Value=”{!contactField}” is the public property defined in the Apex controller class:

public String contactField {get; set;}

//Function to load and sort Contact field metadata for binding to: “{!contactFieldOptions}”
public void loadContactFields()
{
              Map<String, Schema.SObjectField> m = Schema.SObjectType.Contact.fields.getMap();
              List<Schema.SObjectField> sof = m.values();
              contactFieldOptions = new List<selectOption>();
              Map<String, String> tmp = new Map<String, String>();
              List<String> tmp2 = new List<String>();

              for(Schema.SObjectField s : sof)
              {
                            tmp.put(s.getDescribe().getLabel(), s.getDescribe().getName()); // Reversed for sorting
                            tmp2.add(s.getDescribe().getLabel());
              }

              tmp2.sort(); // Sort by field label, not field name
              selectOption so = new selectOption('NONE', '--None--'); // Native SF look and feel
              contactFieldOptions.add(so); // Build the Select List

              for(String s : tmp2)
              {
                            so = new selectOption(tmp.get(s), s);
                            contactFieldOptions.add(so);
              }
}

Finally, you can use the result(s) for dynamic Apex operations such as SOQL:
s = Database.query(contactField + ‘, Namespace__CustomField1__c from Contact limit 1000′);

Pick a number 1-10, randomly, with Apex

In the past when we’ve had to come up with a random number, we’ve leveraged the randomness of when the user performed an operation. We would look at the minute or second that a function ran to come up with a number that would be somewhat random.

There’s actually a much easier way to do this and it’s built-in to Apex. The below code will pick a random number out of a range that you set. It’s extremely simple, enjoy!

public Integer randomNumber(Integer range)
{
Double x = math.random() * range;
return x.intValue();
}

Dynamically inserting the results from Dynamic SOQL

This is the 3rd post in a series discussing some complex code we’ve written for recent projects. Our first post detailed performing a query using Dynamic SOQL. Our second post detailed using the Describe method to compile a string of fields used in the Dynamic SOQL query. This third post demonstrates how to reinsert the results of the query.

The actual use case involved a custom clone/archive function that copied a new lead to a custom object. When copying from one object to another you have to ensure that all custom fields have the same API Name and then manually set any standard fields. To simplify the code, this example will copy a contact to a new contact.

//Function to clone existing Contact with dynamic APEX
public static void copyContact()
{
//Create a map from the results of a Describe of the Contact Object
Map<String, Schema.SObjectField> cFieldMap = Schema.SObjectType.Contact.fields.getMap();

//Generate a comma delimited String of Contact Fields
String conFields = '';
for ( String f : cFieldMap.keySet() )
{
	conFields += f;
	conFields += ',';
}
conFields = conFields.subString(0,conFields.Length() -1);

//Define a Where clause
String whereClause = 'WHERE Lastname != null ';

//Define an Order By clause to sort your query
String orderBy = ' Order By MailingState ';

//Define your entire Query as a string
String qryString = 'SELECT ' + conFields + ' FROM Contact ' + whereClause + orderBy + ' limit 1';

//Query salesforce with your Query string
List<Contact> queryResults = Database.query(qryString);

//Create a list of new contacts to insert
List<Contact> contactInserts = new List<Contact>();

for (Contact c : queryResults)
{
	Contact newC = new Contact();
	for ( String f : cFieldMap.keySet() )
	{
		Schema.SObjectField contactField = cFieldMap.get(f);
		Schema.DescribeFieldResult dfr = cFieldMap.get(f).getDescribe();
		if ( c.get(contactField) != null && dfr.isUpdateable() )
		{
			newC.put( cFieldMap.get(f), c.get(contactField) );
		}
	}
	contactInserts.add(newC);
}

insert ContactInserts;
}

Apex Describe with Dynamic SOQl

This is the 2nd post in a series discussing some complex code we’ve written for recent projects. Our first post detailed performing a query using Dynamic SOQL. In that post, you had to hard-code the Contact fields that you wanted to query. This isn’t always ideal. Sometimes you want to query all fields on the object and you don’t want to edit your code each time you add a new field.

You can accomplish this task by using the field describe result’s getMap() method. Which returns a map of field names and field describe details. Don’t worry about the field describe details portion of the Map, for now we just want the Map’s keySet, which contains every field on the Contact object.

The below code adds to our post from last week, using the above concept to compile a string of field names to use in our SOQL query.

public class website_WebServices
{
//Function to perform Dynamic SOQL query on Contacts
public static <Contact> getContacts(String whereClause)
{
//Create a map from the results of a Describe of the Contact Object
Map<String, Schema.SObjectField> cFieldMap = Schema.SObjectType.Contact.fields.getMap();

//Generate a comma delimited String of Contact Fields
String conFields = '';
for ( String f : cFieldMap.keySet() )
{
conFields += f;
conFields += ',';
}
conFields = conFields.subString(0,conFields.Length() -1);

//Define an Order By clause to sort your query
String orderBy = ' Order By MailingState ';

//Define your entire Query as a string
String qryString = 'SELECT ' + conFields + ' FROM Contact ' + whereClause + orderBy + ' limit 10';

//Query salesforce with your Query string
List<Contact> queryResults = Database.query(qryString);

return queryResults;
}

//Sample Where Clause
public static String whereClause = 'WHERE Lastname != null ';

//Sample function to get a list of Contacts by passing the Where Clause to the getContacts function
public static list<contact> contacts = getContacts(whereClause);

}

Dynamic Queries with Apex

Some of our recent projects have had very complex requirements that forced us to delve into unchartered terrority: Dynamic Apex. These requirements included changing the filter criteria for a query based on user input, custom merge functionality, and custom cloning a record to a different object. All of these functions are best written using Dynamic Apex. There is little documentation out there on using Dynamic Apex so we’ve decided to share our experiences with you. This is the first in a series of posts which will explain Dynamic Apex and how we used it for these projects.

Dynamic SOQL
With our partners Arrowpointe and Spark3, we recently integrated a php website with salesforce.com. Visitors to the website can browse through a list of contacts filtering on various attributes. In the past, this functionality would be written solely using the PHP Toolkit. However, to ensure consistency and reduce the amount of labor to transition to Force.com Sites, we used the PHP Toolkit to connect to salesforce and then call an Apex Web Service. Apex code does all the work to ensure that the data is queried with the correct criteria and then returned properly. Since the Where clause varies in our query we had to either use Dynamic SOQL or a large number of If/Then statements, we chose the former.

Below is a scaled down sample of code you can use to perform the same dynamic query. We’ve also provided you with the syntax for calling the function.

public class website_WebServices
{
    //Function to perform Dynamic SOQL query on Contacts
    public static List<Contact> getContacts(String whereClause)
    {
        //Sample list of Fields
        String fieldList = 'id, FirstName, LastName, Phone, Email ';

        //Define an Order By clause to sort your query
        String orderBy = ' Order By MailingState ';

        //Define your entire Query as a string
        String qryString = 'SELECT ' + fieldList + ' FROM Contact ' + whereClause + orderBy + ' limit 10';

        //Query salesforce with your Query string
        List<Contact> queryResults = Database.query(qryString);

        return queryResults;
    }

    //Sample Where Clause
    public static String whereClause = 'WHERE Lastname != null ';

    //Sample function to get a list of Contacts by passing the Where Clause to the getContacts function
    public static list<contact> contacts = getContacts(whereClause);

}