Calling Salesforce Web Services Using Apex   Leave a comment

http://developer.force.com/cookbook/recipe/calling-salesforce-web-services-using-apex

 

Problem

Most, if not all, of the Web service examples and tutorials use an external programming language to call/invoke the salesforce Web services. However, this requires external hardware and software to run and is not native to the salesforce platform. With a few tweaks to the salesforce Web services’ wsdl and Apex generated classes, it’s possible to invoke them through native Apex.

Solution

To begin, you always need to have either an Apex Partner or Enterprise Web service class so that you can login and get a session id, which will be used in any future Web service calls.

Let’s generate an Apex Partner Web service class first.

  1. Go to Setup | Develop | API -> Click on “Generate Partner WSDL”.
  2. Save the file and name it “Partner.wsdl”.
  3. Go to Setup | Develop | Apex Classes -> Click on “Generate from WSDL”.
  4. Select the “Partner.wsdl” file and click the “Parse” button.
  5. Accept the default class names and click the “Generate Apex code” button.
  6. Now, you’ll see the following message “The following generated class(es) have compilation errors: Error: partnerSoapSforceCom Error: unexpected token: ‘delete’ at 670:51”. This results from some of the partner web methods being the same as Apex DML keywords. To resolve this, simply change the name of the Apex method names.
  7. Copy all the partnerSoapSforceCom Apex code in the textbox.
  8. Go to Setup | Develop | Apex Classes -> New.
  9. Paste the partnetSoapSforceCom Apex code.
  10. Change
    1 public partnerSoapSforceCom.DeleteResult[] delete(String[] ids)

    to

    1 public partnerSoapSforceCom.DeleteResult[] deleteSObjects(String[] ids)
  11. Change
    1 public partnerSoapSforceCom.UpsertResult[] upsert

    to

    1 public partnerSoapSforceCom.UpsertResult[] upsertSObjects
  12. Change
    1 public partnerSoapSforceCom.MergeResult[] merge

    to

    1 public partnerSoapSforceCom.MergeResult[] mergeSObjects
  13. Change
    1 public partnerSoapSforceCom.SaveResult[] update

    to

    1 public partnerSoapSforceCom.SaveResult[] updateSObjects
  14. Change
    1 public partnerSoapSforceCom.UndeleteResult[] undelete

    to

    1 public partnerSoapSforceCom.UndeleteResult[] undeleteSObjects

Now you have an Apex Partner class.

 

Next, let’s generate an Apex class for the Apex Web service.

  1. Go to Setup | Develop | API -> click the “Generate Apex WSDL” button.
  2. Save the file as “Apex.wsdl”.
  3. Go to Setup | Develop | Apex Classes -> Click on “Generate from WSDL”.
  4. Select the “Apex.wsdl” file and click the “Parse” button.
  5. Keep the default “soapSforceCom200608Apex” name and click the “Generate Apex code” button.

Now, you should see the following message “The following generated class(es) compiled successfully with no errors: soapSforceCom200608Apex”, which indicates that you now have an Apex class for the Apex Web service.

 

Before we can use some code to demonstrate that this works, we have to configure our org so that we’re allowed to call the Web services. Not a biggie.

  1. Go to Setup | Security Controls | Remote Site Settings
  2. Click “New Remote Site”.
  3. Enter “SalesforceLogin” for the Site Name.
  4. Enter either “https://login.salesforce.com” or “https://test.salesforce.com” as the Remote Site URL depending on your org.
  5. Click Save. Now, you have granted your org the ability to login, but you still have to grant it access to the correct salesforce web node to allow the Apex Web service to be called, which we’ll do next.
  6. Go to Setup | Security Controls | Remote Site Settings
  7. Click “New Remote Site”.
  8. Enter “SalesforceApex” for the Site Name.
  9. Enter “https://<Prefix>-api.salesforce.com&#8221; where <Prefix> is the salesforce sub-domain you’re using, which can be found by looking at the URL in your browser. Since I’m on “https://na12-api.salesforce.com&#8221;, I would enter “https://na12-api.salesforce.com&#8221;.
  10. Click “Save”

Now, we’re ready to run a quick example that will run all the unit tests in our org in a synchronous fashion.

 

01 partnerSoapSforceCom.Soap sp = new partnerSoapSforceCom.Soap();
02
03 /* For demonstration purposes only, enter your credentials on the following
04    lines, but if you're going to use this a lot or in production, encrypt your credentials and store them somewhere and then decrypt them here.
05 */
06 String username = '<Your username here>';
07 String password = '<Your password here>';
08
09 partnerSoapSforceCom.LoginResult loginResult = sp.login(username, password);
10
11 system.debug('   loginResult ' + loginResult);
12
13 soapSforceCom200608Apex.Apex apexWebSvc = new soapSforceCom200608Apex.Apex();
14 soapSforceCom200608Apex.SessionHeader_element sessionHeader = new soapSforceCom200608Apex.SessionHeader_element();
15 sessionHeader.sessionId = loginResult.sessionId;
16
17 // The Web services have a maximum timeout of 2 minutes. The timeout value
18 // is in milliseconds.
19 apexWebSvc.timeout_x = 120000;
20 apexWebSvc.SessionHeader = sessionHeader;
21
22 soapSforceCom200608Apex.RunTestsRequest testsRequest = new soapSforceCom200608Apex.RunTestsRequest();
23 testsRequest.allTests = true;
24         
25 soapSforceCom200608Apex.RunTestsResult testResults = apexWebSvc.runTests(testsRequest);
26
27 /* Do something worthwhile with the test results here */

Discussion

This is just the tip of the iceberg, since we’re only using the Apex Web service. With a little bit of effort, you can generate an Apex Metadata class for the Metadata Web service. This could “theoretically”, for example, let you deploy code from one org to another using a “deployment” org without the need of the migration tool.

Another example would be creating an automated testing scheduled job, using the above code as a starting point, and emailing the results to your development team. Keep in mind that if you have a lot of tests, it may take longer than 120 seconds and this approach won’t work. You’ll have to switch to the asynchronous “ApexTestQueueItem” and “ApexTestResult” objects, but they don’t currently provide nearly as much information as the synchronous “RunTestsResult” object.

From here, try out different things and please share your findings. I’m certain I’m not the only interested party.

I hope this helps and happy coding.

Luke

Posted 2012年03月8日 by gw8310 in salesforce

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s

%d 博主赞过: