Apex

Jira Attachments: Getting an attachment from a Jira

by Patrick Connelly posted on June 02, 2017

I previously did a post on writing Jira Attachments from Salesforce, and the question has come up of how to write Jira Attachments into Salesforce. This is actually WAAAAY easier than it was to write attachments out. The way that the data is structured from the Jira, we can get a list of all the attachments and the link to it’s content directly from the Jira GET request. This makes for way fewer calls to get the actual content of the attachment.


Milestone Trigger Time Calculator

by Patrick Connelly posted on April 26, 2017

I recently stumbled upon a “new” feature in Salesforce that allows you to use an Apex class to calculate your milestone trigger time for entitlement processes. Given a new feature that I’m working on for our entitlement process, I thought to myself that this could be a good chance to play with it and see what I could do. If you’re not familiar with the entitlement process in Salesforce, take a chance to look over (or run through) my hands-on training for entitlements so that you’re familiar with the terminology and the concepts since I’ll be jumping right in.


List of objects for POST in Apex REST

by Patrick Connelly posted on November 29, 2016

A while ago, someone posted on the developer boards a question about how to bulk create tasks for contacts via REST. I thought it was an interesting enough problem to cover how to do it and how to format the data correctly to use it.

Prerequisite

Before we can bulk create tasks for a contact, we need to know how to identify those contacts. To do this, I create an unique external Id field called External_Id__c. As long as your contacts are uniquely identifiable then it doesn’t matter what field you use. For this example I have two contacts under different accounts “Andy Young” with an external Id of “ayoung” and “Edna Frank” with an external Id of “efrank”


Namespaced REST in Managed Packages

by Patrick Connelly posted on September 07, 2016

Recently I’ve been working more with managed packages and I knew that I’d be writing REST interfaces inside that package. However I had no clue how namespaced REST interfaces would be presented or how you accessed them. I was afraid that there could be conflicts. For example if the package exposed /lastcase and the customer’s org had /lastcase how would they play together. I’m very happy to announce that the folks at Salesfore are on the ball and the platform handles it wonderfully.


Visibility for Apex in Managed Packages

by Patrick Connelly posted on August 16, 2016

Now that I’m starting to spend time playing with packaging code for use I decided to dig into how access modifiers affect visibility of methods and classes inside of managed packages.

Visibility Access Modifiers

Before we get started, let’s review what options we have for defining visibility in Apex

private – Methods, classes and variables marked as private are only visible inside the same class. If you define something as private then it cannot be accessed from an external class

public – Things that are marked as public are available for use by anything in the same namespace.

global – Things marked as global are available for use by anything on the platform.

Typically, public and private are enough for most implementations since your code resides inside the same namespace. When writing code to be used by others from your managed package you’ll want to make it global.


Heatmap for Contact Locations

by Patrick Connelly posted on August 01, 2016

One of the cool new features in Summer ‘16 is the ability to take a built in (or custom) address and automatically get that addresses latitude and longitude with SOQL (Read More). So took this as an opportunity to learn some more about it as well as some other mapping technologies. So for this my goal was to be able to create a heatmap of all the contact’s location under an account and place this on the account page.


XML Parsing in Apex

by Patrick Connelly posted on July 14, 2016

Doing XML parsing in any language can be pretty tough. I wanted to share a quick how to for doing XML parsing in Apex based on a previous board post.

Let’s start with the data we’re trying parse

<?xml version="1.0"?>
<_CREDIT_SCORE for="Bob Dole">
  <_CREDIT_SCORE _CreditScore="668" _ReportingAgency="Experian" />
  <_CREDIT_SCORE _CreditScore="658" _ReportingAgency="TransUnion" />
  <_CREDIT_SCORE _CreditScore="660" _ReportingAgency="Equifax" />
</_CREDIT_SCORE>

For this data we want to pull out who the credit report is for and the credit data from the for field as well as from each of the _CREDIT_SCORE elements the agency and the score.


OAuth Flow for service users in Salesforce

by Patrick Connelly posted on July 05, 2016

When this article was originally written Named Credentials weren't really a thing (or at least not something I really knew about). Using that is going to be a better and more secure way to do this.

A very common use case for integrations with external systems is to have a service user that is authenticated and all subsequent interactions happen via that user. This flow is super easy when you can do username / password auth, but it becomes much harder when you’re only option is to use the oAuth flow.

Use Case

In a recent developer board post, a community user asked for help storing their credentials from the oAuth flow to box.com and then create a new folder whenever an account was created. The problem they were facing is that when you do the initial oAuth flow, you have to approve the use of the app and this requires human interaction. This is not something you can do inside of a trigger, so we’ll need to find another way to do it.


Parse JSON with Reserved Words

by Patrick Connelly posted on June 21, 2016

One of the great things about Salesforce when dealing with external webservices is being able to easily parse JSON into Apex classes. I’ve covered this in several previous posts. However a common problem is that the system you are integrating with is they may be using a variable name that is reserved. With the following data, we can see that there is a variable named “case” if we ant to parse this data into a Apex class we won’t be able to because case is a reserved name.

{
    "data": [
        {
            "case": "123456",
            "subject": "Test case"
        }, {
            "case": "789012",
            "subject": "Another case"
        }
    ]
}

Trailhead: Apex Specialist Superbadge

by Patrick Connelly posted on June 06, 2016

Salesforce has released a new section under Trailhead called Superbadges, and they’re pretty awesome.

Superbadges?

Superbadges.

