August 28, 2011

Sorting Apex SelectOption Array/List !

All apex developers creating visualforce pages with drop-downs and checkboxes use Apex SelectOption class. On most of the occasions instances of this class are created out of records in database that we can query in a desired alphabetical order for ex.
“Select CountryName__c, Country_code__c from Country_Master__c Order by CountryName__c”
So here we can easily create a drop down of countries having country names in ascending sorted order.
But, on a couple of occasions we have to sort Selectoptions without using SOQL ordering. So custom sorting is required, unfortunately Apex collections API just gives sorting API on List for primitives. So I tried to come up with a simple sorting API just for SelectOption collections only. The whole API is available in a class called “SelectOptionSorter”.

SelectOptionSorted API

The core motive of this API was to give simple and efficient sorting for Apex SelectOption only. Here being efficient is very important, as sorting algos mostly end up taking huge amount of script statements, and Apex Governor gives us 200,000 lines only !
So to be efficient this API,
  • Uses Apex System/Native List.Sort() to get the actual sorting done.
  • Number of script lines are minified to best extent, to give more script line bandwidth to client code for other stuff.
This API provides sorting support on either of Label or Value field of SelectOption, though sorting on Label makes sense most of the times, but who knows Smile

Code Sample

// This is the Array of SelectOptions to be sorted
Selectoption[] opts = new Selectoption[] {
                                   new Selectoption('v8', 'l8'),
                                   new Selectoption('v1', 'l1'),
                                   new Selectoption('v5', 'l5')
                               };

Code Sample – Sort by Label

// doSort() returns nothing, it sorts the same inbound collection
SelectOptionSorter.doSort(opts, SelectOptionSorter.FieldToSort.Label);

Code Sample – Sort by Value

// doSort() returns nothing, it sorts the same inbound collection
SelectOptionSorter.doSort(opts, SelectOptionSorter.FieldToSort.Value);

 

Source on GitHub.com

Here is the link to the repos : https://github.com/abhinavguptas/Apex-Select-Option-Sorting

Using Apex-Commons for the same !

One of a really good framework available to sort any Type is Apex-Commons, it is available on git here : https://github.com/apex-commons. This framework is really a rich collections of not only sorting, but many other useful APIs. If you are already using it and know how to sort custom types using it, you can use Apex-Commons very well. My core reason of coming with this stand alone API was
  • I want a simple to deploy and use sorting API for a common Apex system class i.e. SelectOption. So its just one single class with all code and test methods in it. Just copy it and use it for good.
  • Apex-Common sorting algo is great and is very generic like Java Collections API sorting algos. It is generic as it can sort any Apex Type, one just need to create a right comparator. But this generosity comes with some cost, and its number of script lines, more details explained here.
  • Sorting Algo used in SelectOptionSorter API uses List.sort() internally, so all heavy lifting is done by Native Apex and script statements are saved. So typically a list of “N” items would be sorted in “3N” script lines.

Feedback

Would love to hear back your views and comments.

August 2, 2011

Calling Marketo SOAP API from Salesforce APEX Classes !

We know about Marketo and its having a deep Salesforce integration.  Recently I came across a new requirement to call Marketo SOAP API from Apex. You must be thinking this process is pretty straight forward, but it required me a bit of effort to make it working, so thought of sharing this via blog and code on GIT, so that other busy developers can fork/reuse and save some time :)
I started falling in love with github.com, so the two core classes involved in this prototype are available there.  Here is the link to the repository : https://github.com/abhinavguptas/apex-marketo-soap-api-helper

Basic steps : From Marketo WSDL to Apex Stubs.

To start with I followed the normal steps to import a WSDL and generate Apex classes from it, i.e.
  • Download the required WSDL, I tried this one : http://app.marketo.com/soap/mktows/1_6?WSDL
  • Goto Setup > Develop > Apex Classes > Hit "Generate From WSDL" button
  • In the wizard next, feed the WSDL downloaded above to generate a single master apex class having everything. I named this WSDL2Apex class "Mktows.cls". For more details on this process, please refer to this Salesforce Guide.
Next, we will see what are the few things you need to make a successful call to Marketo SOAP operations.

Obtain Marketo UserId, Enc Key and SOAP Endpoint

All this information is available in Marketo Admin Console. Just goto Admin > Integration > SOAP API menu item in left side tree view. You will find all the details as indicated in the screenshot below
image

Setting up the Authorization Headers correctly !

This is the only tricky part in after generating WSDL2Apex stub i.e. Mktows.cls. Creating correct Marketo AuthorizationHeader requires a few things, like
  • Calculating a W3C Datetime format TimeStamp for request.
  • Calculating HMacSHA1 signature using
    1. the timestamp generated in previous step
    2. + Marketo User Id
    3. and Marketo Encryption Key
  • Converting that HMacSHA1 to Hex.
We are lucky that recently Apex added some super useful classes like
  • Datetime : That now takes Dateformat like “yyyy-MM-dd\'T\'HH:mm:ssZ” and converts the datetime value in that. This helped in generating the request timestamp.
  • Crypto : Super helpful in generating signatures for various algos like HMacSHA1
  • EncodingUtil : For generating Hex required for Marketo signatures.
Once this Auth Header is prepared correctly, we just need to associate it with WSDL2Apex Ports.

“MarketoClient.cls” – A helper class !

All the code to create correct AuthenticationHeader and associating it correctly with WSDL2Apex stubs is available in this class called MarketoClient.cls. This class is the core helper class that will prepare a correct Marketo SOAP Apex Port instance, that will be ready for making SOAP calls to various Marketo operations.
Here is a sample code that prepares the port using Marketo User Id and Encryption Key
String mktowsUserId = '[YOUR MARKETO USER ID]';
String encKey = '[YOUR MAKRETO ENCRYPTION KEY]';
// Instantiate MarketoClient using the userId and encKey
MarketoClient client = new MarketoClient(mktowsUserId, encKey);
// Get a readymade SOAP Port using prepareSoqpPort() call
MkTows.MktowsApiSoapPort port =  client.prepareSoapPort();

// Now one can call any method for ex.
// code below gets Lead for a given email via Marketo
Mktows.LeadKey objLeadKey=new Mktows.LeadKey();
objLeadKey.keyType='EMAIL';
objLeadKey.keyValue='abhinav@tgerm.com';
Mktows.ResultGetLead results =port.getLead(objLeadKey);
You might need to change the SOAP endpoint, its defaulting to 'https://na-c.marketo.com/soap/mktows/1_6' in MarketoClient class. Doing this is pretty simple, just update this static variable to required in MarketoClient.cls, for ex.
/**
Change this endpoint if required, as per your Marketo SOAP Endpoint*/
public static String API_ENDPOINT = 'https://na-c.marketo.com/soap/mktows/1_6';

Feedback & Views !

Would love to read your views and comments on this, please share !