Using SoapUI to make Salesforce Marketing Cloud API calls
This tutorial shows how to make SOAP requests to Salesforce' Marketing Cloud API using the open source version of SmartBear's SoapUI. The feedback that SoapUI provides is very helpful in figuring out the correct SOAP request format for each action desired to run. SOAP request envelopes created within SoapUI can be easily saved for later reuse, allowing you to bypass the sometimes cumbersome Email Studio for often-run actions. Also, knowledge of the correct SOAP requests and SOAP responses returned helps speed up development for accessing the API via programmatic means, for example as shown in my Salesforce/Apache CXF tutorial. As with that tutorial, I'll be demonstrating creation of an email data folder, a simple task that provides an easy way to confirm connectivity and authentication before moving on to more complex activities.
Download SoapUI if you haven't already. Free open source version will do.
Import the Marketing Cloud WSDL into a new SoapUI project. Select SoapUI menu item File | New SOAP Project. A New SOAP Project popup will appear (see illustration below.) Choose whatever project name desired. For the Initial WSDL, that can be retrieved from the Salesforce Marketing Cloud (SFMC) WSDL Links page. Choose the WSDL appropriate for the SF instance that you are using: S1, S4, S6, or S7 -- the illustration below shows S1 which may or may not be the correct one for your project. Contact SF customer support if you are uncertain which SFMC instance you are using.
Good to check "Create Requests" as shown above, although this functionality is less useful here than for other web services. SFMC uses generic SOAP operations like Create and Retrieve that hold for dozens of objects instead of specific ones such as CreateXXX, RetrieveYYY, etc. resulting in unworkably large sample SOAP requests to handle the many objects these methods can be applied to.
Configure Username Token Authentication for the SOAP calls. This need be configured only once for all SOAP calls. SoapUI provides efficient documentation for configuring WS-Security, of which SFMC uses the UsernameToken type. To configure, select menu item Project | Show Project View and select the WS-Security Configurations tab from the resulting popup. The (anonymized) settings below are what I configured for my own calls to work, make sure you also have the configuration as given in the bottom half of the illustration. The "Name" field at the top of the illustration can be whatever you want, it is used to identify the security properties desired for any particular SOAP call. The username and password can be what you use to log into Email Studio or can be a new account used specifically for SOAP calls.
Create the SOAP request envelope. General process:
Clone the sample request provided by SoapUI. Creating a clone allows you customize the sample SOAP call to something specific for your needs, while allowing the sample SOAP call to remain as-is so you can clone it again to perform a different action. To clone, right-click the sample request, select "Clone Request" and give the clone a useful name (say "CreateDataFolder"). You'll see it created next to the original sample request. Double-click the cloned request to bring it up in the editor window.
Configure the UsernameToken for the call. In the editor window for the CreateDataFolder call, select the Auth button in the lower-left corner, choose Basic Authentication, leave the basic auth username and password blank, and for Outgoing WSS select the name of the UsernameToken authentication you configured earlier (see illustration).
Check the SFMC documentation to help determine the required SOAP request format for the desired action. For each action, some trial and error can be expected to figure out the correct call. SoapUI excels at providing pre-call validation and rapid SOAP responses helpful for getting the calls right. The best first step is to check the documentation page for the specific SFMC object you're working with, in this case it would be the Data Folder page (note the other objects listed on the left-side menu in case you're working with something else.) You'll get a reasonably accurate listing of properties that can be defined and the types of actions (Create, Retrieve, etc.) permissible on the object. In the case of the Data Folder and some other objects, the bottom of the page gives a link to sample SOAP requests which I've not found to provide everything that's needed but a good starting step. In the case of creating data folders, I've found the description field to be required (or an unclear error response is given), the
xmlns:xsi namespace needed to be added to the soap:envelope and a Client element for your project's MemberID needed. You'll also need to determine the ID of the parent folder for the new folder you're creating, one way to obtain this is to hover over the parent directory with the mouse in Email Studio and reading the "cid" value given in the tooltip popup at the bottom of your browser while doing so. The following is the format that worked for me to create the data folder:
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:par="http://exacttarget.com/wsdl/partnerAPI"> <soapenv:Body> <par:CreateRequest> <par:Options/> <par:Objects xsi:type="par:DataFolder"> <par:Client> <par:ClientID>...yourMID#...</par:ClientID> </par:Client> <par:ModifiedDate xsi:nil="true"/> <par:ObjectID xsi:nil="true"/> <par:ParentFolder> <par:ModifiedDate xsi:nil="true"/> <par:ID>...ParentFolderID#...</par:ID> <par:ObjectID xsi:nil="true"/> </par:ParentFolder> <par:Name>emailFolderViaSoapUI</par:Name> <par:Description>emailFolder1Desc</par:Description> <par:ContentType>email</par:ContentType> <par:IsActive>true</par:IsActive> <par:IsEditable>true</par:IsEditable> <par:AllowChildren>true</par:AllowChildren> </par:Objects> </par:CreateRequest> </soapenv:Body> </soapenv:Envelope>
Validate the SOAP request prior to sending it. If the SOAP request is not valid (missing required elements for example), running it will return a "400 Bad Request" message in the response window. These types of errors can normally be trapped beforehand by right-clicking the SOAP request in the editor window and choosing "Validate". Soap UI will return any WSDL or XML Schema validation errors for you to fix.
Make the SOAP call. Clicking the green arrow in the upper-left corner of the editor window is all that is needed. However, even with the validation done earlier, the SOAP response may return an error message indicating further tweaking needed.
Check the SOAP response for any useful information. In the case of a create data folder request, you'll receive the "NewID" of the folder you created, which you can use to make further changes to the folder. Below shows the (anonymized) SOAP response to my SOAP request:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> <soap:Header> <wsa:Action>CreateResponse</wsa:Action> <wsa:MessageID>urn:uuid:xxxxxx</wsa:MessageID> <wsa:RelatesTo>urn:uuid:yyyyyy</wsa:RelatesTo> <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> <wsse:Security> <wsu:Timestamp wsu:Id="Timestamp-zzzzzz"> <wsu:Created>2017-05-21T14:19:52Z</wsu:Created> <wsu:Expires>2017-05-21T14:24:52Z</wsu:Expires> </wsu:Timestamp> </wsse:Security> </soap:Header> <soap:Body> <CreateResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> <Results> <StatusCode>OK</StatusCode> <StatusMessage>Folder created successfully.</StatusMessage> <OrdinalID>0</OrdinalID> <NewID>012345</NewID> <NewObjectID>zzzzzz</NewObjectID> </Results> <RequestID>wwwwww</RequestID> <OverallStatus>OK</OverallStatus> </CreateResponse> </soap:Body> </soap:Envelope>
Go into SFMC Email Studio to confirm the folder you created is there. If you had Email Studio already open, may need to refresh once or twice for the folder to appear. Can delete the folder from within the Studio if desired (or create another web service call to do that as well.)
Save the project to retain your SOAP request envelopes. Menu item Project | Save Project will do. Keeping this SOAP request template will allow you to tweak and reuse it later to create other folders.
Using MTOM and Apache FOP with SOAP Web Services
This blog entry builds off the WSDL-first DoubleIt tutorial to demonstrate the Message Transmission Optimization Mechanism (MTOM) for sending and receiving PDF files via
uploadPDF (client->web service provider) and
downloadPDF (WSP->client) SOAP operations. While
uploadPDF just sends a static PDF file to the WSP, the downloadPDF operation dynamically constructs a PDF containing the results of doubling the number sent in the SOAP request. The finished tutorial source code can be obtained from GitHub by using either the "Clone or Download" button or
git clone -v git://github.com/gmazza/blog-samples.git command.
Technologies highlighted in this sample:
MTOM using XML-binary Optimized Packaging (XOP) - MTOM commonly refers to the process of taking base64Binary data within a SOAP message and storing it in an optimized binary format as a MIME attachment. The MTOM Recommendation, however, mostly provides references to the XOP Recommendation where this process is actually defined. Apache CXF has an MTOM documentation page, also the IBM WebSphere App Server documentation provides another good resource.
Apache FOP - FOP is an XSL processor that takes XML documents and generates PDF documents from them (it can generate other output formats as well.) XSL is most commonly used when you want to maintain different output formats for the same source document, such as when using Docbook to output to HTML and PDF. In our example below, the web service provider will use FOP to generate the PDF.
XSLT - XSLT will be used to take the incoming integer from the SOAP request and place the doubled value of it in an XML document that has the XSL tags used by FOP to generate the PDF. Although the stylesheet I'm providing is minimal, FOP allows you to get quite detailed and artistic, and there are also commercial XSL processors such as RenderX and AntennaHouse with different and frequently better capabilities.
Please refer back to the WSDL-first tutorial for this task, as the steps below list just the changes needed in that tutorial to support PDF document transmission.
In Step #2, add the below dependencies element to the service/pom.xml file so the web service provider will have access to FOP and JavaMail. We're including the Mail API dependency because of a helpful ByteArrayDataSource class it provides.
<dependencies> <dependency> <groupId>org.apache.xmlgraphics</groupId> <artifactId>fop</artifactId> <version>2.2</version> </dependency> <dependency> <groupId>javax.mail</groupId> <artifactId>javax.mail-api</artifactId> <version>1.5.6</version> </dependency> </dependencies>
Also in this step, create the XSLT file for formatting the PDF document. Call it DoubleIt.xsl and place it in the service submodule's src/main/
For Step #3, use the below DoubleIt.wsdl instead. Note the generic
application/octet-stream expectedContentType suitable for transferring PDF documents being used in the downloadPDF request and uploadPDF response which involve transferring a PDF.
For Step #6, use this Web Service Provider instead to return the PDF document.
For Step #8, replace the WSClient with the one below. It receives PDF documents (here's a sample) and saves it to the directory you ran the client from. It then uploads an already existing PDF located in its Maven resources folder.
A packet sniffer such as Wireshark can show MTOM in operation. A CXF SOAP response to a download request from the client is shown below. The PDF document is in its own MIME attachment in an optimized binary format and referenced back to the SOAP message by way of an xop:Include element that holds the PDF's MIME Content-ID value.
HTTP/1.1 200 Content-Type: multipart/related; type="application/xop+xml"; boundary="uuid:4b9b1267-c8e8-458c-aed5-eed03c5c2373"; start="<firstname.lastname@example.org>"; start-info="text/xml" Content-Length: 5987 Date: Sat, 13 May 2017 10:48:29 GMT --uuid:4b9b1267-c8e8-458c-aed5-eed03c5c2373 Content-Type: application/xop+xml; charset=UTF-8; type="text/xml" Content-Transfer-Encoding: binary Content-ID: <email@example.com> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <ns2:DownloadPDFResponse xmlns:ns2="http://www.example.org/schema/DoubleIt"> <doubledNumber> <xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:firstname.lastname@example.org"/> </doubledNumber> </ns2:DownloadPDFResponse> </soap:Body> </soap:Envelope> --uuid:4b9b1267-c8e8-458c-aed5-eed03c5c2373 Content-Type: application/pdf Content-Transfer-Encoding: binary Content-ID: <email@example.com> %PDF-1.4 %.... 1 0 obj << /Creator (Apache FOP Version 2.2) /Producer (Apache FOP Version 2.2) /CreationDate (D:20170513064829-04'00') >> endobj 2 0 obj << /N 3 /Length 3 0 R /Filter /FlateDecode >> stream ...rest of PDF attachment...
The web service provider in this example takes the input number and makes a small XML document out of it prior to processing it with the DoubleIt.xsl file. As an alternative processing method, since the SOAP request is itself XML, you can have the web service provider implement the Provider interface and feed the raw SOAP request directly to the DoubleIt.xsl file. See the CXF documentation for further information.
Colm O hEigeartaigh has a blog post on using WS-Security with MTOM.
|« May 2017 »|