Stat Tracker

Sunday, November 23, 2014

A Simple PDF Form Service with the Heroku Deploy Button

I recently took the sample PDF Forms Service I built for Dreamforce 2014 and have made it available via GitHub and the Heroku Deploy button.

 The Heroku Deploy button is pretty slick. It will automatically provision an App on Heroku for you with a click of the button! So know you can not only look at my source code on GitHub, but you can also instantly spin up the Form Service Sample App on your own Heroku account! With just a click of a button!

Here is the Simple REST PDF Form Service Heroku Deploy Button! Go forth and build!

Deploy 

If you have question on how the actual Form Service works check out my session from
Dreamforce 2014 here:




Friday, August 29, 2014

Apex Unit Tests - 4 Random Successful Implementation Tips

Any experienced Salesforce.com developer will tell you that Apex Unit Tests are critical to the success of any Salesforce.com implementation. This is especially critical in complex Salesforce.com environments where we have multiple lines of business using the system. Imagine if you have 10 completely different business units using the same objects with different record types, workflow rules, visualforce pages, batch processes, triggers, etc.

Here are some random thoughts on how you can get the most of out your Unit Tests. These have helped me in the past.



  1. Build is not complete without Apex Unit Tests
  • Unit tests should be completed as functional code is delivered. A story or task should not be considered complete until the accompanying unit tests are built. As yourself "Can I deploy this functionality to production successfully? Does it have code coverage?". SFDC will stop you without sufficient code coverage.
  1. Apex Unit Tests without system asserts are worthless for support and maintenance
  • Unit tests need to have system.assert() to be of any practical value. If a unit test executes solely for the purpose of code coverage than it is not doing its true job, which is to guarantee system behavior. The developer who changes this code may think everything is fine because your unit test did not fail, but his change actually broke the runtime code. 
  1. Deployment between sandboxes must pass all unit tests
  • The Salesforce platform only requires unit test coverage for production deployment. If you bake this into your deployment processes you will ensure success in a large enterprise SDLC that has multiple environments.
  1. If you have complex workflows, validation rule logic or Roll-Up Summary Fields (RUS) build some Apex Unit Tests to validate it even if there is not Apex Code.
  • You can use unit tests to validate your "clicks not code" functionality if it is significantly complex. For example if you have RUS fields that have complex filters and get used across several objects for logic. Putting Apex Unit tests in place can help ensure future changes to these items will not corrupt your data.








Wednesday, June 18, 2014

Converting Base 10 to Base 32 (Or Any Base) in Apex

Recently I had the need to convert a base 10 number into a base 32 number in Salesforce. For my project I had a need to integrate SFDC with a legacy AS400 database to store records (contract records).

The Contract Number Requirements

The legacy database had an existing field that had a length of 9 for the contract number, with the first 4 characters a standard prefix, and each number which had to be unique.

For example the contract number looked like "POLY48GH3" where POLY was the prefix, and 48GH3 was the number. If you've ever worked with legacy AS400 databases you know they love to limit the amount of characters in a field! Furthermore we couldn't use the characters W,X,Y, or Z in the field and could only use 0-1, and A-V as uppercase only.

Fun requirements right!

The Solution

We quickly identified that if we used base 32 numbers we could get the most unique numbers out of the 5 available characters per our requirements (32^5=33554432 available numbers).  In Java you can achieve easily this via the standard class/method Integer.toString(integerVal,radix) where you can specify your radix (base). There is no corresponding method in Apex!

You can use EncodingUtils in apex to do Base64 and even Base128, but if you need to tailor your base you are out of luck. To do custom base conversions you need to write your own method to accomplish this, which I have provided below. You can tweak this method to create different base conversions as necessary. Also you could probably write this in a Formula Field with some additional work if you didn't want to do it in Apex.

I hope this helps folks. A big shoutout to the computer science blog from Erik Oosteral which outlines this logic for those who are interested.

