Monday, August 11, 2014

It's off to Dreamforce we go!

Dreamforce is the Mecca of Salesforce Development.  It's a pilgrimage that a Salesforce Developer must make at least once in their careers.  Although the cost is high, whether it's through registration, lodging, or billable hours as a Consultant, the benefits are enormous.

For one, Dreamforce offers an opportunity to network with your peers and top developers within the Salesforce community.  Chances are the moment you step foot out of your hotel on Monday morning, you will find someone you recognize.  Whether that person is a colleague, Salesforce employee, AE, or an MVP, who knows.  Don't be afraid to walk up and introduce yourself.

It's going to be a long day.  On your way to Moscone West, where all the techies hang out, stop by Starbucks and grab your latte.   It's always fun to see how they mispronounce your name on your cup.  Last year, they somehow turned "James" into "Juarez". Check out the Mini Hacks area and just walk around and explore for a bit.  It's overwhelming.

After you get settled in a bit, go check out some sessions.  The best and most informative sessions I attended were on the first day at Dreamforce last year.  I picked up some excellent pointers, and I'm sure you will too.

As the week progresses, don't be afraid to check out other areas outside Moscone West.  Head to the declarative sessions and pick up declarative tips from the formula geniuses like SteveMo or from the Success Community Zone where the MVPs hang out and answer any questions you may have.

As you soak everything in, make sure you take moments to reflect on your week.  Bring your ipads, notebooks, business cards, and document all you have learned over the long week.  In fact, here is my list of must haves for your Dreamforce trip.


  1. A notebook or an iPad for taking notes
  2. Your most recent business cards for networking
  3. Comfortable shoes.  You'll be walking a lot.  I racked up 35,000 fitbit steps on the first day last year.
  4. Precut moleskin pads.  You will get blisters.  Be prepared.  The precut pads are best, otherwise you will need to cut the moleskin, which isn't an easy venture.
  5. Extra space in your luggage for freebies such as books from the Developer Zone, swag from the Expo, or prizes you may win.  Although, you might have trouble finding room for a Mustang or Tesla.
  6. Umbrella.  In general, be prepared for the weather.  Last year it rained a bit, but having an Umbrella helped getting from point A to point B.
  7. A mobile battery pack for your smart phone.  If you're anything like me, your phone will drain quickly.  Here's a battery pack that works well for my iPhone: http://www.amazon.com/dp/B00BZD6QCW
  8. A camera.  I'm a photography fan, so traveling without my Nikon is not an option.  You'll find lots of photographic opportunities around town or in the various Dreamforce venues.  Fisherman's Wharf is a short walk down Market Street.  Or you may be lucky enough to catch a ride from a Marine Biologist down to the Golden Gate bridge, who knows!
  9. Maybe you're a Google Glass user or a Fitbit fanatic or a Pebble Pedestrian.  Either way, bring your wearables along to Dreamforce for an enhanced experience.
  10. Bring a plan.  Odds are your plan will change during the conference.  However, having a general idea of what you want to get out of Dreamforce goes a long way.  
Still interested in attending Dreamforce 2014?  It's fast approaching (http://isitdreamforceyet.com/), so head on over to the following link for more info and start pestering your boss today: http://bit.ly/df14infblog

Monday, April 15, 2013

Lions, Tigers, and Lead Conversion, Oh My!

For something as simple as clicking a button on a Lead to flip its status from "Open" to "Qualified", there sure are a lot of operations and complexity happening behind the scenes.  Converting a lead takes a lot of forethought.  For instance it must abide by Business processes associated with its Record Type. Fields must be mapped correctly for them to be carried over to the related Opportunity, Account, and Contact records.

What if you want to step outside the box with Lead conversion?  What if you want to implement your own lead button with a custom Visualforce UI?  What if you want to implement mass lead conversion through an integration or middleware?  The latter is where lead conversion gets really tricky, and that's the topic of this blog post.

I'm working on a rather large scale integration, which synchronizes both standard and custom objects from a source Salesforce org to another target Salesforce org.  The integration itself is a bit too complex to go with a standard Salesforce to Salesforce implementation.  One of the objects is Leads, and hence Converted Leads as well.

After digging into Lead conversion and how to integrate converted leads, I felt like Frodo getting caught by the spider



A few things I needed to consider were:

  • How do I convert leads using an external id?
  • How do I talk back to the source record, after a successful conversion, and prevent that record from being synchronized again?
  • Can this be accomplished with a successful web service call or two?
