salesforce

JWT Bearer Authentication: Salesforce and Node

by Patrick Connelly posted on March 08, 2019

If you’ve done much API generation then you’ll that you don’t want to have to make your users authenticate multiple times just because your API is going somewhere external. For example, if you have an API that reaches into Salesforce but your app uses Google SSO, you don’t want to have to present an oauth screen to your user after they’ve already authenticated. To work around this, you can use a JWT Bearer flow to login on behalf of a user and get a access token to work with.


Single Sign-On in Salesforce with Google

by Patrick Connelly posted on March 05, 2019

I started down this path to flesh out a proof of concept for a related task. However, the Single Sign-On provider that we use is difficult to get access to and not worth the time to try to get permission to use it. So instead, I thought I’d just use my personal Google domain as the identity provider so I can get it done faster. So I’ve decided to document my journey and hopefully help someone else set this up.


Change Data Capture with Nodejs

by Patrick Connelly posted on January 23, 2019

There’s a new feature in Salesforce called Change Data Capture that allows you to subscribe to a Cometd endpoint and stream changes to most or some of your objects. I’ve talked in a previous post about how to get data out of Salesforce and this seems like it might be the front-runner for one of the best ways. I would still plan on ways to get data if it exceeds the three day replay period and you’ll also need a way to do your initial data import.

What data can I get with Change Data Capture?

In a perfect world, everything you’d need would always live in Salesforce and you’d never have to worry about backing up data. Well, we don’t live in a perfect world. Lot’s of times you need to get data out of Salesforce and get it into an external system. You could do this for data backup, for populating a search index, for sending messages to an external system. With Change Data Capture, you can do this type of data flow in real-time.

Change Data Capture supports the following standard object (at time of writing):

  • Account
  • AccountContactRole
  • Asset
  • Campaign
  • Case
  • Contact
  • Event
  • EventRelation
  • Lead
  • ListEmail
  • Opportunity
  • OpportunityContactRole
  • Order
  • OrderItem
  • Product2
  • Task
  • User

In addition to the standard items above, Change Data Capture supports all custom objects.


PMD and Salesforce: Clean Code is Awesome

by Patrick Connelly posted on July 06, 2018

If you’re not aware, having clean code is more than just about readability. It’s about sustainability, re-usability and knowing that your code is doing what you want it to do. This is where PMD comes into the picture. PMD is a static code analysis tool that takes code from many different languages, analyzes it and provides you with feedback. Fortunately for the Salesforce world PMD now supports Apex as one of it’s languages. So, let’s dive into how to set it up, run it and then how to use some of the rules included.


Postman – Logging in to Salesforce

by Patrick Connelly posted on August 08, 2017

We’ve been slowly replacing all of our SOAP endpoints with REST endpoints inside of Salesforce. The upside of this is that they are much easier to use. The downside is that they are harder to functionally test without a bunch of work to generate session Ids. (This was made even more frustrating by a recent change that obfuscates out the session id in debug logs) So, I decided to figure out how to run a Postman request that would then store the session id and server url for later requests to use. This post will cover how to set that up and use this one request. I plan on writing more in-depth blog later about how to use Postman to test custom REST endpoints later.


JMeter – Logging Into Salesforce for Automated Testing

by Patrick Connelly posted on June 29, 2017

I’ve written quite a few web services in Salesforce, and I’ve written about them a couple of times. And my love of testing is pretty well known. One thing that’s always been a problem is testing the web services in an automated fashion as a real consumer would. I’ve talked about manually testing them with SoapUI before, and while useful doesn’t fit into an automated process well. So let’s jump into the world of JMeter and how we can automate our web service testing for Salesforce.


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.


Javascript and Visualforce: Tips and Tricks

by Patrick Connelly posted on January 09, 2017

In the web 7.0 or whatever version of the web we’re in, Javascript is king. Now, there’s lots of stuff you can do directly with Visualforce (like dynamic picklists) but sometimes for the best user experience you’ll want to use Javascript to make it even better. There are lots of Javascript tutorials out there and there are lots of Visualforce tutorials out there (don’t forget Trailhead) so I’m going to talk about some tricks that people should know when working with Javascript on Visualforce


Managing reports and dashboards programatically

by Patrick Connelly posted on December 08, 2016

One of the challenges you get when you have a special snowflake org is lots of people want to write lots of reports and lots of dashboards for each of their special use cases. Now, lots of times reports aren’t the right way to go with this so you have to educate your users on the right way to do this and their old reports get abandoned. Or a user will create a one off report and never look at it again. As it stands right now, we have several thousand reports that haven’t been looked at in more than 90 days.


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”


Standard picklist changes Winter '17

by Patrick Connelly posted on November 24, 2016

I wrote a couple of weeks ago I wrote about the GlobalPicklist changes in Winter ‘17. This past week I learned that there was another change in the release notes that I overlooked.

After updating the Case object to API 38.0 I didn’t notice that the Case.Type field had changed. In API 37.0 this is what the Case Type field looks like

<fields>
    <fullName>Type</fullName>
    <inlineHelpText>The case type</inlineHelpText>
    <picklist>
        <picklistValues>
            <fullName>Value 1</fullName>
            <default>false</default>
        </picklistValues>
        <picklistValues>
            <fullName>Value 2</fullName>
            <default>false</default>
        </picklistValues>
        <sorted>false</sorted>
    </picklist>
    <trackFeedHistory>false</trackFeedHistory>
    <trackHistory>false</trackHistory>
    <trackTrending>false</trackTrending>
    <type>Picklist</type>
