Intercepting Workflow Outbound Messages in a Ruby Server

Using workflow, I've just got a Ruby server intercepting SOAP messages that are sent via the Force.com workflow system when changes are made to an object.

I’m learning about workflow and approvals, and I’ve just got a Ruby server intercepting SOAP messages that are sent via the Force.com workflow system when changes are made to an object.

The Basic Idea

The way I see it is that you can use the Force.com Workflow system to carry out actions under certain conditions on particular objects. So for example, if object Y has its field X set to Z then perform action Q.

The conditions I chose were on the Contact object, with an evaluation criteria of “Every time a record is created or edited.” The action I chose was what this blog post is all about: an outbound message. Essentially you can have the Force.com server send out a SOAP message to your destination of choice with data.

This is very powerful functionality, and takes 3 minutes to set up. You can imagine using it for integration between Force.com and some other external system. You can also perform simpler actions, like updating fields, sending emails and so on. All of this happens automatically, and the actions are managed by the server.

Here’s how I set this up to send a SOAP message to a Ruby server sitting on my own remote site.

Setting up the Workflow

Go to Setup/Workflow & Approvals/Workflow Rules/New Rule. Select the Contact object, give the rule a name such as “ServerPingChange”, set up some evaluation criteria (I chose “Every time a record is created or edited”) and a Rule Criteria (I set mine to “Formula evaluates to true” and have a formula of “true”). Hit “Save and Next” and “Done”.

That’s it. As you can see, you have a lot of control over the conditions under which the workflow rule will be selected. Now let’s go ahead and create the action, which are reusable. That is, if we create an action for Rule Y we can also use it for a different rule too.

Setting up the Action

Outbound Message_ MyOutboundMsg ~ Salesforce - Developer Edition.jpg Hit “Edit” under “Workflow Actions” for the workflow rule you just created, then “Add” “Outbound Message”. I gave it a name of “MyOutboundMsg” and for endpoint address you need to select your server name. For example, I used http://www.jonmountjoy.com:8080/ (Don’t use my server please 😉 ). You can then select which fields you want to send along in the message. I simply chose Id and Lastname.

That’s it! You’ll now see a cool “Click for WSDL” which you’ll want to do. Download that WSDL file – that defines what your SOAP server endpoint needs to look like. You’ll want to activate your workflow rule now (hit “Activate” on the rule), and set up your security now in Security Controls/RemoteSites to ensure that your remote server has access to Force.com.

Now whenever you add/modify a contact, a SOAP message will be sent to your endpoint.

Monitor

You can check your progress so far. Go ahead and edit a contact for example. Now go to Setup/Monitoring/OutboundMessages. You’ll see a log of outbound messages because, of course, at this point you have nothing listening on the other end.

Outbound Messaging Delivery Status ~ Salesforce - Developer Edition.jpg

Setting up your Ruby Server

I chose to use Ruby here. (I’ll be trying this some day with Java and the Spring Framework if there’s any interest.) Here’s how I set up my Ruby server. It’s somewhat convoluted as I had to set up a private gem home as my server is hosted and I don’t have full control over it. Hopefully this will help folk doing the same.

Modify your .profile to accommodate a location for your gems if your server is hosted. I have mine include the following lines:

export GEM_HOME=~/ruby/gems/
export RUBYOPT=rubygems

Then I installed the soap4r gem, which provides the basis for my SOAP server. I did this by running

gem install soap4r

(Is there a better SOAP server out there for Ruby? This one looks pretty stale, although it works for my purposes. )

Now in a directory in which you have the WSDL downloaded from the previous step, execute:

~/ruby/gems/bin/wsdl2ruby.rb --wsdl wsdl --type server

You should now have a basic SOAP server! Let’s tweak:

I modified NotificationService.rb like so, so that it listens on the correct port (the line is near the bottom of the file):

server = NotificationPortApp.new('app', nil, '0.0.0.0', 8080)

I added a line to DefaultMappingRegistry.rb so that it starts:

require 'default.rb'
gem 'soap4r'
require 'soap/mapping'

Unfortunately it took me an exceedingly long time to figure out that piece of magic. Why I need, I have no idea…

Now you can start hacking the piece that really matters, defaultServant.rb, which is the Ruby code that runs when a message is received. The soap4r gem makes it pretty simple to interact with the SOAP. Here’s my final code that simply prints the incoming id and lastname:

def notifications(request)
p "Jack was here"
p [request.notification[0].sObject.id]
p [request.notification[0].sObject.lastName]
ackResponse = NotificationsResponse.new
ackResponse.ack = true
return ackResponse
end

The only tricky bit is ensuring that you create and return an ackResponse object. Without this, you’ll receive the message but Force.com will keep resending it because it hasn’t received a successful acknowledgement response.

Finally, run your server:

ruby NotificationService.rb

That’s it! Here’s the output I get whenever I modify the contact Tim Barr:

mountjoyj@sobek:~/oof$ ruby NotificationService.rb
"Jon's Workflow Outbound Message Server Received:"
["0035000000N1GwjAAF"]
["Barr"]

Summary

I found outbound messaging pretty straightforward and easy to use. It took 3 minutes to set up the workflow rule, criteria and SOAP message, and I had great fun pulling my hair out getting the Ruby server to run 🙂

Have fun!

History

I started learning this stuff as I was going to give part of the Workflow talk at Tour de Force in Dublin. Rick Greenwald ended up giving the entire presentation, thankfully. I don’t know enough yet, and Rick knows it all. Thanks Rick!

Technorati Tags:
, , ,

Published
July 8, 2008
Topics:

Leave your comments...

Intercepting Workflow Outbound Messages in a Ruby Server