Salesforce.com Partner SOAP API JAX-WS Tutorial Part 1

Salesforce.com provides two SOAP APIs to access objects in a Salesforce.com organization. The Enterprise API is strongly typed and produces a very “discoverable” code-level API. The Partner API is loosely typed and is not very discoverable. For more on the differences between the two APIs, see Salesforce.com API Gotchas Part 1 and the other parts of this blog post series (Part 2, Part 3, Part 4). Update: I’ve released an open source library that presents a better interface to the Partner API (as well as other Salesforce APIs).

To remedy the lack of documentation on using the Partner API documentation with the JAX-WS reference implementation, this tutorial series will describe how to use JAX-WS to create stub code, how to use the stub code to log in as a Salesforce.com partner, and how to perform basic API operations.

Generating Stub Code from the WSDL

When generating stub code, you have two main choices:

Use a command line tool provided with the JAX-WS download in bin/wsimport.sh (wsimport.bat for Windows folks)

You’ll need to change ‘jaxws-ri’ to be the path to your downloaded copy of the JAX-WS reference implementation. ‘sfstub’ is the package used for the generated classes. ‘sfstub-build’ is where the .class files will go. ‘sfstub-src’ is where the .java files will go.

where ‘someClasspath’ is a classpath name that includes the JAX-WS RI tools. This is just one of the many ways to specify classpaths with Ant, so check the Ant documentation for more on classpaths if this is new to you. Once you have your wsimport Ant task defined, you can use it like this:

In real usage, you would probably replace many or all of those attribute values with Ant references, but to keep things simple I’ve just used plain values.

So now you’ve got some stub classes, right? Unfortunately, it’s not that simple. Whether you decide to use the CLI tool or the Ant task , when you try to generate your stub code from the Partner WSDL, you’ll quickly run into errors like the following:

[ERROR] A class/interface with the same name "yourpkg.DescribeLayout" is already in use. Use a class
customization to resolve this conflict.
line 928 of file:/path/to/partner-15.wsdl
[ERROR] (Relevant to above error) another "DescribeLayout" is generated from here.
line 640 of file:/path/to/partner-15.wsdl
[ERROR] Two declarations cause a collision in the ObjectFactory class.
line 928 of file:/path/to/partner-15.wsdl
[ERROR] (Related to above error) This is the other declaration.
line 640 of file:/path/to/partner-15.wsdl

This example run was done against the Release 15 WSDL, so if you’re using a different version your line numbers (or even error messages) may differ, but you’ll probably have some class that has a naming conflict. In this case, the problem arises because there is both a complexType and a element in the WSDL that are named “DescribeLayout”.

By using a JAXB binding file, we can customize the names of the generated classes to not have a conflict.

The JAXB binding file will cause “Type” to be appended. (You could use any string you wanted as long as it solves the conflict.) This is occasionally odd-looking in cases like “SoapType” which then becomes “SoapTypeType”.

You can avoid using a binding by having JAXB automatically resolve name conflicts. To do this, add a parameter to enable automatic name conflict resolution in JAXB. For the CLI tool, that looks like this:

This will result in having a DescribeLayout class as well as a DescribeLayout2 class. In this case, DescribeLayout is the element and DescribeLayout2 is the complexType.

It’s a judgment call whether or not you prefer the binding file method with class names like “SoapTypeType” or the automatic method with class names like “DescribeLayout2” where the class names are a little harder to predict. The Ant task may be easier to integrate into your build system, but shell scripts are also fairly simple to call (albeit less portable than pure Java tasks) from Ant. There are also differences in the way method parameters and return values are handled for API calls; this is described in more detail in Part 2.

Whichever way you choose, you should now have compiled stub classes ready for use.

Continue on to Part 2 where I’ll show to use these stub classes to log in to a Salesforce organization.

Saving the file to my harddrive and then importing from the local files, the import seemed mostly successful. I did, however, received a couple warnings:

[WARNING] src-resolve: Cannot resolve the name ‘tns:ID’ to a(n) ‘type definition’ component.
line 30 of file:/D:/Brian%20Stuff/Education/Force.com/WSDL/enterprise.wsdl.xml#types?schema1

[WARNING] src-resolve: Cannot resolve the name ‘tns:ID’ to a(n) ‘type definition’ component.
line 30 of file:/D:/Brian%20Stuff/Education/Force.com/WSDL/enterprise.wsdl.xml#types?schema1

Could it make any difference that the import was not from a “live” file on a webserver?

Is there something I should do to fix my URL so I could import directly?

Is there anything I should do about these warnings?

Cheers in advance.

Marshall Pierce

You’ll probably want to store the WSDL locally because JAX-WS needs it at runtime. If you look in the generated stub for SforceService or whatever it’s called in the Enterprise WSDL, you’ll see the path to the WSDL hardcoded. Part 2 of the tutorial shows how to deal with the fact that the WSDL will not be at D:/Brian%20Stuff/Education/Force.com/WSDL/enterprise.wsdl.xml when you deploy it.

I get those same warnings about ‘tns:ID’ but they don’t seem to have any negative effect, so I wouldn’t worry about it.