So if you’re familiar with Trailhead Projects, Superbadges are very similar to these but instead of guiding you through the process, you are given a set of requirements and you are required to implement it. All of the badges have requirements that you must meet before you can even start them. This is nice because it encourages you to learn the content before diving in. This way, the challenge of the badge is just building on your existing skills instead of teaching you new ones. For the first release, there are four Superbadges that you can earn:


PDF Headers and Footers with Visualforce

by Patrick Connelly posted on April 04, 2016

Over the past couple of months, I’ve seen several posts on the Developer forums asking how to set PDF headers and footers with Visualforce. I decided to sit down and try my hand at it. If you have done the Battle Station app on Trailhead, you can try this out on your own sandbox! We will be generating a PDF invoice for the Battle Station app that includes a first page header image and a dynamically generated footer.


Rosetta Code: A call for help

by Patrick Connelly posted on March 27, 2016

If you’ve ever started to learn your second programming language, you know how important it is to have example of the new language to help you understand the syntax. In my opinion, once you’ve learned the concepts behind programming (loops, control statements, etc) it’s pretty much just learning the syntax to get started. That’s where the folks over at Rosetta Code come in, to make it easier to learn new languages.


Testing NOW in Apex

by Patrick Connelly posted on March 21, 2016

If you’ve ever written a trigger that stores Date.now(), then this scene from Spaceballs may seem very familiar. This is how I feel when testing now.

Testing now

  • Dark Helmet: What the hell am I looking at? When does this happen in the movie?
  • Colonel Sandurz: Now. You’re looking at now, sir. Everything that happens now, is happening now.
  • Dark Helmet: What happened to then?
  • Colonel Sandurz: We passed then.
  • Dark Helmet: When?
  • Colonel Sandurz: Just now. We’re at now now.
  • Dark Helmet: Go back to then.
  • Colonel Sandurz: When?
  • Dark Helmet: Now.
  • Colonel Sandurz: Now
  • Dark Helmet: Now.

The problem comes down to knowing when now is. Obviously, now is something that’s in constant flux and will change throughout your test. But there are ways to be able to know when now really is in your test.


Extending objects for JSON parsing

by Patrick Connelly posted on March 16, 2016

In a previous post, I talked about how to pull Runkeeper data into Salesforce. The key portion of this revolved around JSON parsing of the data into Apex classes. In this post I’ll talk about how to use Object Oriented structures to extend the classes previously written to support additional data.


Runkeeper data in Salesforce

by Patrick Connelly posted on March 01, 2016

Runkeeper and Salesforce

For the past couple of years I’ve dabbled in running and getting data from Runkeeper. I decided that I’d give it a try to have the entire process inside of Salesforce. This provided an interesting challenge for me, since it’s the first time I’ve setup the oAuth flow from Salesforce back to Salesforce. This post will likely be the first of a couple in this theme of pulling data from Runkeeper. The code included here is just a base for what can be done. I’ll be maintaining an updated version of the RunkeeperUtils class on my github, so make sure you check there for the most recent version of everything. So let’s go over how we can do this


Amazon S3: Attaching a File in Salesforce

by Patrick Connelly posted on February 16, 2016

Last week I covered how to send an attachment from Salesforce to Jira. This week we’ll cover how to attach a file from Salesforce into the Amazons S3 cloud. Unlike the Jira uploading, we will not be associating these files with a specific case, but instead will be uploading them to a generic bucket. This can be modified by changing how the filename is generated on line 8 of the code.


Jira: Attaching a File in Salesforce

by Patrick Connelly posted on February 09, 2016

I was recently challenged with the task of sending an attachment from Salesforce to Jira. Looking over the documentation, this doesn’t appear to be too hard. The toughest part is that Jira wants a multi-part form upload for the attachments and this can be a bit of a headache to do in Apex. Following this post as a guide for multi-part form upload, we can adapt it to the format that Jira expects.


apex:gaugeSeries and display report data

by Patrick Connelly posted on January 25, 2016

I recently helped out on a Developer Boards post about recreating a dashboard in Visualforce to create a home page component. This works great with analytics:reportChart assuming you are not using a gauge chart. However if you want to use a gauge chart then you’ll have to dive into the apex:gaugeSeries component and personally I found the documentation a bit lacking. So, let’s dive into how to create a gauge chart based on a summary report.


Strip extensions from company names

by Patrick Connelly posted on January 10, 2016

In a recent developer boards post, there was a person asking how to programmatically strip extensions from the end of company names. This seems like an interesting problem that can be solved with regular expressions with the data stored in a custom setting

Custom Setting

Custom Setting Definition


Salesforce1 Actions with Visualforce

by Patrick Connelly posted on January 03, 2016

Salesforce1 Actions can be very powerful. Most of the examples I have seen regarding Salesforce1 Actions have been around Global Actions that show up on the home page. I recently had the chance to play around with object specific actions and found that combined with Visualforce pages they can be very powerful.

Goal

The goal of this post is to create two quick actions for the Lead object. One that will reject a lead and one that will accept a lead.

Salesforce1 Goal

We will be doing this via a Visualforce page that has an onload action. This will be useful so that we can re-use this both for a standard page layout button as well as for our Salesforce1 Action


JSON Deserialization in Salesforce

by Patrick Connelly posted on November 30, 2015

I have been several posts recently on the Developer Boards around JSON deserialization and some weird and convoluted ways to convert it into something that is useful for Salesforce. Let’s talk about what I have found is the cleanest way to handle JSON deserialization.

JSON Payload