</fields>

And this is what it looks like in API 38.0

<fields>
    <fullName>Type</fullName>
    <inlineHelpText>The case type</inlineHelpText>
    <trackFeedHistory>false</trackFeedHistory>
    <trackHistory>false</trackHistory>
    <trackTrending>false</trackTrending>
    <type>Picklist</type>
</fields>

In the turmoil of all the other changes to the object file, I completely missed the change. And when the deployment failed I was at a loss to figure out why. The failure wasn’t about the picklist in particular, it was about the picklist value in a record type.


Table Header in PDFs with Visualforce

by Patrick Connelly posted on November 15, 2016

One of the problems I had with the way that we generated the PDFs in previous Battle Station Invoice posts was that the table header wasn’t repeated for long lists of supplies or resources that continued on the next page. There’s a simple way to add the table header for PDFs generated in Salesforce using the flying saucer mark-up but that won’t generate the table header correctly for us. It seems that the -fs-table-paginate tag does not play well when combined with a Visualforce component so we’ll need to take a bit more of a native CSS approach.

If you are doing this with plain Visualforce and apex:pageBlockTable, the -fs-table-paginate is the way to go.

GlobalPicklist changes in Winter '17

by Patrick Connelly posted on November 11, 2016

Like many companies, we have a deployment process in place to handle changes in seasonal releases in Salesforce so that when a sandbox is ahead of production, we can still deploy to both without having to wait for production to be updated. Then, after both the release hits production, we go through a manual process of updating the API (primarily the ant-salesforce.jar) and the metadata to the most recent API version. Typically this just involves updating the jar and updating the API version in the request, pulling down the updated metadata and writing it to SCM. However, with the Winter ‘17 release we saw a problem trying to deploy our GlobalPicklist files after updating the API.


Japanese Users and Reports

by Patrick Connelly posted on November 04, 2016

There are lots of times where working with Salesforce would be so much easier if it weren’t for the users. But, they’re the reason I still have a job, so you’ve got to put up with them. One of the problems with users is they tend to like to live all over the world and they all have their own ways of working and cultural eccentricities. One of the ones that has caused us grief in the past (both in Apex and in reports) is the fact that Japanese users in Salesforce default to “Lastname Firstname” when using the Name field on Users. Now, this in and of itself is not really a problem because lots of reports are written for a single user or for a relatively small group of users (such as others in the same geographical location). Where this becomes a problem is when locales get mixed with reports and all hell breaks loose.


Child Package: Extending a Manage Package

by Patrick Connelly posted on October 18, 2016

In an effort to try to reduce the amount of code in our base repository we’ve been looking at writing managed packages that we install in our production org and then delegate the development and maintenance of these packages off to other teams. Being a Open Source company we also want to try to offer what work we’ve done to other people. However, not everything we want this package to do is useful outside of our business. To solve this, we’re releasing the base package and then creating a private child package to hold most of our business logic and custom fields.


Dreamforce recap

by Patrick Connelly posted on October 13, 2016

So it’s been a week since the end of Dreamforce 2016 and I’ve had some time to soak in what was talked about. This year my task for Dreamforce was to go and get some pretty specific answers. So, instead of talking about everything that happened at Dreamforce and what I think about it, I’m going to talk about the three things I was tasked with looking into.


Live Agent Quickstart

by Patrick Connelly posted on October 03, 2016

With the recent updates to the licensing model at Salesforce, lots of companies now get Live Agent licenses included. Because of this I’m working on a hands-on training for how to setup Live Agent and use it in Service Console. As you could guess, this isn’t an quick thing to do so I’m splitting it up into parts.

Quickstart

Why?

One of the hardest parts of Live Agent to test out for non-developers is the actual web front end part. If write the HTML locally and then you can test it but others can’t. To make it so others can test it, you either have to set up a web server or figure out how to deploy it to a cloud provider such as Heroku or Openshift. And that can be pretty daunting for someone that’s just trying to setup a proof of concept or is just working on the configuration side and will pass it off to someone else from their web team.

What does the quickstart provide?

The Live Agent quickstart I wrote provides a super fast way to deploy a Live Agent button to Heroku. Once you have set up Live Agent, you can copy and paste parts of the configuration into the first screen of the Heroku app setup and then click deploy. After a couple of minutes you have a website that anyone can goto and interact with your chat button!

What’s Next

Similar to the entitlement process hands on training, I’ll be publishing it to github for everyone to use (and fork if desired). It’s going to take some time since it’s a lot of brand new content but I’m hoping to have it done before the end of the year. So, follow here and at the github repo to keep informed of it’s progress.


Dreamforce: What Not To Bring

by Patrick Connelly posted on September 26, 2016

By this point, you’ve no doubt read plenty of articles about what to bring to Dreamforce and how to prepare. If you’ve not had the chance yet, do yourself a favor and checkout the Dreamforce Trailhead module. But that’s not what I’m here to talk about. I want to talk about things you shouldn’t bring to Dreamforce, specifically things that I have brought in the past. So, let’s learn from my mistakes!

Dreamforce Ready

If this upcoming Dreamforce is your first, buckle up! it’s a wild ride. 2016 will be my 5th Dreamforce and I’ve brought a bunch of things over the years thinking I would need them and ended up not using them at all (or barely).

