Creating Web-services in Salesforce

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.

Web services development on Salesforce

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 exterally 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 aUnknownCaseException

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<Object> 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
This entry was posted in Computers, Development, Salesforce and tagged , , , . Bookmark the permalink.
  • Pingback: Salesforce and soapUI – Testing WebServices directly » Deadlypenguin()

  • Newbie

    Hi Patrick, I hope all is well and thank you for sharing the information. We have a third party system that will be sending us SOAP messages when an issue occurs on their end. We’re supposed to catch those messages, parse them, and then create a case for them. They will need us to priovide an IP address and a port number.

    I’m new to this so bare with me 🙂 Reading and learning online, I created the following class in my Dev Org:

    global with sharing class SOAPCaseController
    {

    webservice static void createNewCase(String eventFlag)
    {
    Case c = new Case();
    c.OwnerId = ‘005i0000001uqEm’;
    c.AccountId = ‘001i000000RsOOS’;
    c.Subject = ‘SOAP Test – ‘ + eventFlag;
    c.Status = ‘New’;
    insert c;
    return;
    }

    }

    //Simple start.

    I’m not sure about the next steps. I’ve been told different things that I’m getting lost on like:

    – You need to authenticate, receive a session ID, and an API URL.

    I’m looking for steps on how I should proceed 🙂 I want to learn and do it myself but I can’t find a clear set of instructions on how I can accomplish the requested functionality. Any help is much appreciated, thank you in advance.

  • I’d take a look at my article about testing webservices [1]. That should get you started.

    [1] http://blog.deadlypenguin.com/blog/2012/02/03/salesforce-and-soapui/

  • Pingback: Web services development on Salesforce » Deadlypenguin()

  • Deepak Malkani

    use this code. this should help you.

    global with sharing class SOAPCaseController
    {

    global class CaseObj {

    webservice String OwnerId;
    webservice String AccountId;
    webservice String caseSubject;
    webservice String caseStatus;
    }

    webservice static List createNewCases(List csObjList){

    List cases = new List();
    for(Integer i=0; i<csObjList.Size(); i++){
    Case cs = new Case();
    cs.OwnerId = csObjList[i].OwnerId;
    cs.Status = csObjList[i].Status;
    cs.Subject = csObjList[i].Subject;
    cs.AccountId = csObjList[i].AccountId;
    cases.add(cs);
    }

    if(!cases.isEmpty())
    insert cases;
    return cases;
    }

  • Kenneth Ray

    Thanks for the post! However, I do have a question. I’m using custom Web Service, how do I obtain the SessionId? I’ve generated the WSDL and loaded it into SoapUI but I keep getting an “INVALID_SESSION_ID” error.

  • If you take a look over this other post [1] I cover how to setup SoapUI and get generate the session id.

    [1] http://blog.deadlypenguin.com/blog/2012/02/03/salesforce-and-soapui/