Let’s take a look at our JSON payload. I am taking the payload from the docsample Heroku app since it’s an easy way to get consistent data from a webservice.

{
  "invoiceList": [
    {
      "totalPrice": 5.5,
      "statementDate": "2011-10-04T16:58:54.858Z",
      "lineItems": [
        {
          "UnitPrice": 1,
          "Quantity": 5,
          "ProductName": "Pencil"
        },
        {
          "UnitPrice": 0.5,
          "Quantity": 1,
          "ProductName": "Eraser"
        }
      ],
      "invoiceNumber": 1
    },
    {
      "totalPrice": 11.5,
      "statementDate": "2011-10-04T16:58:54.858Z",
      "lineItems": [
        {
          "UnitPrice": 6,
          "Quantity": 1,
          "ProductName": "Notebook"
        },
        {
          "UnitPrice": 2.5,
          "Quantity": 1,
          "ProductName": "Ruler"
        },
        {
          "UnitPrice": 1.5,
          "Quantity": 2,
          "ProductName": "Pen"
        }
      ],
      "invoiceNumber": 2
    }
  ]
}

So we can see here that the data provided is an invoice list and each invoice contains data and line items for that invoice.


Email Reference Id: Winter 16 Changes

by Patrick Connelly posted on October 12, 2015

In the latest Salesforce release (Winter ‘16) there was an update that changes how the Email Reference Id (aka Thread_Id) is generated.

Old Email Reference Id

The old email reference Id was in the format of [ ref:orgId.caseId:ref ] and was really easy to generate. All you had to do was concatenate the currentUser’s orgId and their caseId together

public static String refId (String orgId, String caseId) {
    return '[ ref:' + orgId + '.' + caseId + ':ref ]';
}

Run this and you’re done. Easy peasy.

New Email Reference Id

This all changed with the release of Winter ‘16. Once this hit the way the email reference Id changed so much that the Email to Case process wouldn’t even parse the old thread ids. So when a reply back to an email containing the old email reference id would come in, it would create a new case instead of pairing the EmailMessage with the Case Id in the thread_id.


Comparable: Sorting Objects in Salesforce

by Patrick Connelly posted on October 10, 2015

Like most Object Oriented languages, Apex will allow you to make an order List of objects that you can then iterate over and manipulate. However, Apex will not let you use the built in sort method for List to sort sObjects by a field inside. To do this, we have to implement our own comparable class to do the sorting for us.

Basic sorting

Implementing Comparable

Let’s take a look at a simple class that takes in an Employee object, stores the employee’s data in it and allows us to sort a list of Employees by their salary.


Service Breach Time on Cases

by Patrick Connelly posted on July 29, 2015

Service Level Agreements (SLAs) are very common in the support industry. Salesforce makes these very easy to apply and manage via the built in Entitlement Processes. These entitlement processes will generate Case Milestones that are associated with your case. These milestones will have a Target Date that shows you when your Case Milestones have to be completed. Typically the date itself is fairly difficult to use however if you convert this into the number of minutes remaining then you get a tangible count down for an action that has to be done on the case. This number is called your Service Breach Time (SBT).

Unfortunately there is no easy way to transfer the Target Date from your Case Milestones to your Case and generate your SBT. These fields cannot be pulled into a formula and you cannot write triggers against Case Milestones. You can however use Apex to get the data onto your Case object.


Web services development on Salesforce

by Patrick Connelly posted on March 09, 2015

Several years ago, I wrote a blog post on developing web services on Salesforce. When helping someone in the IRC channel with web services, I realize that the article was outdated and does not follow some of the design patterns that I have learned after spending a lot of time with web services

What are Web Services?

Let’s start with a little background. Web services are Apex code that you expose out and can consume with either SOAP or REST. Typically this is used to expose complex business logic in an easily consumable way. For example, you could use a web service to combine together an account with all of it’s contacts and return them in a single call. In this article we will be covering SOAP endpoints, but most of the principles also apply to REST endpoints.


Storing Schema RecordTypeInfo in Apex

by Patrick Connelly posted on March 04, 2015

I was recently helping a friend with some Apex Controller work for a new VisualForce page, and ran across this error being displayed on the page.

Not serializable: Map<Id,Schema.RecordTypeInfo>

It was weird because it did not appear to be anywhere in the debug logs and it did not email her that an exception occurred anywhere.


Bitwise operations in Apex

by Patrick Connelly posted on February 17, 2015

A couple of days ago a friend of mine was asking about how to do bitwise math on Salesforce in Apex. I didn’t know how to do it on the platform so I decided to give it a shot.

NOTE: None of the topics covered here are specific to Apex or the Salesforce platform. These concepts extend to most languages. However, the code examples below have been tested and verified on the Salesforce platform.

What are bitwise operations?

Bitwise operations are operations that deal with numbers on a binary level. You see this type of operation mainly in lower level programing languages where you have limited resources and need to store lots of information in a small amount of space. For these examples we’ll be using the match details from DOTA 2 output. This allows for Valve to return a single number to represent lot of information.


Salesforce Trailhead: New Modules

by Patrick Connelly posted on February 03, 2015

At the 2014 Dreamforce, Salesforce announced Trailhead, their new platform for learning all about the Salesforce platform, and I have to say it’s pretty great. Anytime someone asks me how they can get started with Salesforce, “Trailhead” is pretty much the first thing out of my mouth. Well that and the IRC channel.