What Not to Bring

  • Entertainment devices – This is a pretty big category so lemme break it down. Over the years I’ve brought things like card / board games, gameboy, PSP, extra movies, etc. All with the intention of using them in my “downtime,” and let me tell you, there is no downtime. Now if you have a long flight, by all means bring stuff with you to keep you entertained. But don’t bring it thinking you’ll find time to use it. There is so much to do at Dreamforce that you’ll barely have time to sleep. You’d be better off spending that time catching up on your sleep or meeting new people (or catching up with old friends).
  • Work – Now hear me out. I know there are lots of solo admins, senior team members, CEO, CTO, etc coming to Dreamforce and it’s tough to leave work at work. Try. You’ll be better off if you focus on the talks being given, the hands on training or the networking than half paying attention while trying to do work. If you have to do work, try to set expectations that you’ll do it in the morning or the evening before the conference kicks off.
  • Computers – Well, this one is a bit of a “clickbaity” bullet point. When you’re in attending a talk, shut the computer. Bring some paper if you want to take notes but for the most part, just pay attention. The slides will be provided after the talk so there’s no need to copy down every word that’s been said. You’ll absorb more of the talk if you’re giving it your full attention. Now there are plenty of places you’ll want to have your computer, such as the mini-hacks, so bring it. Just don’t use it all the time.
  • All your camera gear – This one pains me to say more than any. I’m a photographer and love to use my camera. But unless I’m have planning to go somewhere like a tour or on a photo walk I found that I just carrying around a bunch of heavy lenses. If you want to bring your real camera, go minimal. This year I’ll just be bringing my D90 and my 50mm lens. Not only will it lighten up my bag, but it will force me to be creative with my work since I can’t just changes lenses.
  • Your conference badge – Yes, you do need to bring it with you when you’re trying to enter any of the conference buildings. But you don’t need to be wearing it when you’re out to dinner with your team. And you don’t need to be wearing it when you’re walking around at Union Square. San Francisco is a pretty safe city, but it’s a big city. And like any big city your ultimate goal should be to not make yourself an obvious target. For some interesting reading look at things on the gray man theory*
  • Preconceptions – Every Dreamforce is different and every person experiences it differently. So, take everything in the article (and every other article you’ve read) with a grain of salt. Do your Dreamforce your way and don’t succumb to peer pressure. Oh, and check your biases at the door too.

What to Bring

Yeah, I know, this is suppose to be what not to bring. But there are a couple of things that I have to list that I have found get left off of most lists.

  • A jacket – I live in a state that is in a constant state of being so humid it should rain but not actually raining. A state where simply the act of walking from your front door to your car can end up with you being drenched in sweat. San Francisco is not in my state. It can get pretty chilly during Dreamforce at night, especially down near the water. Do like your mother told you and bring a light jacket. If you forget, there are typically lots of ways to win a hoodie at Dreamforce.
  • An envelope – One of the first things I do when I check into my hotel room is to ask the front desk for a couple of envelopes. I use these throughout the conference to store receipts in and to store business cards. This keeps all of my paperwork organized so when I get home I don’t have to check through 30 different pockets to find a receipt for my expense report.
  • An extra bag – Most likely, you’re going to end up with a bunch of extra swag (which is not an acronym for Stuff We All Get). In previous years, I’ve relied on the conference bag to be big enough to hold anything extra. Last year all of my bags were bursting at the seams so I decided to pick up a collapsible duffel bag. I’ll fly out with just carry-on bags, fill up the duffel bag and then check a bag on my way back. Check out David’s great article on how to get swag at Dreamforce.

* Just a quick note. Most of the stuff on gray man theory comes from “survivalist” or “tactical” sites. The concepts behind these are useful but some of it can be a little too tin-foil hat for me. I’d also recommend the first chapter of the Handbook of Practical Spying.


My Story: How I Became A Salesforce Developer

by Patrick Connelly posted on September 20, 2016

There are many stories like this, but this one is mine. I was born in North Carolina… wait, that’s probably too far back.

Becoming a Code Monkey

Since an early age, I’ve known that I’ve wanted to be a programmer. I use to “design” web pages on Angelfire and dabble in BASIC back in middle school. Looking back now, it wasn’t anything special but it was the catalyst that would carry me into some of my high school classes and eventually on to my degree in computer science from North Carolina State University (go Wolfpack!).


Namespaced Component in Managed Packages

by Patrick Connelly posted on September 13, 2016

As part of my managed package crusade I decided I should delve into the world of Visualforce from a managed package. While pure Visualforce is going to be in my package that’s not nearly as interesting as packaging and using namespaced components as part of the package. So let’s take a look at how we can use a namespaced component.

Namespaced Component

The component that I created in my packaging org is simple. The Visualforce page provides an account Id and the component lists out each of the account’s cases. This component isn’t going to win any awards for originality, but it will serve it’s purpose.


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.


Quick Deploy with Solenopsis

by Patrick Connelly posted on August 22, 2016

In Spring ‘15 Salesforce released a feature called “Quick Deploy” that allows you to only run a small subset of tests when you do your deployment instead of running all the tests. When you’re in an org like ours that running all tests can take upwards of 5hrs (or longer if the moon is aligned incorrectly) this is wonderful. Let’s take a look at how quick deploy works and how you can use quick deploy with Solenopsis.

How Quick Deploy Works

Quick deploy simply runs a provided list of tests when you run your deployment. This deployment is then staged under your Deployment Status in setup. Once the all the tests have run you’ll get a button that let’s you quick deploy.


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.


