Category Archives: APIs

Creating partner.jar file needed to run BULK API

Faced  lots of issues while generating partner.jar file that is required before using Bulk API in your code.

Mentioning few important steps related to this which makes generation of this file  error free

In Salesforce , if you follow this example :
Set up Application for Bulk API

and run command mentioned  there in Command Prompt :

java -classpath pathToJar\wsc.jar com.sforce.ws.tools.wsdlc pathToWSDL\wsdlFilename .\wsdlGenFiles.jar

You’re most likely to get this error :

Could not find or load Main Class  com.sforce.ws.tools.wsdlc

As I’ve non Java Background, I’d faced considerable difficulty in understanding and dealing with this error :

But key is to remember important things related to this :

  1.  We’ve to run com.sforce.ws.tools.wsdlc to generate Partner.jar file 
  2. To run this, we need wsc Jar file , which we need to download from                            ‘http://mvnrepository.com/artifact/com.force.api/force-wsc’
  3.  To let system find wsc.jar file, we’ve to set class path in the same command (We’ can set it separately also)  using  -classpath <Path of jar file>  syntax
  4. pathToWSDL\wsdlFilename as  suggest , is path of Partner WSDL( Please store in  Same folder as wsc,jar)
  5. .\wsdlGenFiles.jar  : path where ‘to be generated’  parner,jar should be stored.
  6. Will suggest to download  latest wsc jar file  and  Partner WSDL from salesforce and store both of them in same folder ( for e.g , for myself it was D:\BulkApi )

For me the full command was :

java -classpath D:\BulkApi\force-wsc-36.0.0.jar  com.sforce.ws.tools.wsdlc D:\BulkApi\PartnerwsdlDv2.xml  D:\BulkApi\partner.jar

Note : File Names should be proper with extension. When Copying addresses of location, I missed Extention (.jar) and as a result, compilation was giving same error

Even after you run this command , you’re most likely to get big error , a key statement there would be :

Exception in thread “main” java.lang.NoClassDefFoundError: org/stringtemplate/v4/STGroupDir

This is where Salesforce documentation seems like incomplete. We need one more JAR File called ‘StringTemplate’.

Actual name is : ST-4.0.8 (Version could vary)

This jar file should be included in classpath. So new command for Command prompt would be :

java -classpath D:\BulkApi\force-wsc-36.0.0.jar;D:\BulkApi\ST-4.0.8.jar  com.sforce.ws.tools.wsdlc D:\BulkApi\PartnerwsdlDv2.xml  D:\BulkApi\partner.jar.

This should resolve most of error but I faced one more problem : I was getting one more JAVA Error :

which is FileNotFoundException, system was not find some tools.jar file :

After searching I found, I’ve to run above command from ‘bin’ folder where JDK(not JRE) is located, in command prompt.

In my case , it was this : C:\Program Files\Java\jdk1.8.0_20\bin.

NOTE : if JDK folder is not present , then you’ve to download it from oracle site :

http://www.oracle.com/technetwork/java/javase/downloads/index-jsp-138363.html

Once I run above command through proper directory It started working fine and generated partner.wsdl :

 

 

 

 

 

Connecting one Salesforce Org to another via Rest API

I was thinking for long to publish this article. My initial purpose was to learn all major concepts behind Rest API.

Since I don’t have other apps available which I can use for connection so decided that I should Salesforce both as Sending(A) as well as Receiving org(B).

Apart from Rest API basics, This also gave me opportunity to learn following :

  • 1. Expose Apex Classes as REST Resource.
  • 2. JSON serialization and deserialization
  • 3. Making both POST as well as GET request for Rest API call.

We’ll start with ‘RECEIVING ORG CHANGES’

Step 1:  We’ll start with steps needed to configure receiving org(B). Business case : Opportunity is created and closed in ‘Receiving org(B) .After that an order is created outside receiving org. In our case , we ‘ll update Order Amount in  Account object in Receiving org(B) from data created in ‘Sending Org(A).

Step 2: Create a new class in  B . We’ll expose this class as rest resource, so that it can receive data and update Account

