Stat Tracker

Thursday, August 2, 2012

I'll be presenting at Dreamforce 2012!

I'm happy to announce that I will once again be presenting at Dreamforce! This year I will be presenting on NFC and the Force.com Mobile SDK. I'll be speaking about a simple Android Hybrid Application I wrote that uses NFC, PhoneGap, PhoneGap Plugins, and the Force.com REST API to upsert vCard encoded Tags into Salesforce.com. Attendees will leave my session with all the knowledge they will need to get started on their own mobile applications with NFC!

Dreamforce is an awesome event. Mind blowing. I'm excited to be speaking again and look forward to seeing everyone there. I will be in the Developer Zone a good portion of time, so if your at Dreamforce tweet me (@corycowgill) and we can meetup for coffee or chat about Force.com, Mobile Development, or Wealth Management \ Private Equity SFDC implementation best practices!

See you in San Francisco in September!


Thursday, June 28, 2012

Activating Touch.Salesforce.com

You can get Touch.Salesforce.com activated in your orgs by sending a request via the Help menu in Salesforce. Simple send a feature activation case request through the self service portal and Salesforce will enable it.

I've been playing around with it and its pretty slick. As with most people, I'm chomping at the bit for the edit functionality, as well as the offline functionality. Currently in the public beta you can only add Tasks and Chatter Posts. Hoping when they go GA out of Beta that it will be enabled.

One thing to note is you must have Chatter enabled. Sorry Chatter haters, but if you want to roll with touch you'll need to enable it and embrace the future. ;)

Monday, March 26, 2012

Simple Bulk Emails with Amazon Email Service and Force.com from Sean Devine

So last week we had our monthly Chicago Force.com Developer group meetup. This session had a very cool presentation by Sean Devine on a how to integrate Force.com with Amazon Email Services. This allows you to rapidly build custom bulk email processes in Force.com. And whats even cooler is that he has made the source publicly available to everyone on Git Hub. Check it out here: https://github.com/seandevine/apexamazonemail.

While Sean performed the deep dive of the code during his presentation, I found a nugget of code I thought was particularly interesting. Sean used the JSON class and its serialize / desalinize methods to get around some interesting limitations. He uses the JSON class to serialize some data in his apex class and then he stores this as serialized data as an Attachment on the record. Then when needed he serializes the data from the attachment and processes it.

This is pretty interesting. For this example he used this workaround to get around the character limit in String fields on the object. Very creative and flexible solution to a problem in SFDC. For example, instead of creating 10 long text fields in SFDC on a record, you could use this process and not consume any data.

All in all, a very interesting developer meetup and  some very interesting source code!

Sunday, February 26, 2012

Generating a PDF in an Apex Trigger

There are a number of ways you can generate PDF documents on Force.com. The easiest way is to simply use the 'RenderAs' attribute on a Visualforce Page. You can also generate quote PDF easily with templates out of the box. While these options are great and work in a number of situations, they will not work within the context of a trigger.

There are many times during the life of a record where we may need to automatically generate a PDF document and attach it to the record. To do this we can use the Blob object and its method toPDF(String content). I was actually surprised by how little information there is available on this method. There are lots of blogs and articles about rendering a Visualforce page as a PDF, but this method hardly gets any press!

The Blob.toPDF() method takes in the body of the PDF document as a String. And guess what! It can take in HTML content and render the PDF according to the HTML you specify. Pretty awesome! Let's take a look at this in action. I've created a simple Apex Trigger on my Account object which will generate a simple PDF of all the information on the Account object.

Here's the Account Trigger:

trigger AccountTrigger on Account (after delete, after insert, after undelete,
after update, before delete, before insert, before update)
{
    if(trigger.isAfter)
    {
        if(trigger.isInsert)
        {
            if(trigger.new.size() == 1) // Lets only do this if trigger size is 1
            {
                AccountPDFGenerator.generateAccountPDF(trigger.new[0]);
            }
        }else if(trigger.isUpdate)
        {
            if(trigger.new.size() == 1) // Lets only do this if trigger size is 1
            {
                AccountPDFGenerator.generateAccountPDF(trigger.new[0]);
            }
        }
    }
}


And here is the PDF Apex class which will use the Blob.toPDF() method to generate the PDF content and attach it to the Account record as an Attachment. Notice that ths Blob.toPDF() takes in a String as the input, and that the String content can be formatted with HTML.