Getting Data Out of Salesforce

by Patrick Connelly posted on August 13, 2016

If you’ve been working with Salesforce for a while or you’re a larger company you’ll eventually want to get data out of Salesforce and into another system. So let’s take some time to break down the options that are available for getting data out of Salesforce in varying degrees of realtime.


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.


Opensource Update

by Patrick Connelly posted on July 28, 2016

This week is going to be just a social update on a couple of projects that I’m working on. I’ve got plans for a big neat post next week.

Me Code Pretty One Day…

I was hoping to present this at Dreamforce this year but it doesn’t look like that’s going to happen. So instead I’ll just talk briefly about it here

Apex StyleguideLink – I’ve been asked several times what our team does for it’s code style and I’ve been working on an online style guide. It’s really a work in progress and will probably pivot a bit once Apex Checkstyle is complete. Right now all the rules are enforced by regexes and it doesn’t scale well and has a lot of false positives. If you want to create your own styleguide, feel free to fork the project. I’ll add build instructions for the site soon to make this easier.

Apex CheckstyleLink – This has been something that’s been in the works for a while. Initially I tried to just make an extension to Checkstyle but there was just too many problems with that. So instead I completely forked Checkstyle and modified the grammar to help support Apex. While the project builds and it works on some very simple Apex code, it’s nowhere near ready for the big time. I’m going to keep working on it and hopefully someday soon it’ll be ready.

Other Projects

EscalationsLink – Another project still very much in it’s infancy. The idea behind this is to make an easy way for support centers to track escalations to cases. The plan is to have this both as a managed package as well as having the source available if you want to install it as unmanaged code.

SalesforceAppsLink – This is just a repo for random code that I’ve worked on that others may find useful. Right now I think the most useful bits are under the node_scripts directory.

Hands On TrainingLink – Training is in my blood and it’s something I’ve always loved doing. You should checkout my hands on training. I have plans to migrate some others over to it as well as writing a couple more. You can follow the project if you want to be notified of updates.


Solenopsis with XSLT

by Patrick Connelly posted on July 22, 2016

There’s a great feature we use all the time in Solenopsis that isn’t as documented as it should be. This is the ability to write an XSLT to apply to your objects at time of pull, push or both.


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.


SoapUI TLS 1.2

by Patrick Connelly posted on June 27, 2016

Soon, Salesforce will be requiring all connections to be TLS v1.1 or higher. This poses a problem for anyone using SoapUI with Java version 1.7 as that version of Java does not have TLS 1.1 or higher enabled by default. If you attempt to connect to an instance that has the “Require TLS 1.1 or higher for HTTPS connections” enabled you will get an error like the following

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sf="urn:fault.enterprise.soap.sforce.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soapenv:Body>
        <soapenv:Fault>
            <faultcode>sf:UNSUPPORTED_CLIENT</faultcode>
            <faultstring>UNSUPPORTED_CLIENT: TLS 1.0 has been disabled in this organization. Please use TLS 1.1 or higher when connecting to Salesforce using https.</faultstring>
            <detail>
                <sf:UnexpectedErrorFault xsi:type="sf:UnexpectedErrorFault">
                    <sf:exceptionCode>UNSUPPORTED_CLIENT</sf:exceptionCode>
                    <sf:exceptionMessage>TLS 1.0 has been disabled in this organization. Please use TLS 1.1 or higher when connecting to Salesforce using https.</sf:exceptionMessage>
                </sf:UnexpectedErrorFault>
            </detail>
        </soapenv:Fault>
    </soapenv:Body>
</soapenv:Envelope>

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"
        }
    ]
}

Clean REST Endpoints in Salesforce

by Patrick Connelly posted on June 13, 2016

One of the things I love working on are webservices. However, one of the things I dislike about using SOAP is that using the endpoint isn’t as nice as it could be. This is something that has been addressed by how REST endpoints are interacted with. By writing clean REST endpoints, your users can easily understand what is going on under the hood

Clean REST Endpoints

What do I mean by clean REST endpoints? Let’s take a look at two possible URIs and see which ones are cleaner and easier to understand. For the examples below, we are going to have two URIs, one to get a case by case number, and one to get it’s comments

#Get case using url parameter
curl "$SFDC_URL/services/apexrest/v1/cases?number=012345"

#Get case comments using url parameter
curl "$SFDC_URL/services/apexrest/v1/comments?number=012345"

#Get case using number in url
curl "$SFDC_URL/services/apexrest/v1/cases/012345"

#Get case comments using number in url
curl "$SFDC_URL/services/apexrest/v1/cases/012345/comments"

While the parameters are perfectly acceptable, they are not pretty. Also, it is difficult as a programmer to know if the param you have add to the URI is number, or casenumber or what. So instead if we have clean REST endpoints, we have the case number as part of the URI and it is just more logical as to knowing how to get a specific 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:


Entitlements Hands-on Training

by Patrick Connelly posted on June 02, 2016

At Dreamforce 2015, I wrote a hands-on training for Salesforce University and presented it both as a Dreamforce session, as well as recorded it for use on their site. I had a great time writing the content as well as delivering it in their studio. However, the problem is that the content is locked in place and the content isn’t 100% correct. Since publishing it, I’ve found some typos in the guide as well as some mistakes in time calculations. Because of this, I wanted to make the training available in a format that was easier to update as well as easier for people to report issues against.


Trailhead: Entitlement Management