-------------------
public static String generateBase32ContractNumber(Decimal decimalValue, Integer contractNumberLength)
{
try
{
Integer inputBase = 10;
Integer outputBase = 32;
String outputValue = ''
String numericBaseData = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
Integer x;
Integer maxBase = NumericBaseData.length();
if(DecimalValue == 0)
{
return '0';
}
else
{
while(decimalValue > 0)
{
      X = (Integer)(((DecimalValue/outputBase) - (Integer)(DecimalValue/OutputBase))* OutputBase + 1.5);
      System.debug('x' + x);
      OutputValue = NumericBaseData.subString(X - 1,X)+OutputValue;
      DecimalValue = Integer.valueOf(DecimalValue/OutputBase);
}
}
//We want to ensure all characters have a value. So if the Base 32 number is 10, and our Contract Number lenght is 5, we want to make the output String "00010"
while(OutputValue.length() < contractNumberLength)
{
OutputValue = '0' + OutputValue;
}
return OutputValue;
}catch(Exception e)
{
throw new Custom_Exception('There was an error converting the base values:' + e.getMessage());
}

}

Saturday, March 22, 2014

Instrument Your Apex Code : DIY Performance Metrics on Force.com

Performance Monitoring on Force.com

There are many instances when you develop on Force.com where you will have to gather performance metrics on your codebase. You may want to log how long a HTTP Callout in Apex code takes, or how long an Apex Trigger runs with complex sharing rules. Gathering these metrics is especially important on the Force.com platform due to Governor Limits and the impact of having long running apex transactions. Unfortunately the native logs on SFDC do not allow you to log more than 20 transactions per user per transaction batch. Also these logs are not easily reportable.

This can present a clear challenge to developers but it can be easily remedied. In this blog post I will show you how you can roll your own Apex performance monitoring framework. You will be able to log performance on your Apex code, easily toggle the monitoring on or off without a deployment of code, and run reports and dashboards on your metric data. All this natively on the Force.com platform! No additional tools or vendor products need apply!

Step 1: Create a Custom Object For Performance Logs

Our first step will be to create a custom object to hold our performance logs. This object will have only a few fields. 

Name - An Autonumber for the transaction in the format of PERF-{00000001}
Apex Class - A string holding the name of the Apex Class for the transaction
Apex Method - A string holding the name of the Apex Method for the transaction
Time in Milliseconds - A number holding the transaction time in milliseconds
Time in Seconds - A formula field based on Time in Milliseconds for showing time in seconds
Notes - Any developer notes you want to add for details about the transaction (Record Ids, etc)
Created By - The user who was executing the code

The total object looks like this. Note: Make sure to "Enable Reports" so we can write native reports!


Bonus: Create a Custom Object Tab and expose the object in your UI if you want.

Step 2: Create a Custom Setting to Toggle Logs On/Off

Now that we have our custom object we need to create a Custom Setting that will allow us to toggle the logs on or off without changing any code. Custom Settings were specifically built to set Application Wide settings like this and is the perfect use case for Custom Settings. We are going to create a Custom Setting called "Global Setting" this is Setting Type "List". 

We are only going to create one custom field called "Log Transactions". 

Once we are done your Custom Setting will look like this:

Step 3: Create our Apex Monitoring Framework Class

Now that we have our data model complete we can build out Apex framework class for monitoring transactions. The class itself is very simple and really only does 3 things: 
1. It automatically logs the transaction time by calculating the time in milliseconds.
2. It reads the Custom Setting to see if logging is set to true.
3. It will insert a log record via DML insert on the System Performance Log.

Here is the complete Apex Class:

public without sharing class SystemPerformanceDAO
{
 public static void insertPerformanceLog(PerformanceTransaction logRec)
  {
    logRec.endTimeMilliseconds = DateTime.Now().getTime();
    Global_Setting__c globalSetting = Global_Setting__c.getInstance('Global_Setting');
    if(globalSetting != null && globalSetting.Log_Transactions__c == true)
    { 
      insert new System_Performance_Log__c(Apex_Class__c = logRec.apexClassName, Apex_Method__c = logRec.apexMethodName, Notes__c = logRec.notes, Time_in_Milliseconds__c = (logRec.endTimeMilliseconds - logRec.startTimeMilliseconds));
    }
  }

  //Class used to maintain the State of the Transaction for use by Apex Classes.
  public class PerformanceTransaction
  {
    public long startTimeMilliseconds {get;set;}
    public long endTimeMilliseconds {get;set;}
    public String apexClassName {get;set;}
    public String apexMethodName {get;set;}
    public String notes {get;set;}
    
    public PerformanceTransaction(String apexClass, String apexMethod, String innotes)
    {
      apexClassName = apexClass;
      apexMethodName = apexMethod;
      notes = innotes;
      startTimeMilliseconds = DateTime.Now().getTime();
      endTimeMilliseconds = 0;
    }
  }
}