It’s been a couple of months now since Trailhead was released and we’re finally getting new content, and a little bit of updated content for some of the older modules. In addition to these changes the platform seems to have gotten better about it’s error messages when you fail a challenge.


Fun with maps and sets

by Patrick Connelly posted on January 26, 2015

While working on Apex, I discovered an interesting behavior with Maps and the keySet method.

Problem

class TestData {
	public String data;

	public TestData() {}

	public TestData(String data) {
		this.data = data;
	}
}

Map<String, TestData> dataMap = new Map<String, TestData>{
	'foo' => new TestData('foo'),
	'bar' => new TestData('bar')
};

Set<String> keySet = dataMap.keySet();
System.debug(keySet.size()); // 2
System.debug(dataMap.size()); // 2

keySet.remove('foo');
System.debug(keySet.size()); // 1
System.debug(dataMap.size()); // 1

This code does not behave how you would think. If you remove an item from the keySet set it also removes it from the dataMap. What I believe to be happening here is that the keySet method is returning a reference to the key set of the dataMap.


Intro to Apex: Auto converting leads in a trigger

by Patrick Connelly posted on July 23, 2014

Over the past couple of weeks I have seen several posts on the developer forums about writing a trigger to auto convert leads based on some criteria. Since this seems to be a pretty common topic, I thought I’d turn it into my first “Intro to Apex” blog post. In this post I am going to introduce a trigger that converts a lead and the test for this trigger. I am going then break down each line of the trigger and explain what it does and why it is there.

NOTE: This is a very basic trigger. If this were to be used in an environment where there was more than just this functionality in the trigger, I would classify this trigger to control the order of operations.


Snapshotting objects in Salesforce with apex

by Patrick Connelly posted on May 20, 2014

A common issue that we have is a need to see information about Cases when it is created. We do this to do some analysis about how a case changes (primarily to verify how good our automated tools are working). To achieve this, we made a generic snapshot object that will store a JSON version of our data. We chose JSON for it’s portability and it’s ability to dump into other systems.

The Object

To start out we’ll need a place to put this data, so we created the object with the following fields. Download object.

  • JSON_Data_{0-9}__cRequired – These are several LongTextAreas that stores json data
  • Object_Name__cRequired – This is the name of the object that was snapshotted
  • NameRequired – An auto number, just used for identification
  • Case__cOptional – This is used for our case specific snapshot to link a snapshot back to a specific case

Dynamic dependent picklists in Salesforce

by Patrick Connelly posted on July 09, 2012

One thing that comes up a lot in the in the #salesforce IRC channel is doing dynamic Visual Force driven off of picklists. So, let’s buckle up and get to it.

Data Model

In this simple example we are going to make an extension to the case page. On this page we are going to us a custom Product/Version object to display on the page. The product list well be determined on the start/end date of the product. And the version will be driven by the currently selected product. Product

  • Name – The name of the product
  • Currently_Supported__c – Formula based on StartDate__c and EndDate__c (Integer version of a boolean)
  • StartDate__c – The date the product should be shown (Rollup min from the version)
  • EndDate__c – The date the product should be hidden (Rollup max from the version)

Version

  • Name – The name of the version
  • Currently_Supported__c – Formula based on StartDate__c and EndDate__c (Integer version of a boolean)
  • StartDate__c – The date the version should be shown
  • EndDate__c – The date the version should be hidden
  • Product__c – The product the version is related to

Apex Controller

public with sharing class ProductUtils {
    static public List<Product__c> getAllProducts(Boolean includeEOL) {
        //This is done since the formula field cannot return a boolean
        Integer currentlySupported = (includeEOL) ? 0 : 1;

        return [
            select Name
            from Product__c
            where Currently_Supported__c >= :currentlySupported
            order by Name
        ];
    }

    public static List<Product__c> getAllProducts() {
        return getAllProducts(false);
    }

    public static List<Version__c> getAllVersions(Id productId, Boolean includeEOL) {
        Integer currentlySupported = (includeEOL) ? 0 : 1;

        return [
            select Name,
                Product__c
            from Version__c
            where Currently_Supported__c >= :currentlySupported and
                Product__c = :productId
            order by Name
        ];
    }

    public static List<Version__c> getAllVersions(Id productId) {
        return getAllVersions(productId, false);
    }
}

These methods are simple util methods to get product information and version information

global with sharing class CaseEdit_ControllerExtension {
    private final Id recordId;
    private final Case record;
    private final ApexPages.StandardController controller;

    public Case_ControllerExtension(ApexPages.StandardController stdController) {
        this.controller = stdController;
        this.recordId = this.controller.getId();
        this.record = [
            select Product__c,
                Subject,
                Version__c
            from Case
            where Id = :this.recordId
            limit 1
        ];
    }

    public List<SelectOption> getProductList() {
        List<SelectOption> products = new List<SelectOption>();
        products.add(new SelectOption('', '--None--'));

        for (Product__c p: ProductUtils.getAllProducts()) {
            products.add(new SelectOption(p.Id, p.Name));
        }

        return products;
    }

    public Id getProduct() {
        return this.record.Product__c;
    }

    public void setProduct(Id productId) {
        this.record.Product__c = productId;
    }

    public List<SelectOption> getVersionList() {
        List<SelectOption> versions = new List<SelectOption>();
        versions.add(new SelectOption('', '--None--'));

        if (record.Product__c != null) {
            for (Version__c v: ProductUtils.getAllVersions(getProduct())) {
                versions.add(new SelectOption(v.Id, v.Name));
            }
        }

        return versions;
    }

    public Id getVersion() {
        return this.record.Version__c;
    }

    public void setVersion(Id versionId) {
        this.record.Version__c = versionId;
    }

    public PageReference doSave() {
        Case c = (Case) controller.getRecord();
        c.Product__c = this.record.Product__c;
        c.Version__c = this.record.Version__c;

        upsert c;

        return new PageReference('/'+c.Id);
    }
}