by Patrick Connelly posted on May 23, 2016

It’s a pretty well known fact that I’m a big fan of Entitlement Management. I’ve given a Dreamforce talk, been recorded by SalesforceU, and even have a github repo for it (it’s a work in progress). So when I heard that the Trailhead team was releasing a new Entitlement Management module I was ecstatic.


Watermarking PDFs in Visualforce

by Patrick Connelly posted on May 09, 2016

Keeping on the PDF and Trailhead theme, lets take a look at adding watermarks to our PDFs. There was recently a developer boards post about watermarking a PDF and it dovetailed nicely into the previous posts.


Field Sets and Dynamic Visualforce

by Patrick Connelly posted on April 25, 2016

One of the downsides of the code I posted a couple of weeks ago to generate PDFs is that if you want to add new fields to your invoices, you have to edit the Visualforce page. By updating our Visualforce and using field sets, we can dynamically add fields to our invoices


PDF Attachment with Visualforce

by Patrick Connelly posted on April 18, 2016

After last weeks post, let’s take a look at how we can send a PDF attachment via a Visualforce email template. Our goal is to be able to automatically send an invoice to our customer whenever their Battle Station is fully operational. We will be taking the Battle Station Invoice PDF and making it something we can attach to an email and then create a workflow to send that email when the status changes to complete.


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


Trailhead: Navigate the Salesforce Advantage

by Patrick Connelly posted on February 22, 2016

Trailhead: Navigate the Salesforce Advantage

The Trailhead team released another set of fantastic modules this past week. But unlike many of the other modules, these delve into the world of Salesforce itself, and not really into Salesforce the product. Let’s take a look into each of these modules a bit deeper.


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.


SSL and Outbound Messaging

by Patrick Connelly posted on February 01, 2016

Recently I started setting up some Outbound Messaging to I needed to set up a blackhole (messaging sink) for messages to go to until we had stood up the real messaging endpoint. To host this I setup a simple nodejs service on our company’s externally available (but internally hosted) instance of Openshift. This service simply sends back the appropriate ACK for any XML that is POSTed to it.


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.


Salesforce and Fuse: Rolling your own ESB

by Patrick Connelly posted on January 19, 2016

There are lots of reasons why you would want to send data from Salesforce to a third party system. A simple example that comes to mind is to index your Salesforce data for external searching. Now, there are lots of 3rd party companies that you can do integration with, but most of these are externally hosted and do not give you the granular control that you may want or they may not give you access to your backend systems in a way you want.


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


Trailhead: Man your battle stations!

by Patrick Connelly posted on December 18, 2015

It’s no secret that I’m a huge Trailhead fan. I’ve written several posts about it. As much as I love Trailhead, I do find that the standard modules are a little tough for new people to see how it can be useful. That is where the Projects come in. The Trailhead Projects give you a goal and walk you through how to do something from start to finish, and in my opinion, it really helps to solidify how the platform can be used and what powerful things you can do without code.


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.


Coveralls: Code Coverage for Salesforce

by Patrick Connelly posted on August 23, 2015

When we started working on the Apex Lodash project we knew we wanted to publicly post our code coverage percentage. To do this we chose to use coveralls.io since it is free for open source projects.

Travis CI

Travis CI logo

In a previous post I talked about how to setup Travis CI to deploy your Salesforce code automatically. We will be updating the Travis CI configuration to push the testing results to coveralls.

Coveralls

Coveralls logo

There don’t seem to be too many options around for code coverage display on the Internet. Coveralls has lots of options for various coding languages and a pretty nice interface. Like Travis CI, Coveralls is free for open source projects and they do have paid options that supports private repositories. It does support several other CI platforms if you’re not using Travis CI.


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.


Travis CI and Salesforce

by Patrick Connelly posted on April 22, 2015

Recently I started working on a project that required a Salesforce CI build system. This has not been a problem for me in the past because I’ve always had a Jenkins host that was setup and maintained by our admins. However, this is a public facing project and I needed something that everyone contributing could have access to.

Travis CI

Travis CI Logo

I had heard of Travis CI before, but had never had a chance to look into it. Travis CI has most of the features that you would expect from any hosted CI solution, but where it drew me in was it’s pricing. It’s free. Well, it’s free if you’re using it for a open public project on GitHub (which I happen to be doing). They do have support for private GitHub repos, but you will have to pay to access them.

Solenopsis

Solenopsis Logo

Solenopsisis a project that Scot Floess and I have been working on for several years and it has been doing all of the deployment work for our team since it’s inception. Solenopsis is an extension of the Force.com Ant Migration tool that has a bunch of fancy Ant and Python scripts to help deploy code and manage all that pesky XML.

We’ll be using Solenopsis to deploy to Salesforce via Travis CI. While I use Solenopsis to pull data down and push it back up during development, there is no requirement on the end user using it in order to get the code in the repo. The only “requirement” is that is in the src directory so that we can use other directories to hold our build scripts and other build requirements. If you do use Solenopsis for personal it will make some things easier such as building out the .sfdcignore file which may be needed depending on your configuration.


Trailhead Modules: My Favorites

by Patrick Connelly posted on March 19, 2015

I’ve blogged previously about Trailhead and some of the new modules, but I thought I’d take the opportunity to write about two of the modules. Both the Change Management and Apex Testing are near and dear to my heart.


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.


Mobile SDK 3.1 released

by Patrick Connelly posted on February 13, 2015