Step 4: Instrument our Apex Classes with the Framework

Now that we have our data model and Apex framework classes we can start to instrument our Apex classes and methods. To do this we only add two lines of code to the methods we want to instrument. 

The first line of our Apex methods should invoke the constructor in our framework for a transaction log like this:

SystemPerformanceDAO.PerformanceTransaction performanceLog = new SystemPerformanceDAO.PerformanceTransaction('AccountController','refreshContacts','Account Used: ' + acct.Id);

And the last line of our method should simply invoke our Apex class to log the metric like this:

SystemPerformanceDAO.insertPerformanceLog(performanceLog); 

This makes it very easy for us to add instrumentation to our Apex classes with minimal code. And we don't have to change the code since the framework automatically does that for us by checking the custom setting.

A complete example may something like this:

public with sharing class AccountController
{
    public List<ContactListWrapper> acctContacts {get;set;}
    public Account acct {get;set;}

    public AccountController(ApexPages.StandardController std)
    {
        acct = (Account) std.getRecord();
        acctContacts = new List<ContactListWrapper>();
        List<Contact> contacts = [Select Id, Email, FirstName, LastName from Contact where AccountId =: acct.Id];
        for(Contact c : contacts)
        {
            acctContacts.add(new ContactListWrapper(c));
        }
    }


    public ApexPages.PageReference refreshContacts()
    {
        SystemPerformanceDAO.PerformanceTransaction performanceLog = new SystemPerformanceDAO.PerformanceTransaction('AccountController','refreshContacts','Account Used: ' + acct.Id);
        List<Contact> contacts = [Select Id, Email, FirstName, LastName from Contact where AccountId =: acct.Id];
        for(Contact c : contacts)
        {
            acctContacts.add(new ContactListWrapper(c));
        }
        SystemPerformanceDAO.insertPerformanceLog(performanceLog);       
        return null;
    }
    
    public ApexPages.PageReference saveContactUpdates()
    {
        SystemPerformanceDAO.PerformanceTransaction performanceLog = new SystemPerformanceDAO.PerformanceTransaction('AccountController','saveContactUpdates','Account Used: ' + acct.Id);
        List<Contact> contactUpdates = new List<Contact>();
        for(ContactListWrapper clw : acctContacts)
        {
            if(clw.isSelected)
            {
                contactUpdates.add(clw.acctContact);
            }
        }
        if(contactUpdates.size() > 0)
        {
            upsert contactUpdates;
        }
        SystemPerformanceDAO.insertPerformanceLog(performanceLog);
        return null;
    }

    public class ContactListWrapper
    {
        public boolean isSelected {get;set;}
        public Contact acctContact {get;set;}
        
        public ContactListWrapper(Contact c)
        {
            acctContact = c;
            isSelected = false;
        }
    }
}

Step 5: Instrument our Apex Classes with the Framework

Now that we have our classes instrumented we can use the native Force.com Analytics to build our reports. For this example I create a report to show the average, maximum, and minimum transaction times for each of my controller methods.



Conclusions and Caveats

As you can see in this example, it is fairly simple to roll your own instrumentation on Force.com for performance metrics. One of the caveats is that this approach will consume managed data on the platform. So you will need to monitor your logs data usage and periodically purge the records as needed if you don't have a lot of managed data. 

The other caveat is that this will not work for instrumenting Visualforce Apex controller constructor methods. Visualforce Apex controller constructors do not allow you to perform DML statements.

