Using Salesforce Web Services from Java

30 Sep

You can access Salesforce from Java using web services allowing you to integrate external systems with your Salesforce instance. There are two main WSDLs you’ll be interested in for this: the enterprise WSDL and the partner WSDL. The partner version as the name suggests, is designed for partners or people writing for multiple organizations. This version is more generic compared to the enterprise version which provides access to the database objects directly with all the field names and types you have defined. Both provide the same core functionality so if you’re only writing for one organization, you’ll generally use the enterprise version.

The first thing you need to do is download a copy of the WSDL file. To do this, go to setup, Develop, API. Here you’ll see a link to “Generate Enterprise WSDL”, click that link and you’ll see a screen to set the version of any installed packages and a Generate button which will create the file for you. You’ll probably see it rendered as an xml file you can right click on this, view source and save the file.

I use Eclipse for my Java development (version 3.4.1 with web standard tools) and I discovered an issue with the default client code generation in that it doesn’t seem to generate complex type arrays correctly. Not many of the API calls require this so unless you use something like emptyRecycleBin() which works on an array of IDs you might not even notice.

To use the standard tools, import the WSDL into a project, right click on it select Web Services, Generate Client. You’ll get a new package generated with the services you need to access Salesforce. If you run into the issue I did or need an alternative client generation, you can use Apache Axis2. Download the latest version, read the creating clients section of the docs (basically run the bin\WSDL2Java script specifying the WSDL and the client form you want) and import the code generated into your IDE. I’d choose the ADB mapping – it’s much simpler to deal with than XML beans and generates far fewer files for you to deal with.

Before you can do anything with your organization, you need to login. To do this, create a Service Stub, setup your login object and call the Stub login method. Get your session id from the login response and use it to setup your session header. Once you’re logged in, you need to use the endpoint provided in the login response for future calls so create a new stub with this URL and then you’re free to use the API calls you need.

Here’s a basic code stub to show you how that works:


SforceServiceStub stub = new SforceServiceStub();
 Login login = new Login();
 LoginScopeHeader lsh = new LoginScopeHeader();
 login.setUsername("YOUR USERNAME");
 login.setPassword("YOUR PASSWORD");
 LoginResponse lr = stub.login(login, null);
 SessionHeader sh = new SessionHeader();
 sh.setSessionId(lr.getResult().getSessionId());
 System.out.println("Logged in!");
 SforceServiceStub runStub = new SforceServiceStub(lr.getResult().getServerUrl());

Apex Improvements in Winter 11

9 Sep

I’ve finally had a chance to have a quick scan of the Winter 11 release notes and a couple of Apex enhancements caught my eye.

The first is a new isRunningTest() method for System which will return true if the currently executing code was called by a testMethod. This is great for the times you need to do something differently to make sure your test doesn’t run into limit issues but most of the cases I can think of have been rendered moot by another change.

Tests no longer run in a separate context with different limits. If I’m reading that correctly, I no longer have to worry about things like my code being able to return up to 10,000 rows without issue but my test failing if it finds more than 500.

I really like this. Writing extra code in your class/trigger so your test doesn’t have issues seems like a bad idea. First, you’re no longer really testing your code as it would normally run and you’re also adding additional complexity that needs to be maintained.

Triggers, Tests and Assertions

3 Sep

Sometimes (such as when you’re doing a big bulk load of data) you want to disable triggers to speed up the transfer of data or maybe you just temporarily don’t want a trigger firing. You can’t just make them inactive from the UI of your production org, you need to do that in a sandbox and then deploy to the production server.

The downside of this is that all your unit tests will need to be run on the deployment. If you’ve written quality tests with assertions, some of these will fail with the trigger no longer active.¬† Editing your tests each time could become a pain so you can either leave the trigger dependent assertions off, or figure out a way to detect if the trigger is active. Here’s how you do the latter:


ApexTrigger myTrigger  = [SELECT Status from ApexTrigger WHERE  Name='myTestTrigger'];

if  (myTrigger.Status=='Active'){

//do  assert

}

Now you can leave your test code alone and toggle your triggers to your heart’s content.

Testing Batch Apex

21 Aug

I recently had to publish a batch Apex class to our production org and had a tough time doing it thanks to issues with the associated test.

If you read the official documentation, it’s a little vague about the limitations involved in testing batch code and if you get things wrong, your test will probably run but show very low coverage (specifically just the start method showing coverage).

Digging through the discussion boards lead me to this post which outlines the solution.

Basically you’re only allowed to run one batch of 200 records for your test. That means you have to be able to add LIMIT 200 to your SOQL query in your test class and you can only have one call to Database.executeBatch() within your test class. You also need to wrap that call within Test.startTest() and Test.stopTest(). The start test signals the system to collect all async code and then it’s executed after the stop test.

You could just make your SOQL query a public string and default it to your “live” query then your test code would look something like:

Test.startTest();
MyBatchClass mb = new MyBatchClass();
 mb.theQuery = mb.theQuery + ' limit 200';
 String Id = Database.executeBatch( mb, 200);
Test.stopTest();

Providing¬† direct access to the query like that though isn’t really ideal coding.¬† It would be better to add a public method say runAsTest() to your batch which you could call from your test class and have that do the addition of the limit text, therefore protecting your carefully crafted query from the clutches of anything that might mess with it.

Hello world!

20 Aug

I started this blog to keep track of the things I discover while developing in a Salesforce environment. I don’t work for SFDC or have a relationship with the company other than as a customer. I don’t profess to be an expert and most (if not all!) of what I post you can probably find elsewhere but hopefully if it’s useful to me, it might be useful to you too.