Monday, June 3, 2013

QT012: Calling Apex Web Services from IBM Cast Iron

Quick Tip #012: Calling Apex Web Services from IBM Cast Iron

The standard interface between Cast Iron and is the the Salesforce SOAP API.  The SOAP API provides standard CRUD operators that would with all standard and custom objects in  This is a powerful and robust interface, however, you may want to encapsulate complex business logic within salesforce as you might find in a database stored procedure.  This is possible to accomplish using Apex Web Services.

Exposing Apex Web Services with Salesforce allows you to expose your own custom web services using the Apex Programming Language.  Method declarations in apex prefixed with the webservice keyword will be exposed as operations in an Apex Webservice.  Webservice methods must be declared as static methods within a global class.  

global class MyWebService{
 webservice static String getName(Id id){
  Account a = [select Name from Account WHERE id=:id];
  return a.Name;

Any static method declared within a gobal class with the webservice keyword will be exposed as a webservice, to generate a WSDL for the class navigate to the class page under the setup screen in SFDC and click the Generate WSDL button.  The generated WSDL will contain the definition for all web service methods in your class. 

Can I Use Complex Types in an Apex Web Service?

You can define complex data structures to pass to and return from your web service operations by defining a global class to contain the data and declaring the fields of your class with the web service keyword.
global class MyReturnParams{
 webservice Id id;
 webservice String message;

Calling Apex Web Services from Cast Iron

Once you have created your Apex Web Service and downloaded the WSDL, you can import the WSDL into Cast Iron Studio and create a Web Service Endpoint.

You are now ready to add your invoke Webservice Activity to your orchestration.

What About Authentication? Web Services uses a proprietary authentication handshake to get a token which must be passed to your Apex Web Service.  These tokens can get stale and expire, so to avoid building logic to deal with this, we will let Cast Iron do it for us.  CIOS has built in logic to maintain a pool of sessions with SFDC so we will leverage the SFDC Connector to get a token that we can pass to our Web Service.  To do this, we will need a endpoint and we will need to create an Activity to interact with SFDC and get a SessionHeader.  Any activity will do, so we will use a simple get Server Timestamp call to Salesforce.  If you have used the SFDC connector before you may have noticed that the connector returns the session header that it used to make the call to SFDC.  You will need to copy this header and pass it in to your Apex Webservice call.  You will also need to capture the server URL that is returned and use it to construct the appropriate URL for your WSDL.  Because server urls can change between environments and may change over time, it is a good idea not to hard code the URL of your instance and instead use the one that SFDC returns.  To do this you will need to write a simple JavaScript to parse the instance of your organization and use that to build the URL to pass to the location optional parameter of your invoke web service activity.

There are a few other required parameters that you will need to pass to various headers in the web service call.  To see the headers, right click the target side of your Map Inputs step on the invoke WebService Activity and choose show optional parameters.  Here is a list of the required parameters and what they do:
  • headers/SessionHeader/SessionId: This is where you will map the session id from the get Server Timestamp activity.
  • headers/DebuggingHeader/DebugLevel:  This field determines how much debugging info SFDC will return to your call.  For production this value should be None, as there is a governor limit for returning debugging details.  You want to avoid exceeding the limit on calls that do not need to be debugged so you can actually get debugging info when necessary.
  • headers/AllowFieldTruncationHeader/allowFieldTruncation:  This field defines the default behavior for the Database.DMLOptions allowFieldTruncation property.  Prior to version 15.0 SFDC would truncate strings when their value exceeded the size of the field.  This behavior was changed in version 15.0 to default to throwing an error when a string exceeds the field length.  This parameter allows you to specify the previous behavior as the default.  I believe that this parameter will not override the property if it is specified in your apex code.
Note: It appears that recent versions of SFDC now have a Security header which allows you to specify a username and password for authentication.  This option could be used instead of the traditional method of obtaining a session header.  I have never used this method, but it seems that there are some trade offs to consider here.  If you use the above method, you actually make two calls to SFDC one to get a sessionId and another to invoke the web service.  (However, any call to SFDC will return the header, and I often find that I can get the session header from another call within an orchestration such as a query that must be done before the invoke web service)  Specifying a username and password would allow you do everything in one step, however, you would be authenticating for each call to SFDC which can be an expensive operation in itself.  Also, the above method uses SFDC to retrieve the appropriate server URL from the login server.  Without that step you would have to hard code the server, which could change if SFDC moves your instance. provides plenty of warning when they do make changes, so that may not be a major concern.  More investigation in needed to determine if the security header provides a cleaner solution to this problem.