I hope you found this helpful. 

Sunday, January 19, 2014

Using Formula Fields to Translate Picklist Values into System Codes

When implementing multiple integrations with a Salesforce.com org it is a common use case to translate picklist values into system code values for legacy systems. For example, if you have a Quote object you may have a picklist called "Quote Payment Type" with valid values of "Cash", "Credit", or "Debit". These are the values that are displayed in Salesforce.com UI and the values persisted in the Quote_Payment_Type__c field on your Quote object.

However, sometimes we need to translate the picklist values into system codes for an integration. If we are integrating our Quote object with a payment system for example via a web service the legacy system may expect a system code instead of the string values displayed. In this case let's say our legacy system is a AS400 mainframe and expects short bytes for the values (Cash == C, Credit == CR, Debit == D). How should we do this?

We could do this in Apex Code and translate these values prior to making a HTTP Callout. However, that assumes that we will only integrate with this system via a HTTP Callout in Apex code. We wouldn't be translating this for Data Loader integrations, or other 3rd party tool integrations that may simply pull the SObject and pass it to the legacy system. Also if we build this translation in the Apex code layer, everytime we add a new translation or change an existing translation we would need to do a code deployment and update our unit test coverage. Ouch!

A much cleaner way to implement this is to use a Formula Field on the object.

In this case we create a new Formula Field called "Quote Type INT".

Formula Field Definition:

IF(ISPICKVAL(Contract_Type__c, 'Cash') , 'C', 
IF(ISPICKVAL(Contract_Type__c, 'Finance'), 'L', 
IF(ISPICKVAL(Contract_Type__c, 'Lease'), 'LE','NA')))

And now the translation is always done in the declaritive layer which is SFDC best practice. Here is what we get in our UI if you chose to display the system code value:



Its a simple pattern that every developer should have in their toolbox. Always remember to use "Clicks not Code" whenever possible to solve your development or integration needs. With this pattern if we add new translations I can simply update the Formula Field and Picklist values without doing a full code deployment!

One thing to consider: If you have hundreds of values you may exceed the Formula Field size. In that case you may need to use a Custom Setting or other mechanism (Static Resources, etc) to hold the translation values. But please don't hard code them!





Monday, December 16, 2013

Capturing Signatures with HTML5 Canvas in Salesforce 1 Mobile

Recently Salesforce.com released Salesforce 1, their latest mobile application. Salesforce 1 releases a number of new features that enable developers to create mobile applications. One person I spoke with recently at Dreamforce wanted to know how they could capture signatures in the mobile application. With HTML5 Canvas, Visualforce, and a little JavaScript, you can easily roll your own lightweight signature capture functionality in Salesforce 1.

Here is a brief demonstration video:


So I have included the entire source code below, but a few items about the tricky parts.

1. You will need to setup JavaScript event listeners on the canvas for touchstart, touchmove, and touchend. That is what the canvas will execute when you touch and drag your finger on it.

2. You will need to use JavaScript Remoting to ensure that you properly pass the Canvas content into your Apex Controller so that it can save it. The canvas can be converted into a Base64 String with the Canvase.toDataURI() method. That is how you get the bytes from the Canvas into an Attachment in Salesforce.com.

These are illustrated in the sample code.

And here is the source code for the VF and Apex. If you put these into a Visualforce Tab, and make it enabled for Salesforce 1 Mobile, then you easily reuse this sample code.

jQuery: http://code.jquery.com/jquery-2.1.1.min.js

jQuery Mobile Resources (Download Links)
Version 1.3.2: http://jquerymobile.com/resources/download/jquery.mobile-1.3.2.zip

Latest Version 1.4.4: http://jquerymobile.com/resources/download/jquery.mobile-1.4.4.zip

Source Code:

Visualforce Page Code:

<apex:page controller="AnyObjectSignatureController" showheader="false" sidebar="false" standardStylesheets="false">
<script>var $j = jQuery.noConflict();</script>
<apex:stylesheet value="{!URLFOR($Resource.jquerymobile,'/jquerymobile/jquery.mobile-1.3.2.min.css')}"/>
<apex:includeScript value="{!URLFOR($Resource.jquery)}"  />
<apex:includeScript value="{!URLFOR($Resource.jquerymobile,'/jquerymobile/jquery.mobile-1.3.2.min.js')}"/>

