Dashboard

May 21 21:57 | You don't have to be formally educated to sound smart, and formal education won't stop you from sounding stupid. #justsaying
May 21 21:06 | If you ask me if I'm an educated, I will proceed to smoke an imaginary pipe during the rest of our conversation. #twoformsofeducationplease
May 21 20:18 | RT @paul_irish: A+ thread where Mozilla's brilliant Boris Zbarsky sits down with Firefox, a profiler and Facebook's Timeline https://t.c ...

Connecting and using a Salesforce web service from Coldfusion

September 4th 2009

Salesforce.com and Coldfusion. It’s an interesting pairing, but one nonetheless that probably happens more often then you would think. But how does one connect to a Force.com web service?

Connecting to Salesforce from Coldfusion isn’t terribly hard. What you need is the Partner WSDL file from your particular instance of Salesforce. Since I’m not one for duplicating work, the Force.com web services API developers guide covers the topic and the steps needed to retrieve the WSDL.

Needless to say, lets look at an example. You can’t take this and run wild; you would need to make the struct work with your own target, as well as point it to proper WSDL’s and offer login details. Some things to note:

  1. The struct that you sent to your Force.com call needs to be perfect, otherwise you’ll be left shaking your head at a completely unhelpful “Web service operation could not be found” error.
  2. If you ever see “Unable to create web service argument class” this is generally because the struct is also wrong. Check your data and check the target types you should be sending.
  3. Coldfusion MX 7 tends to fight more then Coldfusion 8.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
 
<!--- A pretend struct to send to our web service --->
<cfscript>
	mySentStruct = structNew();
	mySentStruct.somethingF1 = "StringTest-01";
	mySentStruct.somethingF2 = "StringTest-02";
	mySentStruct.ohcomplex[1] = structNew();
	mySentStruct.ohcomplex[1].somethingagain = "herewego";
	mySentStruct.ohcomplex[1].ohcomplex02 = arrayNew(1);
	mySentStruct.ohcomplex[1].ohcomplex02[1] = "something,something";
</cfscript>
 
<CFSET Application.isError = "false" />
 
<!--- Only one session should login at a time. --->
<CFLOCK timeout="10" scope="Application" throwOnTimeout="no" type="exclusive">
 
	<!--- The SFDC login session should remain active for 30 minutes --->
	<CFIF NOT IsDefined("Application.sfdc") OR Application.sfdc EQ "" OR NOT IsDefined("Application.lastLogin") OR (IsDefined("Application.lastLogin") AND Abs(DateDiff("n", Application.lastLogin, Now())) GT 30)>
 
		<!--- Create web service objects --->
		<CFSET Application.sfdc = createObject("webservice","https://someurl.to.partner.wsdl/") />
		<CFSET Application.sfdcyourservice = createObject("webservice","https://someurl.to.yourservice.wsdl") />
		<CFSET loginResult = Application.sfdc.login("username","password") />
 
		<!--- Create the SOAP Header that will contain the Session ID --->
		<CFSET authHeader = createObject("java","org.apache.axis.message.SOAPHeaderElement").init("YourServicesService", "SessionHeader") />
 
		<CFSET Application.sfdcyourservice.setHeader(authHeader) />
 
		<!--- Add (and populate) a text node called sessionId: --->
		<CFSET authHeader.addChildElement("sessionId").addTextNode(loginResult.getSessionId()) />
 
		<!--- Change the endpoint URL to what was returned by the login method: --->
		<CFSET Application.lastLogin = Now() />
	</CFIF>
</CFLOCK>
 
<CFTRY>
	<!--- Only one session at a time should call this method --->
	<CFLOCK timeout="10" scope="Application" throwOnTimeout="no" type="readOnly">
 
		<CFSET sfdcResponse = Application.sfdcyourservice.createSomething(mySentStruct) />
	</CFLOCK>
 
	<cfoutput>My SF Response: #sfdcResponse#</cfoutput>
 
	<!--- Catch any errors --->
	<CFCATCH type="ANY">
 
		<!--- Reset the sfdc session --->
		<CFSET Application.sfdc = "" />
		<CFIF NOT IsDefined("Application.isError") OR Application.isError NEQ "true">
			<h1>An error occurred</h1>
			<h2>Error Details</h2>
			<CFDUMP VAR="#mySentStruct#" />
			<CFDUMP VAR="#CFCATCH#" />
 
			<CFSET Application.isError = "true" />
		</CFIF>
	</CFCATCH>
</CFTRY>

But just you say, what about “Cannot generate stubs errors”? Truly a pain in the neck. What I found that works the best in this situation is to use the CF admin API and reload the web service, which in turn usually regenerates the stubs without issue:

1
2
3
4
5
6
 
<cfset createObject("component","cfide.adminapi.administrator").login("yourCFadminpassword")>
 
<cfset ws = createobject("component","CFIDE.adminapi.extensions")>
<cfset ws.reloadWebService(name="https://someurl.to.yourservice.wsdl",path="https://someurl.to.yourservice.wsdl")>
<cfdump var="#ws.getwebservices("https://someurl.to.yourservice.wsdl")#">

See, now that wasn’t so bad was it? Coldfusion may not be your first choice, but when it’s there and you can wrangle it, you can get it to connect to pretty much anything.

Reader Responses

Skip to Response Form

1
Jim says:
November 06, 7:11

Hi,

I have the following URL to try and connect to a SalesForce Web service:

https://login.salesforce.com/services/Soap/u/20.0/partner.wsdl

Where you say:

could you please give me the EXACT syntax I need based on the URL I am trying to use?… I am a bit confused as to the “someurl.to.yourservice”.

Thank you so much for your help!

2
November 06, 7:49

Usually it’s the Enterprise WSDL.

From Docs: Your Name > Setup > Develop > API > Generate Enterprise WSDL.

Comment on this Entry

About This Entry

You are reading "Connecting and using a Salesforce web service from Coldfusion", and entry posted on 4 September, 2009 and filed under ColdFusion, development, software, Web Apps.

0 responses to this entry. 0 blog reactions. Add your response or trackback from your own site.