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

Using meld with git diff

by Patrick Connelly posted on May 03, 2011

This is test

Syncing saved games between Windows / Mac / Linux with Dropbox

by Patrick Connelly posted on May 20, 2010

So with steam coming out on the Mac and with the Humble Indie Bundle working on all three, there is a problem with keeping all of your saves in sync. Not any more. This is all thanks to dropbox.

What is dropbox?

Dropbox is a cross-platform application / website that keeps files in sync and gives you 2Gb of storage space for free. If you’re not a dropbox user already, you can sign up here.

Initial setup

The initial setup is the tricky part. Fortunately you only need to install something (other than dropbox) on one system and only if you’re running Windows XP.

Windows XP

You’ll need to install junction to make the symlinks in Windows XP. In Vista and later you can use mklink

Linux / OSX

You’ll use the ln command

After you have installed your game you will need to move your save game directory into your dropbox and then link to it. For this example, I’ll be using Civ 4. In the examples below, I’m assuming you’ve already moved your files into Dropbox/games/

Windows

junction "C:\Documents and Settings\User\My Documents\My Games\Sid Meier's Civilization IV\replay" C:\Documents and Settings\User\My Documents\My Dropbox\games\civ4"

Linux / OSX

ln -s "~/Documents/Sid Meier\'s Civilization IV/replay" "~/My Dropbox/games/civ4"

Automatic backups with UDEV

by Patrick Connelly posted on September 25, 2009

I recently challenged myself to come up with a way to make udev automatically backup when you plug in a USB harddrive. I did all my testing with a USB stick drive, but since they both show up as block devices to the kernel, it shouldn’t matter.

UDEV Rules