@RestResource(urlmapping = '/getAccountData/*')
global  class AccountRestService {
@httpGet
global static string DepositAmountviaGet()
{
integer DepositAmount = Integer.valueOf(RestContext.request.params.get('amount'));
String AccId = RestContext.request.params.get('AccountId');

list acclist = [select id, DevWorld__Deposit_Amount__c, DevWorld__Deposit_Date__c 
from account where id = :Accid];
if(acclist.size()==0)
return 'AccountNotFound';
else
{
try{
account a = acclist[0];//For sake of simplicity, consider handling on record.
a.DevWorld__Deposit_Amount__c = DepositAmount;
update a;

}
catch(exception e)
{
}
return 'Deposit updated succesfully';
}
}

Few points to be noted :

  • Class is declared as Global and method Global & Static
  • You’ve to use annotation   @RestResource with Url mapping as some string like get AccountData before Class declaration.Note the exact syntax. This URL mapping string will be used to create URL for making request from sending ORG.

                 @RestResource(urlmapping = ‘/getAccountData/*’)

  •   Note @httpget  annotation before method-  we’ll be calling this rest resource using ‘GET’ method of http request from API call of Sending org
  • This class will receive two parameters, AccountID, indicating which Account need to be updated and Deposit Amount.

Step 3:   Now since, another SFDC org has to call this rest resource, so we’ve to add ‘Salesforce as ‘connected org’ in this receiving org.

For this  follow below steps

  • Go to Setup | Create | Apps , create new connected App, say with name as ‘SendingSFDCOrg’. 
  • Fill other settings as shown in below screeshot. Important thing is you’ve to provide call back URL and Oauth Scopes.

Connected App

On Saving, you’ll get screen where Client Id and Client Secret will be available to you as shown below:

This client Id and secret will be used in the sending org for authentication.

ClientIdnSecret

Now we’ll move to the Sending Org changes

Step 1:   Create a New VF Page which will show2 fields to enter

AccountID –  User will enter ‘ID’ of some account in receiving org.
Deposit Amount – User will enter Deposit amount to be updated in receiving org.

<apex:page controller="clsSubmitDatainOtherOrg">
<apex:form >
<apex:pageblock >
<apex:pageblockSection >
<apex:inputtext label="Enter Account Id" value="{!AccountId}" />
<apex:inputtext label="Enter Deposit Amount" value="{!depositAmount}" />
</apex:pageblockSection>

<apex:commandButton value="Submit Data" Action="{!SubmitDataUsingGet}"/>
</apex:pageblock>
</apex:form>
</apex:page>

Step 2: Update Controller with following code :

public class clsSubmitDatainOtherOrg {

// we'll be making Oauth Request first to get token,
// One we've token we'll make Rest API call to get data updated in target Org.
public Integer depositAmount{get;set;}
public string AccountId{get;set;}

// This four variables are required for authentication to Oauth Token
String clientId = 'Your Client Id copied from Receiving Org' ;
String clientSecret = 'Your client Secret copied from Receiving Org';
String username= 'Your User Id';
String password= 'your Pwd';

//This method is called form VF page on Submit
public PageReference SubmitDataUsingGet() {

//using this request body we'll make API call
String reqbody = 'grant_type=password&client_id='+clientId+'&client_secret='
+clientSecret+'&username='+username+'&password='+password;

Http h = new Http();
HttpRequest req = new HttpRequest();
req.setBody(reqbody);
req.setMethod('POST');
req.setEndpoint('https://login.salesforce.com/services/oauth2/token');
//Note if my domain is set,use the proper domain name else use login.salesforce.com
// for prod or developer environment, and test.salesforce.com for sandbox

HttpResponse res = h.send(req);
OAuth2 objAuthenticationInfo =(OAuth2)JSON.deserialize(res.getbody(), OAuth2.class);

// proceed further only if you get token
if(objAuthenticationInfo.access_token!=null){

// First create http and req object and set EndPoint
// Note Endpt, this part is common' https://ap1.salesforce.com/services/apexrest/
//'getAccountData' name is URLMapping you set while creating Rest 
//resource in Receiving org.

Http h1 = new Http();
HttpRequest req1 = new HttpRequest();
string EndPt = 'https://ap1.salesforce.com/services/apexrest/getAccountData?' +
'AccountId='+AccountId+'&amount='+depositAmount ;

// Set request header to send token, setMethod, and set Endpoint
req1.setHeader('Authorization','Bearer '+objAuthenticationInfo.access_token);
req1.setMethod('GET');
req1.setEndpoint(EndPt);


//finally make a call
HttpResponse res1 = h1.send(req1);
system.debug('RESPONSE_BODY'+res1 .getbody());
}
return null;
}
}

If you’ve set everything correctly,  data will be updated in the target org.

We” learn how to connect using post method in next post

Connecting .NET Console Application to Salesforce via Enterprise WSDL

This was something I had done while doing POC around 2 years back. At that I had whole team to work with. Since I don’t have much idea about .NET, so I was contributing on Salesforce end and other guys proficient in .NET were mainly working. But we didn’t take much time to connect to Salesforce and make the connection working properly.

Few days back, I decided to do that myself. Because of my inadequate knowledge of .NET, it took me full  two days  to make it working. In this blogpost, I’m giving all steps(with code) to make the connection up and running. We’ll use Enterprise WSDL tO make describeGlobal call and return all objects present in SFDC

Step 1 : Install ‘VS Express 2013 for web. VS is Visual Studio. It is available for free  on the internet.

Step 2:  Once installed, Click File Menu to create New Project as shown below:

New Project in .NET Application

Create New Project in .NET Application

Step 3 :  In New Project window,  Select ‘Windows’ Application under Visual C# Option’.  Give Name to application something like ‘ConnectToSFDC or ConsoleSFDC etc ‘. see Screenshot below

Select Windows Application under Visual C# option

Select Windows Application under Visual C# option

Step 4:   After you click ‘OK’. Visual studio will create New Project with name you’ve provided.  There are multiple Frames in the project.  Right Side frame  is called Solution Explorer. Right click the name of the project and give ‘Output Type’ as ‘Console application’. Close the tab having same name as Project name. Step 5:  Your main project window will look like this :

Project Main Window

Project Main Window

Step 6:  Now we’ll have to add Enterprise WSDL so that we can Query, Create/Update records in SFDC For this login into SFDC,  Go to Setup | Develop | API . Download Enterprise WSDL.

Step 7: We now have to add WSDL in .NET Application  Right click name of the  Project and click  Add | Service Reference | Advanced..(option at bottom of the new popup)  |  Add Web reference. if you’ve correctly added the WSDL, then two things happen : 1. Window will show ‘SforceService’ Description window showing methods available in webservice to work with .For e.g  onvertLead, Create, delete etc. 2. Right side of web reference window will say ‘ Web services found at this URL’ with name of WSDL file. Showing this in below screen shot.  It will also give option to change the name of Webreference. Change it to sfdcConnect .Click Ok  in all the windows which have been opened and return back to Project Window

Step 8:  In the Code window, add name space

using System.Web.Services.Protocols;

Step 9: Now under Class1. which is default crated by .NET. Add following code . showing screen shot also

Main Code Window

Main Code Window

 
private connectToSFDC.SfdcConnect.SforceService binding;
    
    
    [STAThread]
        static void Main(string[] args)
        {
            Class1 sample = new Class1();
            sample.run();
        }

        public void run()
        {
            // Make a login call

            if (login())
            {
                // Do a describe global
                describeGlobalSample();
                // Describe an account object
                // describeSObjectsSample();
                // Retrieve some data using a query
                //querySample();
                // Log out
                //logout();
            }
        }
        private bool login()
        {
            Console.Write("Enter username: ");
            string username = Console.ReadLine();
            Console.Write("Enter password: ");
            string password = Console.ReadLine();
            // Create a service object
            binding = new connectToSFDC.SfdcConnect.SforceService();
            // Timeout after a minute
            binding.Timeout = 60000;
            // Try logging in
            connectToSFDC.SfdcConnect.LoginResult lr;
            try
            {
                Console.WriteLine("\nLogging in...\n");
                lr = binding.login(username, password);
            }
            // ApiFault is a proxy stub generated from the WSDL contract when
            // the web service was imported
            catch (SoapException e)
            {
                // Write the fault code to the console
                Console.WriteLine(e.Code);
                // Write the fault message to the console
                Console.WriteLine("An unexpected error has occurred: " + e.Message);



                // Write the stack trace to the console
                Console.WriteLine(e.StackTrace);
                // Return False to indicate that the login was not successful
                return false;
            }
            // Save old authentication end point URL
            String authEndPoint = binding.Url;
            // Set returned service endpoint URL
            binding.Url = lr.serverUrl;

         binding.SessionHeaderValue = new connectToSFDC.SfdcConnect.SessionHeader();
         binding.SessionHeaderValue.sessionId = lr.sessionId;
         printUserInfo(lr, authEndPoint);
            // Return true to indicate that we are logged in, pointed
            // at the right URL and have our security token in place.
            return true;

        }
private void printUserInfo(connectToSFDC.SfdcConnect.LoginResult lr, String authEP)
        {
            try
            {
                connectToSFDC.SfdcConnect.GetUserInfoResult userInfo = lr.userInfo;
                Console.WriteLine("\nLogging in ...\n");
                Console.WriteLine("UserID: " + userInfo.userId);

                Console.WriteLine();
                Console.WriteLine("SessionID: " + lr.sessionId);
                Console.WriteLine("Auth End Point: " + authEP);
                Console.WriteLine("Service End Point: " + lr.serverUrl);
                Console.WriteLine();
                Console.ReadLine();

            }

            catch (SoapException e)
            {
              Console.WriteLine("An unexpected error has occurred: " + e.Message +
              " Stack trace: " + e.StackTrace);
            }

        }

        private void describeGlobalSample()
        {
            try
            {

                SfdcConnect.DescribeGlobalResult dgr = binding.describeGlobal();
                Console.WriteLine("\nDescribe Global Results:\n");
                // Loop through the array echoing the object names to the console
                for (int i = 0; i < dgr.sobjects.Length; i++)
                {
                    Console.WriteLine(dgr.sobjects[i].name);
                }
            }
            catch (SoapException e)
            {
                Console.WriteLine("An exception has occurred: " + e.Message +
                "\nStack trace: " + e.StackTrace);
            }

            Console.ReadLine();
        }

Important :  Make sure that Visual Studio Editor shouldn’t be showing errors in the form of red line under code expressions.One of the main source of error is, if WSDL is not properly added as web reference. In case you face any problem. try deleting and adding web reference again. Try to check name of reference added and name used in your class code.

Step 10: As a next step, click on debug tab on top bar of VS editor and click ‘Start Debugging’. This will build the application and open and new window asking you to enter username and password, meant to connect to Salesforce.

once done it will provide list of all objects, which shows connection is working properly.