I’ve posted a lot of information about Salesforce over the years (Partner API Gotchas Part 1, Part 2, Part 3, Part 4, JAX-WS Tutorial Part 1, Part 2, Part 3, Part 4). I’m supplementing that with the release of an open source Java library for using the REST, Partner, Metadata and Apex APIs. You can get the source from the Palomino Labs open source project. The code is under active development but it is stable and ready for use. When I do cut a release, I’ll update this blog post to point to it.
- Easy-to-use wrappers around the APIs. The classes that tools generate for the SOAP APIs are clumsy and unintuitive (and not thread safe), so I’ve written better versions.
- Limits concurrent API calls for Partner, Metadata and Apex connectors. This helps you avoid ‘concurrent request limit exceeded’ errors. (The REST API is harder to hit the limit with. I will add it to the request limiting system in the future.)
- Transparent handling of
INVALID_SESSION_IDfor the Partner API. If someone else has closed the session ID you were using, the library will automatically re-login as needed.
- Designed to be used with many different organizations simultaneously. If your app needs to talk to the orgs of many different customers all at the same time, it’s easy to do so. Of course, it’s also easy to work with just one org if that’s what you need.
- Connections are reconfigurable at any time. You can update the login and password (for SOAP connections) or OAuth token (for REST connections) and the next API call you make will seamlessly use the updated information, even if it’s in another thread.
- Designed with thread-safety in mind. Where practical, classes are thread-safe or immutable.
- HTTP communication is gzip-compressed.
- Integration with Metrics.
- Well-tested, robust code.
- Business-friendly Apache License (no GPL issues)
First you’ll need to check out and build the code.
% git clone git://github.com/palominolabs/sf-api-connector.git % cd sf-api-connector % mvn clean install -DskipTests
Maven will probably need to download a bunch of plugins if you’re not a Maven user yet. Once it’s done, you’ll have installed the jars into your local maven repository. The reason tests are skipped is that some of the tests actually use Salesforce’s real API and are therefore restricted to only come from certain blocks of IP addresses, so those tests will fail unless you happen to be using my ISP. Also, the tests take quite some time to run. The SOAP-based APIs (Partner, Metadata and Apex) are in the
soap-api-connector module and the REST API is in the
rest-api-connector module. The dependencies to use for your pom.xml are shown below. You only need to include the dependency for the API that you’ll be using (that is, you don’t need both unless you’re using both). The dependencies are both SNAPSHOT versions because that’s what’s declared in the project’s pom.xml right now.
1 2 3 4 5 6 7 8 9 10
Using the REST API
Most people can probably do what they need with the REST API, so I’ll start with that since it’s simpler.
RestConnectionPool is the starting point for using the REST API. The class has a generic parameter to allow you to use any class you want to identify organizations. You might use the Salesforce organization id (the id that starts with ‘00D’) or perhaps the primary key for a table in your DB that has a row for each organization. Make sure you use an immutable class with a useful
equals() implementation since these objects will be used as keys in a
Map. In this example I’ll use Integer. You’ll need to provide a
MetricRegistry. If you’re not already using Metrics, just having a static final
MetricRegistry that you use globally is a reasonable place to start; check the Metrics getting started guide for more.
Before you can use the pool to get a connection for a specific org, you need to inform the pool about that org.
The host is the HTTP endpoint to use. Different orgs may be on different Salesforce clusters, so this is a per-org setting. You can extract the host from the partner server URL (see
ConnectionBundle.getBindingConfig() in the SOAP API module or the tip later on in this article) if you don’t already have it. The OAuth token is something you’ll get by following the steps outlined in Salesforce’s OAuth docs. You can also use a session Id from the SOAP API as the OAuth token. You can configure a pool with as many orgs as you want. The pool is shared between all of them for efficiency. You can also reconfigure the data for an org in a pool at any time. Now that the pool is configured, let’s actually use a connection.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
RestConnection interface to see what else you can do with it.
Using the SOAP APIs
The SOAP APIs are a little more complicated because there are three different WSDLs that share some common configuration. First you’ll need to pick a “partner key” or “client id”. This is a fairly arbitrary identifier that will be used to identify what application made an individual API call. Choose something at least mildly human-readable. As with
RestConnectionPool, you can choose any class you like to be your org identifier. Here I’ll use
1 2 3
Username and password are the Salesforce username and password of the person you want to log in as. The last parameter sets the max number of concurrent calls you want to happen per org. Fortunately in a recent update (API version 19 or 20, I think) Salesforce greatly relaxed the limits on concurrent connection usage to only apply to calls that take longer than 20 seconds, so you can set this limit fairly high unless you’re going to be doing long-running calls. See Salesforce’s API Usage Metering docs for more details. You can now get a
ConnectionBundle for an org. A
ConnectionBundle represents the per-org configuration needed for all SOAP connections.
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
Note that the Metadata API example shows how to get custom field Ids, something that is impossible via the Partner API. The
ConnectionBundle interface also lets you get the current configuration data for an org. You can use this to get the hostname that you need for
RestConnectionPool. Using OAuth to get the token is recommended if that’s an option, but if not you can also get the current session Id from the configuration data and use that as the OAuth token.
1 2 3 4
The library doesn’t support every single possible call in all of the APIs, but it does support most of them. I only implemented the calls I had occasion to use, so the Partner, Metadata and REST APIs have fairly complete support while the Apex API only supports a fraction of the available calls. If there’s a call that you use that the library doesn’t support, let me know and I’ll see what I can do. Similarly, if the library’s API doesn’t seem intuitive or doesn’t fit well with what you’re doing, I’d like to hear about that as well.