Simon Fell > Its just code > May 2004
I've been spending some time recently working more with the .NET 1.1 SOAP stack and with Axis 1.1, it was a brutal reminder of how big a difference there is between (a) the current tools, (b) current best practice (e.g. WS-I BP) and (c) the WS-* stack of specs. Both tools (and the rest I imagine, PocketSOAP certainly not excluded) have their pain points, .NET's use of public fields in classes rather than properties is a PIA when it comes to data binding and an even bigger PIA with the additional XXXXspecified properties, which you need to remember to set when sending them out of the client, otherwise your XXX value is going nowhere. [tell me this is fixed in Whidbey, right ? (still fighting to get a working Whidbey install)]. Axis, which does a much better job at that part, has some real strange header handling, the WSDL documents which headers are valid for which operation, but once you've set a header, Axis will just blindly send it on every subsequent request. So you're left to remove the header yourself on the operations that shouldn't send it, but dang!, there's no direct way to remove a header, you have to grab all the current headers, call clearheaders, then add them all back in, minus the one you wanted to remove. urrrgghhh. And to top it off, when faced with the task of generating a server side stub from WSDL, they both end up generating code that doesn't work. (how exactly did wsdl.exe /server make it out unfixed in 2 releases of .NET ?)
Brad is looking to go dual DVI, a move I made earlier this year, the trick (if you're using the FP2001's), is not to find a dual DVI card, but a dual DVI card that will drive both outputs at 1600x1200, a number of the gaming centric cards I looked at wouldn't do dual DVI at that res, and I settled on the Matrox P750 card, which I've been happy with, but judging by the reviews, its not a card for gamers (can't remember the last time I played a PC game).
Anyone have a list of toolkits offering WSI BP conformance ?, I'm surprised there isn't a list on the WS-I site. As the BP seems to largely be a rubber stamp of what the MS tools do, I'm assuming that you can use .NET to build BP compatible tools, what about other toolsets, any of the Java tools there yet ?
One re-occuring theme I see various WSDL's is that they are designed so that the generated proxy in tool X is easy to use, and not what makes the most sense on the wire. This is such a broken way of doing things that I don't know where to start, but lets start with this.
- For doc/literal SOAP services there is no standard for what the programming model for the generated client is, therefore what works well in tool X may be completely different in tool Y.
- Programming models are going to evolve, what looks good today maybe a complete lemon with next years tools
- The whole point of doc/literal web services is that the wire format is king, and how they map to environment Z is irrelivant.
SOAP Headers are a good example of where tools differ, Axis and .NET are similar in concept, but (with v1.1 Axis at least) are way more manual and complicated and non-obivous in Axis. In either case I personally don't like the "set the headers at the proxy class instance level" that both these tools use, and if you use the PocketSOAP WSDL Wizard, it will generate parameters in the operation method call to pass the headers in, making it way more obvious which headers are valid for which operations.
I just wrapped up a tutorial that shows how to use PocketSOAP and the WSDL Wizard to access SForce. It contains a short explanation of the programming model that the WSDL wizard generates for doc/literal services, which as its different to the typically programming model that other tools expose, is worth a look at if you're doing doc/literal with the WSDL wizard generated code.
This tutorial shows how to use PocketSOAP to access SForce, the Salesforce.com Web Services API.
- First off, if you don't have a salesforce.com account, head over to sforce.com and sign up for the free developers edition account
- Next, make sure you've got PocketSOAP and the PocketSOAP WSDL Wizard (v2.3 or greater) installed.
- Now we need to grab the WSDL for your account, login to salesforce.com, click the setup link at the top right, then from the left menu under studio select WSDL Generator. Finally, right click on the Download Enterprise WSDL link and select save link to disk, and save the WSDL somewhere on your machine.
- Now we can run it through the WSDL Wizard to get an easy to use object model generated for us. Start the WSDL Wizard, enter the path and filename of the WSDL in the top box, and the second line select a directory for it to generate the VB6 files to, and enter sforce as the name of the project in the bottom box.
- Hit next, you'll be presented with the list of bindings, of which there's only one, so hit next again, now you can see the list of methods, leave them all selected and hit next again. The Wizard will now generate the code, then say its finished. Click OK to close the wizard.
- If everything went according to plan, you now have a ton of generated VB code (~200 classes!), open the sforce.vbp project and compile it.
- Now start a new VB standard EXE project, and do add reference, scroll down the list and pick "SForce Proxy class....". The main entry point into the generated proxy code is the Soap class (this is named from the WSDL), if you look at this in the object browser, you'll see a bunch of methods, one for each one listed in the WSDL.
Now, in order to access the data we need to login, so drop a button on your form, and add this code
' create the proxy object and the login message
Dim svc As New Soap
Dim lr As loginResponse
Dim lo As New login
lo.Username = "<your login>"
lo.password = "<your password>"
Set lr = svc.login(lo)
SForce uses a document/literal style service, so the programming model exposed by the generated proxy has a method for each operation in the WSDL where each method takes an object that represents the request message, and returns an object that represents the response message. In addition any SOAP headers that may apply to the operation are also passed as parameters to the method (this is likely different to the programming model generated by other tools, I'll save why I think this is better for another day)
Now, going back to our login code, you can see that we create an instance of the login message, populate its data (username & password in this case), and call the login method, this returns a loginResponse message.
The loginResponse message contains a single loginResult stucture that contains a few pieces of useful information, the 2 important ones are the serverUrl and the sessionId. In the SForce world, once you're authenticated you communicate with a different server (as indicated by the serverUrl value), and you tell it your authentication info by passing the sessionId back to the server in a SOAP Header. So what we'll do next is create the SOAP header object, and populate it with the sessionId, and point the proxy object at the new Url.
' create the session header, and update the server Url that we connect to
Dim sh As New SessionHeader
sh.sessionId = lr.result.sessionId
svc.Url = lr.result.serverUrl
Now, we'll create a couple of new Accounts, we do this via the create operation, here's how the object browser shows the create method.
The create_ parameter is the create message, and there's 2 headers we can send, the SessionHeader which we've already discussed and the SaveOptions header, this header lets use control how lead assignment is handled, which we don't care about for Accounts, so we can just pass nothing for that in this case.
The create message contains an array of sObjects, everything in Salesforce.com is based on an sObject, the Account object inherits (or extends in XSD speak) from sObject. So, we need to create an array of sObjects, where each item in the array is an account. One wrinkle is that VB won't let you pass a statically sized array to a property call, so you need to ensure that your array is dynamically sized (i.e. use redim)
' create 2 new accounts, note that the create call uses an object hierarchy
' but in VB we need to pass sObject() to the create call, so declare the array
' as that, but populate it with account objects
Dim acc() As sObject
Dim na As New Account
na.Name = "Simon's Test Account"
na.AccountNumber = "42424242"
na.AnnualRevenue = 10000
Set acc(0) = na
Set na = New Account
na.Name = "Simon's other test account"
na.AccountNumber = "24242424"
na.AnnualRevenue = 11111
Set acc(1) = na
Now we've got the 2 accounts we want to create, we can create the Create message, and make the call to the create operation.
' do the create call
Dim cr As New Create
cr.sObjects = acc
Dim cres As createResponse
Set cres = svc.Create(cr, sh, Nothing)
All that's left is to check the response, to see if there are any errors (as there might be an error with only a single object, there's a separate error indication for each Account we tried to create).
' check the results
Dim idx As Long
For idx = LBound(cres.result) To UBound(cres.result)
If Not cres.result()(idx).success Then
debug.print "failed creating account: " & cres.result()(idx).errors()(0).message
debug.print "created account with Id " + cres.result()(idx).id
That's it!, you can now login through the web interface and see the new accounts you've created, the rest of the functions all work in the same manner, finally the describeSObject call exposes a lot of information about the fields on each of the sObjects derived types in the system (including any custom fields or custom objects you may of created yourself through studio), making it easy to do grid views and similar that are completely driven by the meta data.
I just released an updated WSDL Wizard which has a couple of bug fixes and improvements to the generated code for doc/literal services.
If you use PocketSOAP, then I'm interested in which platforms & features you use, head over to the mailing list and do the survey, thanks !
If any of the MSDN folks are reading, The Integrating Web Services and COM Components article listed in the RSS feed and here, just drops you back at the WS dev center home page.