After toying around with a simple web service, it was quickly apparent that a single call really wouldn't suffice.  The leads in the integration are basically under a single account, and once you try and convert leads under a single account using logic similar to below, you get a "Duplicate Id in list exception".  Here's my post on Stackexchange asking for help on this issue: http://salesforce.stackexchange.com/questions/10520/best-approach-for-integrating-converted-leadswith-external-ids/10531?noredirect=1#10531

 List leadConversions = new List();
        for(Lead l : leadsToConvert){
            Database.LeadConvert lc = new Database.LeadConvert();
            if(l.Contact__r != null){
                lc.setContactId(l.Contact__r.Id);
                lc.setAccountId(l.Contact__r.AccountId);
            }
            lc.setLeadId(l.Id);
            lc.setDoNotCreateOpportunity(true);
            lc.setConvertedStatus(status);
            leadConversions.add(lc);              
            leadExternalIds.add(l.External_Id__c);
        }
     
        List lcr = new List();
        Integer i=0;
        for(Database.LeadConvertResult r : Database.convertLead(leadConversions,false)){
            lcr.add(
                new LeadConversionResult(
                    r.isSuccess(),
                    r.getErrors().isEmpty() ? null : r.getErrors().get(0).getMessage(),
                    leadExternalIds.get(i++)
                )
            );
        }

After realizing this wouldn't work, it was time for a completely different approach.  Breaking out SoapUI (http://www.soapui.org/), a handy plugin for testing web service calls, and your best friend for testing out the Salesforce.com Enterprise and Partner WSDLs,  it was apparent that the api convertLead operation behaves differently than the apex version.  The convertLead operation does allow multiple leads under the same account!  Continuing the LOTR theme, the convertLead operation was my Samwise Gamgee to my integration Shelob (http://en.wikipedia.org/wiki/Shelob)

Taking the above into consideration I came up with the following solution:

  1. When the source lead is converted, the external id is loaded into a custom object.  This allows the control successes and failures in the integration since leads cannot be updated after they are converted.
  2. The integration queries the converted object queue above and passes the external ids to a webservice on the target org to retrieve their Salesforce Ids.  Since the external ids are Unique, and Case sensitive, it's a straight 1-1 mapping.
  3. The ids are transformed into a convertLead request, which is a operation available on the partner wsdl.
  4. Any successes are passed back to a third webservice call, which deletes successful conversions from the custom object "queue".  Errors are left in the queue for re-processing
The flow of the operation looks something like this:


And there you have it, a solution for integrating converted leads.



Wednesday, February 13, 2013

Managed Package Unknown Server Errors (Gacks)

Creating a Salesforce managed package and get a non-descript "Salesforce has encountered an Unknown error "8675309" code?  These are called gacks in Salesforce land.  The only way to decode these errors is to contact Salesforce support, or someone at Salesforce who can look up the gack for you.

Through a bit of trial and error, here are the reasons I've encountered gacks while uploading packages

  1. Record Types or Business Processes have the same name (even though they are across different objects)  
    1. The resolution for this is simple (hopefully) and involves renaming the record type or business process to be distinct, such as RecordTypeName_ObjectName
  2. Invalidated class.  
    1. The result of perhaps only deploying a subset of classes to the packaging org.  I deployed a change to a VF controller, but removed a method its test class was dependent on.  After fixing the issue, the package was successfully uploaded.
  3. Permission Sets
    1. Permission sets containing CRUD permissions on Standard objects fail with "Unknown error".  This is because Permission sets cannot by design update Contacts, Leads, Accounts, Opportunities, and other standard objects.  The fix for this issue is to modify the permission set to uncheck all permissions on standard objects, and update them manually when installed.
If you have any other gacks and resolutions to them you've come across, feel free to comment below, and I will update the list above.

Tuesday, November 20, 2012

POSTing sensitive data over VisualForce

The Problem

My current project has a requirement for passing credentials from SFDC to an external site for auto-logging in users.  The requirement is a bit different from SSO, as these are Sales support representatives needing to log in to their customer's orgs for troubleshooting purposes.  The credentials are inherently sensitive, since they are username and passwords.

The current legacy system simply posts the credentials to a Cold Fusion form over HTTPS.  To mimmick this functionality, making it slightly more secure I implemented the following:
  The client's integration into SFDC stores the username / password data in encrypted fields, only allowing the System Admin to view the password data.  Secondly, the auto login function does its best to obscure the private information.  Furthermore, the auto login must be an HTTP POST to a form, rather than an HTTP GET.

Posting from VisualForce

POSTing from Visualforce is a bit tricky.  There's no real good way of going about it.  I've gotten comments on twitter (@dancinllama, by the way) regarding using the action parameter to do a HTTP callout on load.  However, the VF action also has to redirect to the page keeping the user logged in.  When I attempted this route, the browser never maintained the session.  Perhaps I was doing something wrong here, but I decided to go with a different solution.

In order to POST from Visualforce, I created a simple form with a username and password field.  The form was a straight HTML form, not utilizing the standard VF component.  On page load, JavaScript submits the form (to an HTTPS URL) and auto-logins the user.

Security through Obfuscation

The form itself was simple, but lead to a potential security flaw:  What if a "hacker" viewed the HTML source?  Even though the form input utilizes type="password" for masking in the UI, any schmuck can view the source and see the password in plain text.  Ruh-roh.  The solution was to utilize @RemoteAction call to populate the password value before the form was submitted.

The Code