To start with, we need to set up static naming for the storage device that you want to make into backup disk. Start by plugging in the disk. (Now I’m not using Gnome or KDE so I’m not sure what their automounter will do. So, you might have to find a way to exclude it from the automounter. We need to find out the “model” of the drive. My udev rules are pretty basic, and will work since most people don’t have more than one the same model of USB drive laying around that they would use. You can always modify the udev rules to work for you.

udevadm info -a -p /sys/block/sdc | grep model

Here we are looking at the block device sdc (which is what the kernel named it since we don’t have any udev rules yet). This could change depending on how many block devices you currently have. Now we take this information, and feed it into a udev rule. I created a file /etc/udev/rules.d/50-backup.rules The name isn’t really important, however, the number 50- is. That is the order in which it runs. We want that number to be less than 90 so that hal doesn’t run first. Inside that file, we have the following:

KERNEL=="sd?1″, SUBSYSTEM=="block", ATTRS{model}=="MODEL GOES HERE", SYMLINK+="backup", RUN+="/usr/local/bin/backup.sh"

Replace “MODEL GOES HERE” with the output from the udevadm command

The backup script

Now we udev running our script /usr/local/bin/backup.sh we need to make that script

#!/bin/bash

NOTIFYUSER="pcon"
MAINDIR="/home/pcon/"
BACKUPDIR="/mnt/backup"

su $NOTIFYUSER alt-notify-send backup "Waiting for things to settle" 0
sleep 5

su $NOTIFYUSER alt-notify-send backup "Starting backup" 0
echo "$(date) - Mounting /dev/backup to $BACKUPDIR" > /tmp/backup.log
mount /dev/backup $BACKUPDIR >> /tmp/backup.log 2>&1
echo "$(date) - Staring rsync of $MAINDIR to $BACKUPDIR" >> /tmp/backup.log
rsync -arvuz --inplace --delete $MAINDIR $BACKUPDIR >> /tmp/backup.log 2>&1
echo "$(date) - Mounting /dev/backup to $BACKUPDIR" >> /tmp/backup.log
umount $BACKUPDIR >> /tmp/backup.log 2>&1
su $NOTIFYUSER alt-notify-send backup "Backup completed" 0

We have a couple of things to setup here. First we need to create /mnt/backup as root, and fill out the other variables in the top of the script. Also, if we want notification in gnome, we need to make a notify-send work around. Put the following in /usr/local/bin/alt-notify-send

#!/bin/sh
user=`whoami`
pids=`pgrep -u $user gnome-panel`
title=$1
text=$2
timeout=$3

if [ -z "$title" ]; then
    echo You need to give me a title >&2
    exit 1
fi
if [ -z "$text" ]; then
     text=$title
fi
if [ -z "$timeout" ]; then
     timeout=60000
fi

for pid in $pids; do
    # find DBUS session bus for this session
    DBUS_SESSION_BUS_ADDRESS=`grep -z DBUS_SESSION_BUS_ADDRESS \
    /proc/$pid/environ | sed -e 's/DBUS_SESSION_BUS_ADDRESS=//'`
    # use it
    DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS \
    notify-send -u low -t $timeout "$title" "$text"
done

Now chmod +x the two scripts, and everything should be good to go.


External programs that update screen

by Patrick Connelly posted on September 18, 2009

Screen is a great tool, and it allows you do to alot of neat things. One of my favorites is binding commands to key strokes. So all you have to do is hit F5 and it will start something in the background. Such as a build command. The problem is, you either get no output, or you get spam all over your screen. Well I’ve finally found a way around that. The answer lies in ANSI Privacy Messages.

In your .screenrc, make sure you have a place that will show messages. If you start up screen and you see “New screen…” then you’ve got this. Next add your script to your .screenrc

bind -k k5 exec /home/pcon/bin/build_script.sh

Now everything in your screen is ready to go. Now, on to build_script.sh

#!/bin/bash

echo -n -e "\033^Starting Build\033\\"

# Do something here

echo -n -e "\033^Ending Build\033\\"

That’s it. Now your screen will display “Starting Build” and “Ending Build” on your display. If the stuff in between happens too fast, you may only see your last message. The key thing is that your message has to start with \033^ and end with \033\\ otherwise you’ll lose your cursor. And you have to have the -e on the echo so that it will interpret the octal codes correctly.


irssi + mumbles == push notification goodness

by Patrick Connelly posted on August 31, 2009

One of the biggest problems with irssi is that if you run it on remote machine, it can be quite hard to get notifications. For the past couple of years, I’ve been running a plugin called fnotify that writes notifications to a file, then using another script I read that file and print it out with libnotify. There are a couple of problems with this:

  1. libnotify is ugly
  2. takes up diskspace if you don’t clear the queue
  3. requires you to either have the script, or remember the ridiculously long command

Well, these are things of the past. Thanks to mumbles!

First install mumbles from yum (or source) then install the irssi script. Make sure you change the growl_server and growl_password then you are good to go. The script has a dependency on Net::GrowlNotify in perl.

The script uses irssi config variables so you can use /SET growl_server or /SET growl_password to set your growl server/password without having to load/unload the script.


DVD player with xsessions

by Patrick Connelly posted on June 12, 2009

I’ve come across the need to simply the dvd playing process. I’m having to set up a laptop to play a dvd and use a remote presenter control. Now in the past I’ve just been in charge of this setup, and haven’t had to worry about explaining how to start it up for others. This time, I need to make it as user friendly as possible. So, I’ve decided to do this with a couple of bash scripts and a couple of xsessions.

Goals

  • Generic user with a generic password to hand to the person in charge
  • Ability to play dvd stored locally. (Called presentation_dvd)
  • Ability to play any dvd inserted.
  • Require no user input except to choose presentation_dvd or dvd

Preperation

To get ready, we need to do a couple of things

  • Create a presenter user
  • Install xine and xine-lib-extras-freeworld
  • Copy our presentation_dvd to an iso
    dd if=/dev/dvd of=/home/presenter/presentation_dvd.iso
    

Xesssions

Xsessions are what defines your window manager. It’s what tells X11 what to run when you say Session->Gnome or Session->fluxbox. These files are stored in /usr/share/xsessions.

[Desktop Entry]
Encoding=UTF-8
Name=Presentation_DVD
Comment=Start the presentation DVD
Exec=/usr/local/bin/presentation_dvd
Terminal=False

[Window Manager]
SessionManaged=true

This is our file in /usr/share/xesssions/presentation_dvd.desktop We then create one in /usr/share/xesssions/dvd.desktop and replace presentation_dvd with dvd.

The Scripts

Our /usr/local/bin/presentation_dvd looks like this:

#!bin/bash
amixer set Master playback 100%
xine -f -g --no-splash dvd:/home/presenter/presentation_dvd.iso

This will turn the volume up to 100% and then start xine on the iso. To exit, just right click and say exit. This will take you back to the login screen.

Now to handle any dvd with the /usr/local/bin/dvd

#!/bin/bash
amixer set Master playback 100%
xine -f -g --no-splash dvd://

And the final touch, make them both executable

chmod a+x /usr/local/bin/dvd /usr/local/bin/presentation_dvd

Usage

From the login menu, choose your presenter user, and then choose the appropriate session at the bottom. Then type in the password. Like magic, everything should work.

Potential problems

If you don’t see your session in the list, you might have a typo in your xsession file

If one of the xine scripts don’t work, try logging into gnome and running the script from the command-line to see why.


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

Mutt and Lynx

by Patrick Connelly posted on April 21, 2009

So, in my time with mutt, I have grown to have a disdain for people that send HTML only email. And surprisingly, this happens alot! So, instead of trying to change the world, I’ve decided to just use mutt and lynx to my advantage and call it a day. Thanks to one of my co-workers for showing me how to do this.

At the end of your ~/.mailcap file, add the following

text/html; lynx -dump -width=78 -nolist %s | sed ‘s/^   //’; copiousoutput; needsterminal; nametemplate=%s.html

Then, in the ~/.muttrc add

auto_view text/x-vcard text/html text/enriched

And restart mutt. This will use lynx to render the email. You can substitute lynx for any text-based html browser you’d like.