<div data-role="page" id="signatureCaptureHome"> 
<div data-role="content">
<input id="accountNameId" type="text" name="accountName"/>
<input type="button" name="findAccountBtn" onclick="findAccounts();" value="Find Accounts"/>
<h1 id="recordSigId">Record Signature:</h1>
<canvas id="signatureCanvas" height="200px" width="300px"/>
<input id="saveSigButton" type="button" name="SigCap" onclick="saveSignature();" value="Capture Signature"></input>
</div> 
</div> 
<div data-role="page" id="signatureCaptureHome"> 
<div data-role="content">
<input id="accountNameId" type="text" name="accountName"/>
<input type="button" name="findAccountBtn" onclick="findAccounts();" value="Find Accounts"/>
</div> 
</div> 

<script>

    var canvas;
    var context;
    var drawingUtil;
    var isDrawing = false;
    var accountId = '';

function DrawingUtil() 
{
    isDrawing = false;
    canvas.addEventListener("touchstart",start,false);
    canvas.addEventListener("touchmove",draw,false);
    canvas.addEventListener("touchend",stop,false);
    context.strokeStyle = "#FFF";  
}

//Start Event for Signature Captuare on HTML5 Canvas
function start(event) 
{
    isDrawing = true;
    canvas = document.getElementById("signatureCanvas");
    context = canvas.getContext("2d");    
    context.strokeStyle = "rgba(155,0,0,0.5)";      
    context.beginPath();
     context.moveTo(event.touches[0].pageX - canvas.getBoundingClientRect().left,event.touches[0].pageY - canvas.getBoundingClientRect().top);
}

//Event while someone is drawing to caputre the path while they draw....
function draw(event) {
    event.preventDefault();
    if(isDrawing) {     
        context.lineTo(event.touches[0].pageX - canvas.getBoundingClientRect().left,event.touches[0].pageY - canvas.getBoundingClientRect().top);
        context.stroke();
    }
}


//Event when someone stops drawing their signature line
function stop(event) {
    if(isDrawing) {
        context.stroke();
        context.closePath();
        isDrawing = false;
    }
}

canvas = document.getElementById("signatureCanvas");
context = canvas.getContext("2d");
drawingUtil = new DrawingUtil(canvas);

function saveSignature()
{
var strDataURI = canvas.toDataURL();
    // alert(strDataURI);
    strDataURI = strDataURI.replace(/^data:image\/(png|jpg);base64,/, "");
//alert(strDataURI);
AnyObjectSignatureController.saveSignature(strDataURI,accountId,processResult);
}

function processResult(result)
{
alert(JSON.stringify(result));
}