Below is the simple @RemoteAction method.  Since the method is static, I had to pass in three variables to perform a dynamic query for retrieving the password on the fly.


  @RemoteAction
  public static String getPass(String field, String apiName, String recordId){
    String ans = null;
    try{
      sObject sobj = Database.query('Select ' + field + ' From ' + apiName + ' Where Id=:recordId');
      ans = (String)sobj.get(field);
    }catch(Exception e){}
    return ans;
  }

The remote action is called on page load from the VisualForce page using javascript wizardry, which passes in the object api name, the field api name, and the id of the record to query.



<form method="post" id="uform" name="uform" action="{!url}">  <input type="text" name="username" value="{!username}" />  <input type="password" name="password" value="" />  <input type="submit" value="Submit" /></form>



<script type="text/javascript"> function getPass() {
   Visualforce.remoting.Manager.invokeAction(
     '{!$RemoteAction.MyClass.getPass}',        '{!passwordFieldName}'        '{!objectApiName}'        '{!recordId}',        function(result, event){
          if(event.status){
            document.getElementById('pass').value=result;
            document.uform.submit();
          }
        },
        {escape: true}
    );
}
if(window.attachEvent){
    window.attachEvent("onload",getPass);
}else{    window.addEventListener("load",getPass, false);
}
</script>


Although it's a bit clumodgeony, it gets the job done.  The end result is the user is redirected to "url" and if they have valid credentials, are logged into the external system.  If you have any questions, comments, or critiques, please leave them below or ping me on twitter (@dancinllama).








Thursday, May 17, 2012

Overriding Approval Button Label

I had a recent need for override the label of the 'Submit for Approval' button, which is enabled by creating an approval process on an object out of the box in Salesforce.  Unfortunately, since the Submit for Approval is sort of generic across different objects, there is no way of overriding the label through Setup->Customize->Tab Names and Labels.

The solution is to implement a two line VF page and hook it up to it's own button, complete with the new label.  The VF page still uses standard out of the box functionality, and no apex was used nor harmed during this customization.  

The trick is to utilize the $Action global variable.  If you take a look at the Name of the Submit For Approval button on the page layout, you should find the name of the button/action is "Submit".  Going forward with this, I created the following simple Visualforce page:

<apex:page standardController="Case" action="{!URLFOR($Action.Case.Submit,case.Id)}">
apex:page>

Note that utilizing the action parameter is considered a CSR security risk and will be flagged if you depend on packaging up the Visualforce page.

After the Visuaforce page is created, the next step is to create a custom detail page button, opening the page in existing window with sidebar.  Set the label on the button to the text you desire.  Finally, modify the page layout(s) and replace the 'Submit for Approval' button with your custom VF button.

There you have it, an easy-peasy way to "override the label" using (mostly) out-of-the-box functionality.

Friday, January 6, 2012

Adding a default value for Campaign Standard Field

Scenario: Without needing to enter the Campaign Name field on the edit Campaign screen, have a trigger define the Campaign Name field based on a formula like criteria.


Problem:  The Name field is required on the Campaign, and saving the page layout fires a field validation rule before the before update trigger runs.  Furthermore, there is no option to provide a default value for the Name field unlike custom text fields.


Solution: Feed a dummy data value into the Campaign name through a custom Visualforce solution.  The solution involves overriding the New button on the Campaign and directing the user to the Campaign edit page with the Campaign name pre-populated, allowing the campaign to save and fire the trigger.


Step 1) Create a Controller extension to prepopulate the Campaign Name:


Apex controller extension (CampaignExtension.cls):
public with sharing class CampaignExtension {

  public CampaignExtension(ApexPages.StandardController stdController) { 
  }
  
  public PageReference gotoUrl(){
    PageReference pageRef = new PageReference('/701/e');
    Map params = pageRef.getParameters();
    params.put('nooverride','1');
    params.put('RecordType',recordType);
    //See notes below
    params.put('cpn1','Campaign Name');
    return pageRef;
  }
}



** Notes:  
The 'cpn1' parameter is related to whichever field to default.
Viewing the HTML source of the Campaign edit screen reveals that the HTML id of the Name field is 'cpn1', hence the cpn1 parameter for the Campaign Name field.

Step 2) Create a VF page:


<apex:page standardController="Campaign" 
  extensions="CampaignExtension" 
  action="{!gotoUrl}" />

Step 3) Override standard new button for Campaign:
  1. Setup->Customize->Campaigns->Buttons and Links
  2. Click Edit next the standard New button
  3. Select the Visualforce Page radio button and select the Visualforce page from Step 2 above.
  4. Validate that "Skip Record Type Selection Page" is unchecked. 
  5. Save the override properties
Wa-la, you should have a mechanism to set the default value for a required standard field on a standard object.






Tuesday, August 16, 2011

Convert Credit Card Exp date to YYYY-MM-DD

Had a recent requirement to convert a credit card expiration date from MMYY to YYYY-MM-DD so that it could be sorted upon in Salesforce.  Fortunately, I only had to modify the view in Oracle to the following:

select
    DECODE(
      NVL(myColumn,'N/A'),
      'N/A',
      'N/A',
      to_char(last_day(to_date(myColumn,'MMYY')),'YYYY-MM-DD')
    )
  from myTable