At the end of last year, Salesforce released the Mobile SDK 3.0 which added quite a few new features. Now, they’ve released the Mobile SDK 3.1 with some really nice new features. I have not had a chance to dive into the Mobile SDK prior to this release, but I think it’s made some great progress and should be something to give a try of.

Background on the Mobile SDK

Mobile SDK Unified Cross Platform Architecture

The mobile SDK is a great way to write native apps for iOS, Android or hybrid apps using a number of web frameworks.

What’s new?

The updated SDK includes:

  • A more consistent implementation for native and hybrid apps for iOS and Android
  • Full CRUD operations for both online and offline usage
  • CocoaPods for iOS
  • Library updates

What can I do with this?

The updated mobile SDK makes it even easier now to get started with Android Studio and Gradle now being fully supported for native apps. To get started, checkout the Mobile SDK wiki page for the learning path you want to take. You can also take a look at the Android, iOS or Hybrid sample apps to get started.

Read the full announcement


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.


Displaying Salesforce Test Status in screen using JSforce

by Patrick Connelly posted on September 29, 2014

This post will probably only be useful to one other person out there, but it was a fun exercise and thought I’d at least share my output.

One of the biggest challenges I have when running tests is that I will often forget they are running and leave them completed for a while before I go back and remember I ran them. This mainly happens when I’m running an entire class worth of tests and have 5-10 minutes to kill. When first learned about JSforce and it’s cli capability I was in love! So I set out to make it so that the current testing status is displayed inside of my screen session. At the end of it all this is what I came up with:

Screen status


Why developers should go to Dreamforce, and how you should prepare.

by Patrick Connelly posted on August 08, 2014

With Dreamforce just around the corner, it seems appropriate to do my list of reasons why developers should go to this conference. Over the past couple of years, Salesforce has really stepped up their game in bringing more to the conference for developers. So, why should you go to Dreamforce (or why should you send your developers)?

  • Networking – This is my top reason. Yes all of the ones below are great reasons, but this is the one I still use long after my first Dreamforce. You get the chance to meet so many other developers and they are the ones you can lean on long after Dreamforce has packed up. Try to find people near you that you can sync back up with afterwards to get more involved. And there are plenty of social events you can join that don’t require you to think and can get you some exercise, such as the Community 5k or the Streaking to Dreamforce
  • Hands-on development – There are lots of opportunities at Dreamforce to get your hands on code and have someone there to help you if you get stuck.
  • Best practices – If you want to learn if you’re doing your Salesforce development right, this is the place to figure it out. There are lots of talks that go over the best way to do development with everything from handling bulk data, testing and even deployments.
  • Reid Carlberg – Ok, so maybe not just Reid, but folks like Reid who do neat stuff with technology. In 2013 there was the Connected Device Lab and it was fantastic. It’s a great way to learn about the Internet of Things. I can only assume that this year it will be even better!

So, now that you know you’re going what should you do to get ready?

  • Register – This is pretty obvious right? Well, go ahead and do it now so you’ll be ready when it’s time to sign up for talks
  • Be ready to sign up – Once the session list goes up, you should be ready to jump in. The really good sessions fill up fast. I’d recommend following @salesforce and @salesforcedevs on twitter for the best chance to see when it’s time.
  • Ask questions – Get on Chatter/Twitter/ and ask questions if you have them. Dreamforce is huge and can be quite daunting if it's your first time. There are plenty of fantastic people out there that can help you out.

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.


Using Git with Salesforce and distributed teams

by Patrick Connelly posted on July 21, 2014

Introduction

I’ve been asked several times (and have presented a couple of times) on how our team handles doing Continuous Integration (CI) and Continuous Deployment (CD) with a distributed team. However one of the points that I’m always asked is specifically how we use Software Configuration Management (SCM) with this processes. For this blog post I’m going to do a deep dive into our process.

NOTE: This process is by no means the end-all-be-all process for everyone. This is just what we have come up with (generalized for public consumption) over several years of developing on the Force.com platform


The best feature in Salesforce Summer '14

by Patrick Connelly posted on June 26, 2014

Ok, so it might not be the BEST feature ever, but it is a feature after my own heart.

If you’ve ever done anything with pricebooks, you know how painful they can be. And worst of all how you cannot create a Pricebook2 entry in a test. This means that you have to pull a Pricebook2 from your orgs data which means you have to enable the dreaded SeeAllData.

If you’ve ever seen my talk on testing, you’ll know how much I hate SeeAllData. Not only does it make your tests run slower it means that you’re not having a true test. Well, this is no more in Summer ‘14. With this release you should be able to create Pricebook2 entries without SeeAllData to your hearts content!

You can create price book entries for standard and custom price books in Apex tests.

Previously, you couldn’t create price book entries in an Apex test by default unless the test had access to organization data via the @isTest(SeeAllData=true) annotation. With this new support, you can isolate your price book test data from your organization data. Note that custom price books can be created but standard price books cannot.

Support for test price book entries is added for all tests, including tests that use the default data isolation mode (tests that can’t access organization data). With this support, you can do the following.

  • Query for the ID of the standard price book in your organization with the Test.getStandardPricebookId() method.
  • Create test price book entries with standard prices by using the standard price book ID that’s returned by Test.getStandardPricebookId().
  • Create test custom price books, which enables you to add price book entries with custom prices

If you want to read more about this and see examples, see page 257 of the summer release notes


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

Deleting all scheduled jobs in Salesforce with CasperJs