public with sharing class AccountPDFGenerator
{
   
    public static final String FORM_HTML_START = '<HTML><BODY>';
    public static final String FORM_HTML_END = '</BODY></HTML>';

    public static void generateAccountPDF(Account account)
    {
        String pdfContent = '' + FORM_HTML_START;
        try
        {
            pdfContent = '' + FORM_HTML_START;
            pdfContent = pdfContent + '<H2>Account Information in PDF</H2>';
           
            //Dynamically grab all the fields to store in the PDF
            Map<String, Schema.SObjectType> sobjectSchemaMap = Schema.getGlobalDescribe();
            Schema.DescribeSObjectResult objDescribe = sobjectSchemaMap.get('Account').getDescribe();
            Map<String, Schema.SObjectField> fieldMap = objDescribe.fields.getMap();
           
            //Append each Field to the PDF
            for(Schema.SObjectField fieldDef : fieldMap.values())
            {
                Schema.Describefieldresult fieldDescResult = fieldDef.getDescribe();
                String name = fieldDescResult.getName();
                pdfContent = pdfContent + '<P>' + name + ': ' + account.get(name) + '</P>';
            }
            pdfContent = pdfContent + FORM_HTML_END;
        }catch(Exception e)
        {
            pdfContent = '' + FORM_HTML_START;
            pdfContent = pdfContent + '<P>THERE WAS AN ERROR GENERATING PDF: ' + e.getMessage() + '</P>';
            pdfContent = pdfContent + FORM_HTML_END;
        }
        attachPDF(account,pdfContent);
    }
   
    public static void attachPDF(Account account, String pdfContent)
    {
        try
        {
            Attachment attachmentPDF = new Attachment();
            attachmentPDF.parentId = account.Id;
            attachmentPDF.Name = account.Name + '.pdf';
            attachmentPDF.body = Blob.toPDF(pdfContent); //This creates the PDF content
            insert attachmentPDF;
        }catch(Exception e)
        {
            account.addError(e.getMessage());
        }
    }
   
}


And here is the PDF that was generated in the Apex Trigger and attached to the Account record.


Pretty awesome, right? Since you can't get a Visualforce page's content in a Apex Trigger this method is a lifesaver when you need to automatically generate simple PDF documents via Triggers.

Let me know your thoughts and if you have any other feedback on this method!

Tuesday, February 7, 2012

Fun Times with the Force.com Metadata API

So this past weekend I spent a few hours playing around with the Force.com Metadata API. Currently Force.com is running a developer contest to drive folks to do some cool stuff with it. In my everyday Force.com adventures, this is not a feature I get to play with alot. Typically I use the Force.com IDE to do small deploys, or the Force.com Migration Toolkit to run more complex deployments (both of which use this API under the hood).

However, there are some cool things you can do with the API. You can retrieve and update all your objects, apex code, triggers, visualforce, static resources, etc via the API. Meaning you can build tools that make deployments easy. You could even build an application to take snapshots of all your Metadata on a Nightly Basis for backing up and creating versions of objects. There are all sorts of cool stuff you can do!

For example, my simple java application reads a local MySQL database schema information and uploads it to Force.com. Here's a screenshot of the beta or work in progress if you will:

You can also take a look at this demo on YouTube here: http://www.youtube.com/watch?v=OTQcayubCEA&context=C3378280ADOEgsToPDskKXJUZxact1OiFZosSoQ_52

Hopefully I'll get this sucker finished up soon. Once I do I'll post the code to GitHub along with a follow up article about it about the technical details. But if you're reading this, your probably interested in the API and what you can do. And really the sky's the limit!

I'd like to also give a shout out to Cloud Converter from Model Metrics while I'm talking about this. This application has been around a while and is available on the App Exchange, and its great for building data dictionaries for clients. Its Open Source too, so you can take a peak of the code on Google Code. http://developer.force.com/projectpage?id=a0630000003LD3HAAW

Thursday, January 12, 2012

Executing SOSL in Unit Tests

SOSL is a very powerful query method available in the Force.com platform. It allows you to query across all objects for matching text and return results in a List<List<Sobject>> result set. Very cool and very powerful.

As with any Apex code you'll need to write some unit tests to ensure code coverage and that the queries behave as designed before deploying to production. The funny thing is if you just dive right into writing some SOSL queries in Apex and try to test it, you may notice that you get 0 results back for your data. What gives? You know the code is correct. You know the code is working in your sandbox via testing it in a Visualforce page. What the heck?

You're not having a heart attack There is no issue, you just need to know how to setup your unit test properly! Because Salesforce is a multi-tenant architecture, and queries are shared across the system, they don't allow you to run the full SOSL query in your unit test since SOSL can go across all objects in the org. Fear not though, you can still test your code and the query!

You need to use the Test.setFixedSearchResults() method inside your unit test to set a subset of available data to the SOSL query. This method will open up these records so that they can be searched on by the SOSL in your unit test.

For example, lets say I have an Apex class which has a method called "search()" which executes the SOSL like so:


List<List<SObject>> searchList = [FIND :param IN ALL FIELDS RETURNING Account(Id,Name), Contact(Id,Name), Opportunity(Id,Name)];

If I setup my Unit Test as follows, it will query on the data properly and return 3 results back (1 result for each object type):

        Account a = UnitTestFactory.buildTestAccount();
        insert a;
       
        Contact c = UnitTestFactory.buildTestContact();
        insert c;
       
        Opportunity o = UnitTestFactory.buildTestOpportunity();
        insert o;
       
        Id [] fixedSearchResults= new Id[3];
        fixedSearchResults[0] = a.Id;
        fixedSearchResults[1] = c.Id;
        fixedSearchResults[2] = o.Id;
        //Required so SOSL will fire in Unit Tests Properly
        Test.setFixedSearchResults(fixedSearchResults);
       
        CustomSearchController rs = new CustomSearchController();
        rs.searchParam = 'Unit';
       
        test.startTest();
        rs.search();
        test.stopTest();
       
        system.assertEquals(3,rs.results.size());



This Unit Test code will execute and give me the 3 results I am expecting. That's it. You can now test your SOSL queries properly and ensure that they work! Easy enough!

For more information you can checkout the documenation on Force.com: http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_testing_SOSL.htm