The controller has the getters and setters for the product and version. But most importantly the getters for productList and versionList. The versionList is triggered off the record’s product. The other part of this is that for whatever reason (I couldn’t find a good one) is the getRecord does not include the changes made to the Product__c and Version__c field, so you’ll need to set them by hand in the doSave method.

One thing to note is since this is all done in the controller extension and since get and set use the Id, the select list will have the correct thing set when editing an existing record.

Visual Force Page

<apex:page standardController="Case" extensions="CaseEdit_ControllerExtension" title="Case Edit" tabStyle="Case">
    <apex:form id="form">
        <apex:pageBlock title="Case Edit">
            <apex:pageBlockButtons>
                <apex:commandButton action="{!doSave}" value="Save" />
                <apex:commandButton action="{!cancel}" value="Cancel" />
            </apex:pageBlockButtons>
            <apex:pageBlockSection title="Case Information">
                <apex:inputField value="{!Case.Summary}" required="true" />
                <apex:pageBlockSectionItem>
                    <apex:outputLabel for="productList" value="{!$ObjectType.Case.fields.Product__c.label}" />
                    <apex:actionRegion>
                        <apex:selectList value="{!product}" title="Product" size="1" id="products">
                            <apex:selectOptions value="{!productList}" />
                            <apex:actionSupport event="onchange" rerender="versions" />
                        </apex:selectList>
                    </apex:actionRegion>
                </apex:pageBlockSectionItem>
                <apex:pageBlockSectionItem>
                    <apex:outputLabel for="versions" value="{!$ObjectType.Case.fields.Version__c.label}" />
                    <apex:actionRegion>
                        <apex:selectList value="{!version}" title="Version" size="1" id="versions">
                            <apex:selectOptions value="{!versionList}" />
                        </apex:selectList>
                    </apex:actionRegion>
                </apex:pageBlockSectionItem>
            </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form>
</apex:page>

The key parts of this is that the actionRegion surrounds both the item changing (product) and the dependent item (version). If you had a third picklist you wanted to trigger on you could add another actionSupport item and tell it to rerender that third list.

Conclusion

Dependent picklists are not very hard to do as long as you remember the actionRegion around both the source and target, and making sure to get the data from the picklist prior to upserting your record.


Scheduled actions in Salesforce with Apex

by Patrick Connelly posted on May 26, 2012

Scheduled actions in Apex are great to use when you need to have a section of code run at a particular time in the future and Time-Based workflows will not work. In the example below I’ll talk about how to schedule code to run at the first of every month, in addition talk about some constructs you can use to make your life easier when you have to redeploy/change this code

Schedulable

The key part of the apex class is that it must implement Schedulable and it must have an excecute method.

global class scheduledMonthly implements Schedulable {
    /**
    * Builds up all of the new Objects
    *
    * @param sc The schedulable context
    */
    global void execute(SchedulableContext sc) {
        //Code goes here
    }
}

Now, we can fill out the class. Below is an example where we iterate through all of the accounts of a specific record type and insert a new list of MyObject based on that account. This could be as complex as you want.

global class scheduledMonthly implements Schedulable {
    /**
    * Builds up all of the new Objects
    *
    * @param sc The schedulable context
    */
    global void execute(SchedulableContext sc) {
        RecordType rt = [
            select Id
            from RecordType
            where DeveloperName = 'Recipient'
        ];

        List<MyObject__c> objectList = new List<MyObject__c>();

        //Get all of the accounts of type 'Recipient'
        for (Account account: [
            select Id
            from Account
            where RecordTypeId = :rt.Id
        ]) {
            objectList.add(new MyObject__c(
                Account__c = account.Id
            ));
        }

        if (!objectList.isEmpty()) {
            insert objectList;
        }
    }
}

To schedule this class we could call it from any number of places, such as a VisualForce page, a Trigger or the Developer Console. Since scheduled classes cannot be pushed out or changed when there are jobs in the queue we want to add a helper method to schedule this job. In our instance it will only be ran once a month, so we include our CRON_EXP as a static variable (for easy use) and to reduce the change of mis-scheduling.

/**
* To schedule the monthly reconciliation:
*    NOTE: It should run at midnight on the first of every month on it's own, but if you make
*    changes and need to requeue run the command below from the developer's console
*
*    scheduledMonthly.scheduleIt();
*/

global class scheduledMonthly implements Schedulable {
    public static String CRON_EXP = '0 0 0 1 * ? *';

    /**
    * Static method used to schedule the default reconciliation
    *
    * @return The jobId from the scheduled run
    */
    global static String scheduleIt() {
        scheduledMonthly sm = new scheduledMonthly();
        return System.schedule('Monthly Reconciliation', CRON_EXP, sm);
    }

    /**
    * Builds up all of the new Monthly Reconciliations and Distributions
    *
    * @param sc The schedulable context
    */
    global void execute(SchedulableContext sc) {
        RecordType rt = [
            select Id
            from RecordType
            where DeveloperName = 'Recipient'
        ];

        List<MyObject__c> objectList = new List<MyObject__c>();

        //Get all of the accounts of type 'Recipient'
        for (Account account: [
            select Id
            from Account
            where RecordTypeId = :rt.Id
        ]) {
            objectList.add(new MyObject__c(
                Account__c = account.Id
            ));
        }

        if (!objectList.isEmpty()) {
            insert objectList;
        }
    }
}