by Patrick Connelly posted on July 26, 2013

PREFACE

In a previous post, I talked about how to log in to Salesforce with CasperJs. At the time I did not have a good example of what to do next with it. Well, this week I had a need that is something that other people can relate to.

Casper Script

If you’ve ever done any Scheduled Apex work, then you know that if there are scheduled jobs for the class and you do a deployment, the deployment fails. To help negate this with automated installs I wrote the following CasperJs script does the following:

  1. Logs into Salesforce
  2. Navigates to the scheduled jobs page
  3. Gathers all the delete links for the jobs
  4. Deletes them
/*jslint browser: true, regexp: true */
/*global casper, require, jQuery*/

var BASE_URL, LOGIN_URL, LOGIN_USERNAME, LOGIN_PASSWORD, SCHEDULED_JOBS_URI, casp;

casp = require('casper').create({
     clientScripts: [
          'jquery.min.js'
     ],
     viewportSize: {
          width: 1024,
          height: 768
     },
     verbose: true,
     logLevel: 'info'
});

if (!casp.cli.has('username') && !casp.cli.has('password')) {
     casp.echo('Usage: $ casperjs deleteScheduledJobs.casper.js --username=USERNAME --password=PASSWORD [--prod]').exit(-1);
}

if (casp.cli.has('prod')) {
     LOGIN_URL = 'https://login.salesforce.com/';
} else {
     LOGIN_URL = 'https://test.salesforce.com/';
}

LOGIN_USERNAME = casp.cli.get('username');
LOGIN_PASSWORD = casp.cli.get('password');

SCHEDULED_JOBS_URI = '08e?setupid=ScheduledJobs';

casp.start(LOGIN_URL, function () {
     'use strict';

     this.log('Logging in', 'info');
     this.fill('form', {
          'username': LOGIN_USERNAME,
          'pw': LOGIN_PASSWORD
     }, true);

     this.log('Logged in', 'info');

     BASE_URL = casp.getCurrentUrl().split('.salesforce.com')[0] + '.salesforce.com/';

     casp.thenOpen(BASE_URL + SCHEDULED_JOBS_URI, function () {
          var deleteUrls;

          this.log('Fetching jobs to delete', 'info');

          deleteUrls = this.evaluate(function () {
               var urls, url;
               urls = [];

               jQuery('table.list tr.dataRow').each(function (i, item) {
                    url = {};
                    url.href = jQuery('td.actionColumn a.actionLink', item).attr('href').substring(1);
                    url.name = jQuery('th', item).html();
                    urls.push(url);
               });

               return urls;
          });

          this.each(deleteUrls, function (self, url) {
               this.log('Deleting "' + url.name + '"', 'info');
               self.thenOpen(BASE_URL + url.href, function () {
                    this.log('"' + url.name + '" deleted', 'info');
               }, function () {
                    this.log('Timed out deleting "' + url.name + '"', 'error');
               });
          });
     });
});

casp.run();

Then we can run it like all other CasperJs scripts

casperjs deleteScheduleJobs.casper.js --username=USERNAME --password=PASSWORD [--prod]

Logging into Salesforce with CasperJs

by Patrick Connelly posted on July 09, 2013

Preface

Anyone that has ever had to deal with editing multiple Entitlement Processes in Salesforce will know the pain of having to do this in multiple environments and making sure you don’t fat finger this manual process. In the past when I’ve had to do this, I’ve either sucked it up and did it manually, or did it with Selenium. I wasn’t a big fan of either of these solutions since I’m a command-line kinda guy. That’s when I was told about CasperJs and I think I’m in love.

CasperJs

CasperJs is a framework built on top of PhantomJs, and allows you to write JavaScript to web automation. Like with all Salesforce tasks, logging in is the first thing you need to do. Let’s take a look at the sfdclogin.casper.js.

/*jslint browser: true, regexp: true */
/*global casper, require */

var LOGIN_URL, LOGIN_USERNAME, LOGIN_PASSWORD, casp;

casp = require('casper').create({
     viewportSize: {
          width: 1024,
          height: 768
     },
     verbose: true,
     logLevel: 'warning'
});

if (!casp.cli.has('username') && !casp.cli.has('password')) {
     casp.echo('Usage: $ casperjs sfdclogin.casper.js --username=USERNAME --password=PASSWORD [--prod]').exit(-1);
}

if (casp.cli.has('prod')) {
     LOGIN_URL = 'https://login.salesforce.com/';
} else {
     LOGIN_URL = 'https://test.salesforce.com/';
}

LOGIN_USERNAME = casp.cli.get('username');
LOGIN_PASSWORD = casp.cli.get('password');

casp.start(LOGIN_URL, function () {
     'use strict';

     this.log('Logging in', 'debug');
     this.fill('form', {
          'username': LOGIN_USERNAME,
          'pw': LOGIN_PASSWORD
     }, true);

     this.log('Logged in', 'debug');
});

casp.then(function () {
     'use strict';

     this.echo('We\'re logged in.  Now we can do more stuff like take a screenshot!');

     this.waitForSelector('#userNavLabel', function () {
          this.captureSelector('test.png', 'html');
          this.log('saved screenshot of ' + this.getCurrentUrl() + 'to test.png', 'warning');
     }, function () {
          this.die('Timeout reached');
          this.exit();
     }, 12000);
});

casp.run();

To run this class we simply do

casperjs sfdclogin.casper.js --username=USERNAME --password=PASSWORD [--prod]