function findAccounts()
{
var nameValue = document.getElementById("accountNameId").value;
AnyObjectSignatureController.findAccounts(nameValue, processSearchResult);

function processSearchResult(result)
{
$j = jQuery.noConflict();
//$j("#accountList").html("");
$j.each(result, function(i, record) {accountId = record.Id; $j("#recordSigId").html("Record Signature: " + record.Name);});
$j("#recordSigId").trigger("update");
//$j("#accountList").trigger("update");
//alert(JSON.stringify(result));
}


</script>

</apex:page>

Apex Controller:
global with sharing class AnyObjectSignatureController 
{
public AnyObjectSignatureController()
{
}
@RemoteAction
global static List<Account> findAccounts(String name)
{
name = '%' + name + '%';
List<Account> accounts = [Select Id, Name from Account where Name like :name];
return accounts;
}
@RemoteAction
global static String saveSignature(String signatureBody, String parentId) 
{
try
{
system.debug('Record Id == ' + parentId);
system.debug(signatureBody);
Attachment a = new Attachment();
a.ParentId = parentId;
a.Body = EncodingUtil.base64Decode(signatureBody);
a.ContentType = 'image/png';
a.Name = 'Signature Capture.png';
insert a;
return '{success:true, attachId:' + a.Id + '}';
}catch(Exception e)
{
return JSON.serialize(e);
}
return null;
}

}

Sunday, October 13, 2013

Dreamforce 2013 Sessions - Lets Rock

Dreamforce is upon us! In just a few weeks San Francisco will turn into the mecca for cloud computing with almost 100,000 cloud devotees making the annual pilgrimage.  This will be my third year presenting at Dreamforce and I can honestly say each year the Developer Zone has gotten better and better. This year I will be presenting or contributing on four different sessions. And for the first time I'll be co-presenting a session with another person! I'm excited to be working with Tim McDonald on our administrator and developer session.

Come check out the sessions, contribute to the conversations on the chatter feeds, and get your brain ready for data downloads!

Case Study: Building a Mobile App for Field Services

Wednesday, November 20th: 4:00 PM - 4:30 PM
Moscone Center West, Mobile Theater

Description

The Salesforce Platform allows you to architect complete solutions for entire lines of business, whether it's desktop or mobile users. Join us as we focus on how users can build a fully featured mobile solution for Field Service engineers. 

By dissecting an HTML 5 Hybrid Application for the Service Cloud, you'll get exposure to building a complete mobile application using the jQuery Mobile for UI, Salesforce Mobile SDK for Security &amp; REST API Access, NFC Phonegap Plugin for Serial Number Scanning and Automatic Case Assignment, HTML5 Canvas for Signature Capture Camera Access for Case Documentation &amp; Attachemnt on the Case in Salesforce, and Chatter API for Social Feeds on Cases.
Speakers:
Cory CowgillThe Warranty Group

Apex Trigger Debugging: Solving the Hard Problems

Wednesday, November 20th: 11:45 AM - 12:30 PM
Moscone Center West, 2020
Full

Description

Apex Triggers can be your best friend or your worst enemy. When a trigger is firing properly your data is under control and remains sane, but when a trigger doesn't fire properly, your users can be faced with the frustration of exceptions when saving a record, or worse: incorrect data. Join us to learn tips and tricks on how to debug and solve the most complex issues, including: Ambiguous Field Validation, After Insert Activity Errors, and SOQL and Governor Limit Errors. You'll learn the origins of these kinds of advanced trigger issues and gain solutions for avoiding them.
Speakers:
Cory Cowgill

Clicks AND Code: A Dreamforce Session for Administrators AND Developers

Wednesday, November 20th: 9:00 AM - 9:50 AM
The Westin St. Francis San Francisco, California West
Full

Description

Administrators seem to have adopted the mantra of “Clicks not Code.” However, more often than not, the customization of the Salesforce Platform through the use of code provided by a developer is not only necessary, but required for a successful implementation. Join us as we present best practices for administrators to use when engaging their developer counterparts, while providing some tips and tricks for developers to quickly respond to the requests placed before them.
Speakers:
Cory CowgillWest Monroe Partners
Tim McDonaldNew Tangram, LLC

Force.com Careers: How Do I Get There From Here?

Thursday, November 21st: 11:00 AM - 11:45 AM
Moscone Center West, 2020

Description

Do you love developing on the Salesforce Platform, but wonder what the next steps are for your career? Join our panelists to hear about various career paths, including Consultant, Architect, Product Manager, and AppExchange Developer, to name a few. These experts will share the pros and cons of their careers and also the path to get there.
Speakers:
Carolina Ruiz MedinaFinancialForce.com
Cory CowgillWest Monroe Partners
Leah McGowen-Haresalesforce.com
Cheryl Porrosalesforce.com
Ayori Selassiesalesforce.com
Andy OgnenoffCloud Sherpas
Kevin O'HaraLevelEleven


Can't get into one of my sessions because its full? Don't worry, sessions, presentations and source code will be distributed to the general public after the sessions. Have a question for me? Hit me up in the Developer Zone during the conference. I usually camp out there either by the hackathon, theaters, or coffee station. Hit me up in dreamforce chatter or on twitter @corycowgill and I'm happy to discuss anything Force.com related.

Looking forward to another awesome year!