To reset our schedule all we have to do is use type the following into the Developer console.

scheduledMonthly.scheduleIt();

And by looking in Setup → Monitoring → Scheduled Jobs we can see that our scheduledMonthly class is there.

Cron Syntax

There are seven fields for Salesforce’s cron syntax, unlike *nix’s 5 fields.

  • Seconds [0-59]
  • Minutes [0-59]
  • Hours [0-23]
  • Day of month [1-31]
  • Month [1-12 or JAN-DEC]
  • Day of week [1-7 or SUN-SAT]
  • Year [1970-2099]

There are also some special characters you can use:

  • , used to delimit values [hours, day of month, month, day of week, year]
  • - used to specify a range [hours, day of month, month, day of week, year]
  • * used to specify all values [hours, day of month, month, day of week, year]
  • ? used to specify no specific value [day of month, day of week]
  • / used to specify increments [hours, day of month, month, day of week, year]
  • L used to specify the end of a range [day of month, day of week]
  • W used to specify the nearest weekday [day of month]
  • # used to specify the nth day of the month [day of week]

Testing

Testing for scheduled apex may seem confusing but it’s very straight forward. Like @future calls, scheduled apex will not fire until after the _Test.stopTest()_has been run. In the test below we test the following:

  • The Cron Expression is the same
  • The job has not been triggered yet
  • The scheduled date is correct
  • No MyObjects were created
  • One object was created after the scheduled job was ran
@isTest
class scheduledMonthlyTest {
    public static RecordType fetchRecordType(String name) {
        return [
            select Id
            from RecordType
            where DeveloperName = :name
        ];
    }

    public static Account getAccount(RecordType rt) {
        return getAccount(rt, '_unittest_account_: 001');
    }

    public static Account getAccount(RecordType rt, String name) {
        return new Account(
            Name = name,
            RecordTypeId = rt.Id
        );
    }

    public static CronTrigger fetchCronTrigger(String jobId) {
        return [
            select CronExpression,
                TimesTriggered,
                NextFireTime
            from CronTrigger
            where Id = :jobId
        ];
    }
    public static Map<Id, List<MyObject__c>> fetchMyObjects(List<Account> accts) {
        Map<Id, List<MyObject__c>> result = new Map<Id, List<MyObject__c>>();

        for (Account a: accts) {
            result.put(a.Id, new List<MyObject__c>());
        }

        for (MyObject__c mo: [
            select Account__c
            from MyObject__c
            where Account__c in :result.keySet()
        ]) {
            result.get(mo.Account__c).add(mo);
        }
    }

    static testMethod void testScheduledMonthly() {
        RecordType rt = fetchRecordType('Recipient');

        Account testAccount = getAccount(rt);
        insert testAccount;

        Test.startTest();

        String jobId = System.schedule(
            '_unittest_scheduled_: 001',
            scheduledMonthly.CRON_EXP,
            new scheduledMonthly()
        );

        CronTrigger ct = fetchCronTrigger(jobId);

        System.assertEquals(
            scheduledMonthly.CRON_EXP,
            ct.CronExpression,
            'Did not get the same Cron Expression back'
        );
        System.assertEquals(
            0,
            ct.TimesTriggered,
            'The job has been run and should not have'
        );

        DateTime today = DateTime.now();
        String dateString = '' +
            today.year() + '-' +
            today.addMonths(1).month() +
            '-01 00:00:00';
        System.assertEquals(
            String.valueOf(DateTime.valueOf(dateString)),
            String.valueOf(ct.NextFireTime),
            'Did not get the right fire date'
        );

        List<MyObject__c> myObjs = fetchMyObjects(new List<Account>{testAccount}).get(testAccount.Id);
        System.assert(
            myObjs.isEmpty(),
            'Should have gotten no objects back'
        );

        Test.stopTest();

        myObjs = fetchMyObj(new List<Account>{testAccount}).get(testAccount.Id);
        System.assert(
            1,
            myObjs.size(),
            'Did not get the right number of objects back'
        );
    }
}

Limitations / Notes

There are three big limitations / notes about scheduled Apex

  • It will be put on the queue at the given time, it is not guaranteed to run at that time.
  • You can only have 25 classes scheduled at a time
  • You cannot use getContent or getContentAsPDFPageReference

Salesforce and soapUI – Using the default query method

by Patrick Connelly posted on April 13, 2012

In a previous post I discussed how to test Salesforce webservices with soapUI. In this post I will show how to use the “default” methods inside the enterprise WSDL.

Logging In

First we need to login to Salesforce and get our session Id. Under the SoapBinding list, expand login and choose Show Request Editor. After opening the request editor we need to remove the extra headers we don’t need, and fill in our username and password.

Logging In

Then press the “play” button to send the request

Login request play button

Now in the resulting XML we can pull out our session Id

Session Id

And we can pull out our server Url

Server Url

Adding the new endpoint

If we create a new query request and remove the unneeded headers and insert our session Id and run the request you get the following error:

UNKNOWN_EXCEPTION: Destination URL not reset. The URL returned from login must be set in the SforceService

To fix this issue we need to add a new end point to our SOAP request. Using the server Url obtained during login we can add it to our request

New end point

And now we can rerun our new request with the correct endpoint

New end point

Conclusion