This JavaScript is pretty simple, but it gives us a base to build on top of. We first setup our CasperJs instance with our screen size, the verbosity and the log level. Then we get our parameters from the command-line for username and password, this allows us to not store these inside the js file. We then fill in the login form and submit it. Now we’re ready to do some actual work. In the above js file, all we are doing is taking a simple screenshot of the page, but we could do any number of things from the CaseperJs documentation.


Nulling fields in Salesforce with SoapUI

by Patrick Connelly posted on August 26, 2012

The Problem

The other day I came across a problem where sending in a blank field to Salesforce via SOAP was not nulling out the field. Instead, the enterprise WSDL was treating this as if nothing was sent, and therefore not updating the field at all. This make sense. If you were to send a sparse data structure over with only fields you want to update, you wouldn’t want to either have to provide the current value of every field or have them all nulled out. So, how do you null out a field with SOAP via the enterprise (or partner) WSDL in Salesforce?

The Solution

This is input is formatted for SoapUI, it may differ depending on the client you are using to send the SOAP message. The key take away is fieldToNull urn.

Lets start with a simple example of updating a field via the Enterprise WSDL

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:enterprise.soap.sforce.com" xmlns:urn1="urn:sobject.enterprise.soap.sforce.com">
   <soapenv:Header>
      <urn:SessionHeader>
         <urn:sessionId>${#Project#sessionid}</urn:sessionId>
      </urn:SessionHeader>
   </soapenv:Header>
   <soapenv:Body>
      <urn:update>
         <!--Zero or more repetitions:-->
         <urn:sObjects xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Contact">
               <urn:Id>${#Project#contactid}</urn:Id>
               <urn:CustomField__c>Yay! Data</urn:CustomField__c>
         </urn:sObjects>
      </urn:update>
   </soapenv:Body>
</soapenv:Envelope>

This will set the CustomField__c on the Contact to “Yay! Data”

To null out this field we simply send the field name as part of the fieldsToNull list

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:enterprise.soap.sforce.com" xmlns:urn1="urn:sobject.enterprise.soap.sforce.com">
   <soapenv:Header>
      <urn:SessionHeader>
         <urn:sessionId>${#Project#sessionid}</urn:sessionId>
      </urn:SessionHeader>
   </soapenv:Header>
   <soapenv:Body>
      <urn:update>
         <!--Zero or more repetitions:-->
         <urn:sObjects xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Contact">
               <urn:Id>${#Project#contactid}</urn:Id>
               <urn:fieldsToNull>CustomField__c</urn:fieldsToNull>
         </urn:sObjects>
      </urn:update>
   </soapenv:Body>
</soapenv:Envelope>

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


Vim and Salesforce development

by Patrick Connelly posted on February 09, 2012

Since I switched over to using vim as my primary mode of Salesforce development, I’ve been asked several times how I’ve configured vim. Well, it’s about time I show the man behind the curtain. My primary vim config file is quite large now, but I’ve condensed it down to the parts that I think are most pertinent to Salesforce development.

Highlighting

Now vim is great for editing but where I think it shines the most is in highlighting. I’ve taken the standard java vim file and have modified it for use with the Apex language. To use it, download the apex.vim file and place it in your syntax directory for vim.

Local

To make it work for just your user you can place the file in ~/.vim/syntax/ but you will need to also symlink (or copy) the html.vim file into that directory.

ln -s /usr/share/vim/vim73/syntax/html.vim ~/.vim/syntax/html.vim

Global

To make it work for all users on the system you can just place the file into your global syntax directory. For fedora and probably most unix systems it is /usr/share/vim/vim73/syntax/

.vimrc

Now that we’ve got highlighting installed, lets get vim to use it. First we need to create our backup and swap directories. We do this to keep extra files out of our Salesforce directory so that we don’t try to deploy them (or commit them to our repo).

mkdir ~/.bak ~/.swp

Now we can add / replace the following options into our .vimrc file

You might need to edit the values for tabstop, shiftwidth and softtabstop for your coding standards but 4 is what we use.


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

Salesforce.com and Subversion

by Patrick Connelly posted on April 29, 2009

Our team has since switch to git. For more information read my article on our git workflow

From what I’ve been able to tell, there is no real version control built into Salesforce.com and this is a problem when pushing from a sandbox instance into a production instance. To fix this problem (at least until Salesforce does something), I think the best option is to use the Force.com plugin and the Subclipse plugin for Eclipse. With both of these in place, it should make version control a reality.

  1. Install Eclipse for your platform (it’s eclipse-platform if you are using Fedora)
  2. Install both the Force.com and Subclipse plugin (eclipse-subclipse)
  3. Add your Force.com project to Eclipse (Howto)
  4. Add your SVN repo to Eclipse. (Howto)
  5. Share your Force.com project (Right-click on Project name → Team → Share Project → SVN → Choose repo)
  6. Then after updating a file in the Force.com project, commit the update to SVN before deploying to the server

Now if you want to use this in another Eclipse instance then, you’ll want to do the first two steps to prepare your Eclipse environment. Then:

  1. Add the existing SVN repo to Eclipse (Howto)
  2. Right click on the Project Force.com → Project Properties and update the username / password

When using this in a collaborative setting, the following workflow should be followed whenever possible.

  1. Team → Update
  2. Make changes to code
  3. Team → Update
  4. Make changes to resolve collisions if needed
  5. Team → Commit
  6. Force.com → Deploy to Server