Unlike custom webservices which include the Salesforce endpoint as part of the WSDL the standard Salesforce enterprise WSDL only has the test or login url included. Because of this, we need to use the returned server url to set our end point.


Reducing Salesforce SOQL queries by using static variables

by Patrick Connelly posted on April 04, 2012

The more moving pieces you have with triggers and classes the more you want to reduce the number of SOQL queries. One way to do this is to have Utility classes that do a lot of the heavy lifting. The problem with this is that you don’t want to call a utility method that does a query every time, because if you call it from different triggers you’ll end up with multiple calls. This is where overloading static variables can come in.

The Problem

Lets say you have a trigger on a Contact that needs information from our mostly static MyObject__c and then the Contact trigger then updates a Case. The Case trigger also need information from the MyObject__c. Normally this would require two SOQL queries even if it was in a utility class. We can use some of the built-in functionality in Apex to overload a static variable.

The Class

public with sharing class MyObjectUtils {
     public static List<MyObject__c> myObjectList {
          get {
               if (myObjectList == null) {
                    myObjectList = [
                         select Name
                         from MyObject__c
                    ];
               }

               return myObjectList;
          }
          set;
     }

     public static Map<String, MyObject__c> myObjectMap {
          get {
               if (myObjectMap == null) {
                    myObjectMap = new Map<String, MyObject__c>();
                    for (MyObject__c obj: myObjectList) {
                         myObjectMap.put(obj.Name, obj);
                    }
               }

               return myObjectMap;
          }
          set;
     }
}

The Implementation

In the trigger where we want to use the MyObject instance we can do the following

MyObject__c obj = MyObjectUtils.myObjectMap.get('Foo');

Now, the next time the map or list are used in the same execution we will have it “cached” and will not have to make an additional query.


Classifying Triggers in Salesforce

by Patrick Connelly posted on February 13, 2012

Anyone that has ever had multiple triggers on objects in Salesforce knows that it can be very painful to manage them. Because of the way Salesforce chooses to run the triggers your code can be run in a non-deterministic order. In addition to this, having to sort through multiple files to find the one piece of code you are looking to update can be painful.

To combat this, you can take your triggers and condense them down into a single trigger and a single class. Inside this class you would have a method containing each of your individual triggers.

Preface

In the examples below we will be creating a trigger on the MyObject__c to do awesomeness. In the example we do not cover the case of undelete.

The Trigger

The trigger is quite simple, all it does is call the a static method of the class with the correct parameters.

trigger MyObject on MyObject__c (before insert, before update, before delete, after insert, after update, after delete) {
     MyObjectTrigger.processTrigger(Trigger.oldMap, Trigger.new, Trigger.isBefore);
}

The Class

This is where the meat of the functionality exists. The constructor sets up the maps and lists as well as the booleans. Inside your doAwesomeness method you can check to the booleans isUpdate, isDelete, isInsert to make your routing determination. If you do not want the method to run, just return out of it and the execution will stop.

public class MyObjectTrigger {
     private final Map<Id, MyObject__c> oldMap;
     private final Map<Id, MyObject__c> newMap;
     private final List<MyObject__c> newObjs;
     private final Boolean isInsert;
     private final Boolean isUpdate;
     private final Boolean isDelete;
     private final Boolean isBulk;

     /**
     * The constructor
     *
     * @param xoldMap The old map from the trigger
     * @param xnewObj The list of new objects from the trigger
     * @param isBefore If the trigger is in before or after
     */
     public MyObjectTrigger(Map<Id, MyObject__c> xoldMap, List<MyObject__c> xnewObjs, Boolean isBefore) {
          oldMap = xoldMap;
          newObjs = xnewObjs;

          if (!isBefore && newObjs != null) {
               newMap = new Map<Id, MyObject__c>(newObjs);
          }

          isDelete = (((newObjs == null || newObjs.isEmpty()) && isBefore) || ((newMap == null || newMap.isEmpty()) && !isBefore));
          isUpdate = ! (isDelete || oldMap == null || oldMap.isEmpty());
          isInsert = ! (isDelete || isUpdate);
          isBulk = (((!isDelete) && (newObjs.size() > 1)) || ((isDelete) && (oldMap.size() > 1)));
     }

     public void doAwesomeness() {
          //Do stuff
     }

    /**
    * Method to initiate trigger logic
    *
    * @param oldMap The old map from the trigger
    * @param newObj The list of new objects from the trigger
    * @param isBefore If the trigger is in before or after
    */
     public static void processTrigger(Map<Id, MyObject__c> oldMap, List<MyObject__c> newObj, Boolean isBefore) {
          final MyObjectTrigger myTrigger = new MyObjectTrigger(oldMap, newObj, isBefore);

          if (isBefore) {
               myTrigger.doAwesomeness();
          }
     }
}

Conclusion

We’ve been using this method for almost a year now and it works really well. If you need data to persist between methods this way works wonderfully. Just create a global variable and set it up in your constructor. This will save you SOQL calls and if done correctly could save you DML operations


Salesforce and soapUI — Testing WebServices directly

by Patrick Connelly posted on February 03, 2012

In a previous post I talked about writing webservices for Salesforce. In this post I’ll discuss how to test your webservice with soapUI without having to write any additional code.

Getting soapUI

You will need to install the Open Source version of soapUI from their ]sourceforge. Go ahead, I’ll wait…

Getting the WSDLs

Now that you have soapUI installed we need to download our WSDLs. You’ll need the Enterprise WSDL which can be found at Setup-Develop-API. And you’ll need the WSDL for your webservice which can be found at Setup-Develop-Apex Classes, then find your class and click the WSDL link next to it. I suggest downloading them into a WSDL folder just for organization.

Setting up soapUI

Now that we’ve got all of our parts we need to create a new soapUI project. If you are testing multiple webservices I suggest you only create one soapUI project and import the additional webservices into it. This will make updating the enterprise WSDL easier, and will make your life less stressful.

Right-click on Projects and select New soapUI Project and fill out the form with your information. Your intial WSDL should be the enterprise WSDL. You will at the very least want to have Create Requests checked. You can choose the other later if you want to.

New soapUI Project

After creating the new project you will see a section called SoapBinding with several methods below it. These are standard Salesforce methods that are provided by the Salesforce Enterprise WSDL. Let’s ignore these for right now, and import our webservice. To add a new WSDL right-click on the project name, Salesforce in our case, and select Add WSDL.

Add WSDL button

Then we want to choose our webservices WSDL

Add WSDL screen

Using soapUI

Now that we are all setup, let’s test our webservice. First we need to login to Salesforce and get our session Id. Under the SoapBinding list, expand login and choose Show Request Editor. After opening the request editor we need to remove the extra headers we don’t need, and fill in our username and password.

Login request

Then press the “play” button to send the request

Play button on login request

Now in the resulting XML we can pull out our session Id

Session Id

Copy the session Id and we will use it to make a request to our webservice. In the example below I am calling the search method on my CaseAPI. Again, we can remove almost all of the header out of the request. The only section we need to leave is the SessionHeader and SessionId.

Request with session Id

Then fill in the request to your webservice. This will all depend on how yours is designed. In the webservice call below, we pass in two context objects. One takes in an ssoName and the other takes in a searchString. Then as before click the “play” button and you’ll get your response back.

Conclusion

SoapUI is a great tool to help test webservices out. You can use it to build up tests, but that’s another post. I use it all of the time to verify that Salesforce is returning the correct data from my webservice instead of trying to write against the webservice and trying to determine if my client is messing up.


Creating Web Services in Salesforce

by Patrick Connelly posted on January 06, 2012

This article has been updated to show lessons learned over the past three years. The content of this article is still relevant, but is a little out-dated.

Preface

At my current job, we have several external systems that interact with Salesforce, and they do so through web-services. This document will cover what I have learned in regards to web-services, caveats with them and common pitfalls.

Overview

The goal of our web-services is to provide a single point of entry for each major object represented in Salesforce. A major object would be Account, Case, Case Comment etc. The reason this is differentiated is that for instance, Case Groups would under the AccountAPI since they are a minor object. Each web-service consists of two parts. First the actual web-service class which holds the externally facing methods and from which the WSDL is generated. The second part is that of the util class which holds all of the logic and is reusable.

Web-service class

APIUtils

This class contains several static variables, exceptions and most importantly the classes that are returned from the web-service

Static Variables

The static variables listed here are used to set the returnCode in the resulting return class. This helps to keep return codes consistent with what is expected by the calling app

Exceptions

There are two types of base exceptions in APIUtils

InvalidException

This is used for things that are passed into the web-service that are considered invalid. For example an invalid username passed in, or if the account does not match the requesting contact.

UnknownException

This is used when the requested object cannot be found. For example if the case 123456 was requested and was not found then this would be a_UnknownCaseException_

Generic Contexts

For most web-services, they will contain their own Context classes. But there are some context classes that are common and reusable. The primary one being the ContactContext. The ContactContext is often passed into the method to determine access level.

Returned Classes

These are abstraction classes usually representative of a Salesforce object.

  • Each field to be returned must be of type WebService
  • Each class should have Integer returnCode and String message to be passed back to the caller.
  • If the method is to return a List a wrapper class of APIObjects should contain returnCode, message and a List of Objects. [Example below]
  • Each class should have a constructor to aid in creation. This will save time in the long run and will make writing tests 1000 times easier

Note: You could probably throw exceptions out to the calling service instead of setting a returnCode. I think that setting the returnCode instead of throwing an exception makes it easier for integration since the integrator does not need to know the exceptions.

ObjectAPI

This class should be written primarily as a wrapper class for the Object’s util class

Specific Contexts

If contexts are needed and they will only be used by this API, then they should be included directly in the API file

  • Each field must be of type WebService
  • Each class should have a constructor to aid in creation
  • Do not assume that variables in contexts will be set

Methods

Each method should be disparate function of work and contain minimal logic. These methods should call the required Util methods, transform data, catch exceptions and set returnCode/messages

  • Method must be of type WebService
  • Method must be static
  • Method should return an APIObject
  • Method should set the returnCode and the message of the APIObject
  • All calls should be in a try-catch block so that no exceptions are leaked

ObjectUtils

This class should have the majority of the logic. The methods in this class should follow the idea of Samurai Programming. Samurai Programming means the method should “return successful or not at all.” This means instead of returning null if an error happens (if the method should return something ie getCase) then the method should throw an exception.

  • Most methods will be static
  • Methods should throw an exception if the parameters are set incorrectly
  • SOQL queries that are single lines should have their exceptions caught, reported then throw the appropriate exception. For example if we are selecting a single Case using Case c = [ select ... ] then we should catch the exception in case the query fails, and then thrown an UnknownCaseException.

Caveats

  • Declaring a class as virtual and then implementing that class to try to have global variables that all classes get do not work. The fields will not show up in the generated WSDL