Showing posts with label Apex. Show all posts
Showing posts with label Apex. Show all posts

Saturday, March 21, 2015

Use Custom Setting Efficiently in Apex

Use Custom Setting Efficiently in Apex

What is Custom Setting?

Custom Settings are similar to custom objects and gives ability to create custom sets of data. The data can be associate to an organisation, profile, or specific user. 

Data Types for Custom Setting fields:


  • Checkbox
  • Currency
  • Date
  • DateTime
  • Email
  • Number
  • Percent
  • Phone
  • Text
  • Text Area
  • URL

Note: The data in these fields are cached with the application.

Types of Custom Settings

There are two types of custom settings:

  • List
  • Hierarchy


List

A type of custom setting that provides a reusable set of static data that can be accessed across your organisation.

For example you have a custom setting for Status Code. It has 2 fields:
Name (object Name field same as when you create a custom object)
Code (Text field)

How to access this List type custom setting in Apex:

// Method 1
// Returns a map of the data sets defined for the custom setting.
Map<String, Status_Code__c> mapStatusCodeCustomSetting = Status_Code__c.getAll();
for(Status_Code__c mandatoryRoles : mapStatusCodeCustomSetting.values()){
}

// Method 2
for(Status_Code__c mandatoryRoles : Status_Code__c.getAll().values()){
}

// Method 3    
Status_Code__c statusCodeCS = Status_Code__c.getValues('400');
String statusCode = statusCodeCS.Code__c;

// Method 4
String statusCode = Status_Code__c.getValues('400').Code__c;


Hierarchy

A type of custom setting that uses a built-in hierarchical logic that checks the organisation, profile, and user settings for the current user and returns the most specific, or “lowest,” value. 

How to access this Hierarchy type custom setting in Apex:

// Method 1
// Returns a custom setting data set record for the current user.
Authentication_Token_Setting__c authTokenSetting = Authentication_Token_Setting__c.getInstance();

// Method 2
// Returns the custom setting data set record for the specified User ID or Profile ID. 
Authentication_Token_Setting__c authTokenSetting = Authentication_Token_Setting__c.getInstance(Userinfo.getUserId());

// Method 3
// Returns the custom setting data set record for the organization.
Authentication_Token_Setting__c authTokenSetting = Authentication_Token_Setting__c.getOrgDefaults();

// Method 4
// Returns the custom setting data set record for the specified User ID or Profile ID.
Authentication_Token_Setting__c authTokenSetting = Authentication_Token_Setting__c.getValues(Userinfo.getUserId());

Note:

  • For Apex saved using Salesforce API version 21.0 or earlier, this method returns the custom setting data set  record with fields merged from field values defined at the lowest hierarchy level, starting with the user.  Also, if no custom setting data is defined in the hierarchy, this method returns null.
  • For Apex saved using Salesforce API version 22.0 or later, If no custom setting data is defined in the hierarchy, the returned custom setting has empty fields, except for the SetupOwnerId field which contains the user ID.


Benefits of Using Custom Setting:


  • Custom settings data is exposed in the application cache, which enables efficient access without the cost of repeated queries to the database.
  • Custom settings data can be used by formula fields, Visualforce, Apex, and the Force.com Web Services API.
  • You can make visibility of custom setting public or protected.


DON'T:

Don't query custom settings data using Standard Object Query Language (SOQL). It doesn't make use of the application cache and is similar to querying a custom object. 

Note: You can create up to 2 MB data in custom settings.



Use Static Resources to Create Custom Settings Data

// Publicly exposed Data Factory Class for Test class
@isTest
public class TestDataFactory{
    public static List<Status_Code__c> createStatusCodeCustomSettingByStaticResource(){
        // Create records for a custom setting Status_Code__c
        // using a sample .CSV file "StatusCodes" stored in Static Resource
        List<Status_Code__c> lstStatusCodeSetting = Test.loadData(Status_Code__c.sObjectType, 'StatusCodes');
        return lstStatusCodeSetting;
    }    
}

// Main Test Class to Test the functionality
@isTest
private class StatusCodeTest{
    @isTest
    static void testStatusCode(){
        // Call publicly exposed method of Test class to create data in a custom setting "Status_Code__c"
        // via CSV file stored in a Static Resource 
        List<Status_Code__c> lstStatusCodeSetting = TestDataFactory.createStatusCodeCustomSettingByStaticResource(); 
    }
}

Useful Resources:


Testing in Apex

“one unit test is infinitely better than no unit test”

Testing in Apex

Testing is an important part of the development process. Like other programming languages, Apex also provides a testing framework that allows you to write unit tests, run, check and have code coverage of your test results.
In Salesforce before you deploy Apex to your Salesforce.com Production organisation or package it for the Force.com AppExchange, you must have at least 75% of your Apex code covered by unit tests, and all of those tests must complete successfully. 

The most important point and advantage to create a separate class for Apex Test methods is that it does not count against your organisation limit of 3 MB for all Apex code. 

Apex Test Class Syntax:


// This class contains test methods with different data access levels.
@isTest
private class className{
    
    // Method 1
    static testMethod void methodName1(){
              // your logic here
    }
    
    // Method 2
    @isTest static void methodName2(){
              // your logic here
    }
    
    // Method 3
    @isTest (SeeAllData = true)
    static void methodName3(){
              // your logic here
    }
    
    // Method 4
    @isTest
    static void methodName4(){
              // your logic here
    }

}


// All test methods in this class can access all data of Salesforce organisation.
@isTest (SeeAllData = true)
private class className{
    
    // Method 1
    static testMethod void methodName1(){
              // your logic here
    }
    
    // Method 2
    @isTest
    static void methodName2(){
              // your logic here
    }
    Note: You don't need "@isTest (SeeAllData = true)" here because class has already been defined with the @isTest(SeeAllData=true) annotation.

}


First thing to notice is that we use the @isTest annotation. All classes marked with "@isTest" annotation will make classes to run in Testing context only. Also, you see we use "testMethod" keyword and "@isTest" annotation for defining methods within Test classes. Both are interchangeable the only difference is you can access your organisation's data by using "@isTest (SeeAllData = true)" annotation individually with the method.


Winter '12 Features for Apex Testing

With Winter '12 releaseForce.com platform provided you a capability to create Public test classes that expose common methods for test data creation. These public methods can be called by tests outside the test class for setting up data that the tests need to run against.

Methods of a public test class can only be called from a running test, that is, a test method or code invoked by a test method, and can't be called by a non-test request. 

// In this class you can create and expose records to called by other test classes
@isTest
public class TestDataFactory{

    public static Account createTestAccount(){
              // create test Account records
    }
    public static Contact createTestContact(){
              // create test Contact records
    }

}


Spring '12 Features for Apex Testing

Spring '12 release came with a feature "Isolation of Test Data for Unit Test". It means with Spring 12 release you can now explicitly mark your test class "@isTest (SeeAllData = true)" to access your Salesforce organisation data.

As we know all Salesforce metadata components associate to a particular Salesforce API version and every version has dependency based on features.

Spring '12 release came up with Salesforce API version 24.0 and announced that Apex code saved using Salesforce API version 24.0, test classes and methods don't have access by default to pre-existing data in the organisation. So, for Apex code saved using Salesforce API version 24.0 and later, use explicitly the @isTest(SeeAllData=true) annotation to grant test classes and individual test methods access to all data in the organisationBut Test code saved against Salesforce API version 23.0 or earlier continues to have access to all data in the organisation and its data access is unchanged.


Spring '15 Features for Apex Testing

Finally Spring '15 release has came up with a new annotation "@testSetup" which gives you ability to "Setup Test Data for Entire Class".
With Spring '15 release now you create common test records once and access them in every test method in the test class. All methods that are annotated with @testSetup will be called test setup methods.

Syntax for Test Setup Method (@testSetup annotation)

@isTest
private class className{

           @testSetup static void commonmethodName() {
                               // your logic here
           }

           // Method 1
           static testMethod void methodName1(){
                               // your logic here
           }
    
          // Method 2
          @isTest static void methodName2(){
                               // your logic here
          }

}

For further details of @testSetup method see here


Considerations:

  • Use the @isTest annotation to define classes and methods that only contain code used for testing your application. The @isTest annotation on methods is equivalent to the testMethod keyword.
  • Classes and methods defined as @isTest can be either private or public.
  • Classes defined as @isTest must be top-level classes.
  • Classes defined with the @isTest annotation don't count against your organisation limit of 3 MB for all Apex code. 
  • Classes defined as @isTest can't be interfaces or enums.
  • Methods of a public test class can only be called from a running test, that is, a test method or code invoked by a test method, and can't be called by a non-test request.
  • You must have at least 75% of the Apex code coverage in your organisation to be able to deploy the code to your Salesforce production organisation.

Useful Resources:

Enums in Apex (Salesforce)


Enums in Apex


Apex is probably the first on-demand programming language by Salesforce.com that provides easy, fast and robust ways to design, develop, test and deploy apps on Force.com platform. Apex is more similar to Java but it has some differences which makes it very unique programming language.

Apex also has Enums like we have in Java and other programming languages with some unique differences. 

Let's take an example: We need to send data FROM different objects of Salesforce TO some External 3rd party system.

Below is the code which gives you an idea that how we can use Enums here instead of using variables (e.g. to check the object type).



public class IntegrationImplementation{
    // Declare Enums
    public Enum serviceType {ACCOUNT, CONTACT}
    
    // a method to send Notification based on Object Type
    public static String sendNotification(IntegrationImplementation.serviceType objectType, Set<Id> objectIds){
        String resultCallOutNotification = '';
        // For Account
        if(objectType == serviceType.ACCOUNT){
            // logic here
        }
        // ... logic here for other object types
        return resultCallOutNotification;
    }
}

public class callOutExternalSystem{
    public static void sendAccountToExternalSystem(){
        Set<Id> setAccountIds = new Set<Id>();
        // For Account
        String resultNotification = IntegrationImplementation.sendNotification(IntegrationImplementation.serviceType.ACCOUNT, setAccountIds); 
    }
}

For further details:

Sunday, March 15, 2015

@testSetup - Create Common Test Data Efficiently

With Spring '15 release now you create common test records once and access them in every test method in the test class. All methods that are annotated with @testSetup will be called test setup methods.

Syntax for Test Setup Method (@testSetup annotation)
@testSetup static void methodName() {}

Let's take an example. You need to create an Account and a Contact record in Apex test classes (@isTest).


// Test Data Factory class
@isTest
public class TestDataFactory{
    public static Account createAccount(String accountName, String accountIndustry){
        Account acct = new Account();
            acct.Name = accountName;
            acct.Industry = accountIndustry;
        return acct;
    }     

    public static Contact createContact(String contactFirstName, String contactLastName, Account acct){
        Contact cont = new Contact();
            cont.FirstName = contactFirstName;
            cont.LastName = contactLastName;
            cont.AccountId = acct.Id;
        return cont;
    }
}


// Main Test class to create Account and Contact
@isTest
private class AccountContactTest{
    @testSetup static void setupCommonData(){
        Account acct = TestDataFactory.createAccount('Salesforce.com', 'Technology');
        insert acct;
        Contact cont = TestDataFactory.createContact('Marc', 'Benioff', acct);
        insert cont;
    }
    
    @isTest static void testMethodOne(){
        Account queryAccount = [SELECT Id, Name, Industry FROM Account WHERE Name = 'Salesforce.com' LIMIT 1];
        System.assertNotEquals(null, queryAccount);
        System.assertEquals('Salesforce.com', queryAccount.Name);
        System.assertEquals('Technology', queryAccount.Industry);
        
        queryAccount.Name = 'Facebook';
        update queryAccount;
        System.assertEquals('Facebook', queryAccount.Name);

        Contact queryContact = [SELECT Id, FirstName, LastName FROM Contact WHERE LastName = 'Benioff' LIMIT 1];
        System.assertNotEquals(null, queryContact);
        System.assertEquals('Marc', queryContact.FirstName);
        System.assertEquals('Benioff', queryContact.LastName); 
        
        queryContact.FirstName = 'Mark';
        queryContact.LastName = 'Zuckerberg';
        update queryContact;
        System.assertEquals('Mark', queryContact.FirstName);
        System.assertEquals('Zuckerberg', queryContact.LastName);        
    }

    @isTest static void testMethodTwo(){
        Account queryAccount = [SELECT Id, Name, Industry FROM Account WHERE Name = 'Salesforce.com' LIMIT 1];
        System.assertNotEquals(null, queryAccount);
        System.assertEquals('Salesforce.com', queryAccount.Name);
        System.assertEquals('Technology', queryAccount.Industry);
        
        queryAccount.Name = 'Google';
        update queryAccount;
        System.assertEquals('Google', queryAccount.Name);

        Contact queryContact = [SELECT Id, FirstName, LastName FROM Contact WHERE LastName = 'Benioff' LIMIT 1];
        System.assertNotEquals(null, queryContact);
        System.assertEquals('Marc', queryContact.FirstName);
        System.assertEquals('Benioff', queryContact.LastName); 
        
        queryContact.FirstName = 'Larry';
        queryContact.LastName = 'Page';
        update queryContact;
        System.assertEquals('Larry', queryContact.FirstName);
        System.assertEquals('Page', queryContact.LastName); 
    }    
} 

Note: All changes will be Rollback to the common setup data before starting a specific test method.

Benefits:


  • Create common test data easily and efficiently.
  • Reduce the number of lines of code.
  • Reduce test execution time.
  • It can be time-saving when you need to create a common set of records that all test methods depends on.
  • Use system resources more efficiently (Because now system would just need to roll back data from a single test method instead of roll back for each test method).

Considerations:


  • If a test class contains a test setup method, the test setup method executes first, before any test method in the class.
  • Records that are created in a test setup method are available to all test methods in the test class and are rolled back at the end of test class execution.
  • If a test method changes those records, such as record field updates or record deletions, those changes are rolled back after each test method finishes execution. The next executing test method gets access to the original unmodified state of those records.
  • It takes no arguments, and return no value. @testSetup static void methodName(){}
  • @testSetup method only works with the default data isolation mode "@isTest(SeeAllData=true)" for a test class.
  • It does not work with "@isTest(​SeeAllData=​true)". Because data isolation for tests is available for API versions 24.0 and later, test setup methods are also available for those versions only. Otherwise you will get an error: Test class containing a test setup method cannot be annotated with @isTest(​SeeAllData=​true)
  • Multiple @testSetup methods are allowed in a test class, but the order in which they’re executed by the testing framework isn’t guaranteed.
  • If a fatal error occurs during the execution of a @testSetup method, such as an exception that’s caused by a DML operation or an assertion failure, the entire test class fails, and no further tests in the class are executed.
  • If a @testSetup method calls a non-test method of another class, no code coverage is calculated for the non-test method. 

See further details for @testSetup method

Saturday, February 28, 2015

Play with Apex Collections


public class ApexCollectionConversion{

    /******************** FOR LIST **********************************************/
    public void convert_List_INTO_Set(){
        // Conver List into Set
        List<String> lstEnglishCapitalLetters = new List<String> {'A', 'B'};
        // Method 1:
        Set<String> setEnglishCapitalLetters = new Set<String>(lstEnglishCapitalLetters);
        // Method 2:
        setEnglishCapitalLetters.addAll(lstEnglishCapitalLetters); 
        // Method 3:
        for(String engLetter : lstEnglishCapitalLetters){
            setEnglishCapitalLetters.add(engLetter);
        }       
    }

    public void convert_List_INTO_Map(){
        // Conver List into Map
        // Method 1:
        List<String> lstEnglishSmallLetters = new List<String> {'a', 'b'};
        Map<String, String> mapEnglishSmallLetters = new Map<String, String>();
        for(String engLetter : lstEnglishSmallLetters){
            mapEnglishSmallLetters.put(engLetter, engLetter);
        }
        // Method 2:
        List<Account> lstAccounts = [SELECT Id, Name FROM Account WHERE Name = 'Salesforce'];
        Map<Id, Account> mapAccounts = new Map<Id, Account>(lstAccounts);
    }



    /******************** FOR SET **********************************************/

    public void convert_Set_INTO_List(){
        // Conver Set into List
        Set<String> setFruitsName = new Set<String>{'Apple', 'Orange'};
        // Method 1:
        List<String> lstFruitsName = new List<String>(setFruitsName);
        // Method 2:
        lstFruitsName.addAll(setFruitsName);
    }

    public void convert_Set_INTO_Map(){
        // Conver Set into Map
        Set<String> setVagetablesName = new Set<String>{'Potato', 'Carrot'};        
        Map<String, String> mapVagetablesName = new Map<String, String>();
        for(String vegetable : setVagetablesName){
            mapVagetablesName.put(vegetable, vegetable);
        }
    }    



    /******************** FOR MAP **********************************************/

    public void convert_Map_INTO_List(){
        // Conver Map into List
        Map<String, String> mapCountryAbbreviations = new Map<String, String>{'USA' => 'United States of America', 'UK' => 'United Kingdom'};
        List<String> lstCountryShortName = new List<String>(mapCountryAbbreviations.keySet());
        List<String> lstCountryFullName = new List<String>(mapCountryAbbreviations.values());
    }

    public void convert_Map_INTO_Set(){
        // Conver Map into Set
        Map<String, String> mapCityCodes = new Map<String, String>{'1001' => 'California', '1002' => 'London'};
        Set<String> setCountryShortName = new Set<String>(mapCityCodes.keySet());
        Set<String> setCountryFullName = new Set<String>(mapCityCodes.values());
    }    


}

Use Static Resources to create data in Test Classes (@isTest)

Use Static Resources to create data in Test Classes (@isTest)

Example 1:
// Test data preparation (from CSV file store in Static Resource)
// Load test data from static resource CSV into the DB
List<sObject> ls = Test.loadData(Account.sObjectType, 'myCsvResource');

Example 2:
// Test Data Factory class
@isTest
public class TestDataFactoryUtil{
    public static List<Custom_Setting__c> createCustomSettingValues(){
    // Create a sample .csv file "CustomSettingValues" and save it in Static Resource
    List<Custom_Setting__c> customSetting = Test.loadData(Custom_Setting__c.sObjectType,       'CustomSettingValues');
    return customSetting;
   }
}

// Main Test Data that is using Test Data Factory class
// Create records of custom setting "Custom_Setting__c"
List<Custom_Setting__c> customSettingValues = TestDataFactoryUtil.createCustomSettingValues();

Wednesday, June 12, 2013

Syncing Salesforce Quotes using Apex

Wondering how to sync quote with an opportunity using Apex? Did you tried updating the “IsSyncing” field and it showed an error saying field is not writable? If yes then here is the solution for you. At the Opportunity level you have a field named as “SyncedQuoteId” and if you update this field with the desired quote id, then salesforce automatically sync this quote with opportunity.

Opportunity.SyncedQuoteId = (desired) Quote.id;
update opportunity;

In the same way do you wanna sync your custom fields for quote and quote line item then here is the application from appexchange.

App Exchange App's:
Custom Quote Sync (Managed)

Custom Quote Sync (Unmanaged)

Tuesday, June 4, 2013

Integrate Custom Apex WebService with .Net Using Force.com SOAP API

This blog post will describe that how to create an Apex web service and integrate it with .Net App using Force.com SOAP API.

Below is an example of how to integrate Apex webservice with Force.com SOAP API and .Net Apps using Visual Studio.

To get started, we'll run through the following steps:

1) Create an Apex webService class

Apex Code:
/********************************************************************************/
global class SuperClass{
    global class RequestClass{
        webService String accountName;
    }
    global class ResponseClass{
        webService String responseResultID;
        webService String responseResultName;
        webService String responseResultRecordType;
    }
    webService static ResponseClass behaviourOfWebService(RequestClass reqClass){
        Account acct = new Account();
        acct.Name = reqClass.accountName;
        insert acct;
        ResponseClass resClass = new ResponseClass();
        resClass.responseResultID = acct.Id;
        resClass.responseResultName = acct.Name;
        resClass.responseResultRecordType = acct.RecordTypeId;
        return resClass;
    }
}
/********************************************************************************/

2) Download the "Enterprise WSDL" or "Partner WSDL" from your salesforce.com organization.

Log in into salesforce.com organization -> User Name ->  Setup -> App Setup section -> Develop -> API -> click on Generate Enterprise or Partner WSDL -> Save file with extension ".wsdl" as "EnterpriseWSDL.wsdl" or "PartnerWSDL.wsdl".

3) Download the Apex class "SuperClass" wsdl.

Log in into salesforce.com organization -> User Name ->  Setup -> App Setup section -> Develop -> Apex Classes-> click on SuperClass -> click Generate WSDL -> Save file with extension ".wsdl" as "WebServiceWSDL.wsdl".

4) Create a .Net App in Visual Studio

Open Visual Studio -> File -> New -> Project -> Visual C# -> Windows -> Console Application -> Name it "CustomWebService" -> OK

5) Copy the path where your both WSDL's are present.

For Example:
C:\Users\Administrator\Desktop\EnterpriseWSDL.wsdl
C:\Users\Administrator\Desktop\WebServiceWSDL.wsdl

6) Add these WSDL's as Web References in Visual Studio.

In Solution Explorer -> right click on project -> Add Web Reference -> add the path in URL for Enterprise WSDL -> Web reference name = EnterpriseWSDL -> click Add Reference.

For Example:
C:\Users\Administrator\Desktop\EnterpriseWSDL.wsdl

In Solution Explorer -> right click on project -> Add Web Reference -> add the path in URL for Apex Class WSDL -> Web reference name = WebServiceWSDL -> click Add Reference.

For Example:
C:\Users\Administrator\Desktop\WebServiceWSDL.wsdl

Your Project in Visual Studio will look like below screenshot:




















7) Write C# Code to integrate with Force.com Apex Web Service using Force.com SOAP API

C# Code:
/********************************************************************************/
using System;
using System.Collections.Generic;
using System.Text;

namespace CustomWebService
{
    class Program
    {
        static void Main(string[] args)
        {
            /*
            When I add WebReferences I named Apex Class WSDL as "WebServiceWSDL"
            When I add WebReferences I named Enterprise WSDL as "EnterpriseWSDL"
            */

            //Salesforce.com Credentials
            string userName = "Your User Name";
            string userPassword = "Your Password + Your Security Token";

            //Apex Main Class WSDL Object
            WebServiceWSDL.SessionHeader webServiceWSDLSession = new WebServiceWSDL.SessionHeader();

            //Enterprise WSDL Object
            EnterpriseWSDL.LoginResult enterpriseWSDLLoginResult = new EnterpriseWSDL.LoginResult();
            EnterpriseWSDL.SforceService enterpriseWSDLSforceService = new EnterpriseWSDL.SforceService();

            //Make Sessions and Login successfully
            enterpriseWSDLLoginResult = enterpriseWSDLSforceService.login(userName, userPassword);
            enterpriseWSDLSforceService.Url = enterpriseWSDLLoginResult.serverUrl;
            webServiceWSDLSession.sessionId = enterpriseWSDLLoginResult.sessionId;

            //Number of records to process
            int numOfRecords = 1;

            //Apex Inner Class RequestClass object to fill the variables of RequestClass and send it to Salesforce.com
            WebServiceWSDL.RequestClass reqClass = new WebServiceWSDL.RequestClass();
            WebServiceWSDL.RequestClass[] reqClassList = new WebServiceWSDL.RequestClass[numOfRecords];
         
            //Traverse each record
            for (int i = 0; i < numOfRecords; i++)
            {
                reqClass = new WebServiceWSDL.RequestClass();
                reqClass.accountName = "Account Name from Dot Net";
                reqClassList[i] = reqClass;
            }

            //Apex Main Class Object
            WebServiceWSDL.SuperClassService mainWSDLClassObject = new WebServiceWSDL.SuperClassService();
            mainWSDLClassObject.SessionHeaderValue = new WebServiceWSDL.SessionHeader();
            mainWSDLClassObject.SessionHeaderValue.sessionId = webServiceWSDLSession.sessionId;
            //mainWSDLClassObject.behaviourOfWebService(reqClassList[0]);

            //Retrieve the Response of Apex class
            WebServiceWSDL.ResponseClass responseClassObject = new WebServiceWSDL.ResponseClass();
            responseClassObject = mainWSDLClassObject.behaviourOfWebService(reqClassList[0]);

            //Response Result
            Console.WriteLine("ID" + responseClassObject.responseResultID);
            Console.WriteLine("NAME" + responseClassObject.responseResultName);
            Console.WriteLine("RECORD TYPE" + responseClassObject.responseResultRecordType);
            Console.ReadLine();

        }
    }
}
/********************************************************************************/

Integrate Custom Apex WebService with Java Using Force.com Web Services Connector (WSC)

This blog post will describe that how to create an Apex web service and integrate it with Java App using Force.com Web Services Connector (WSC).

Below is an example of how to integrate Apex webservice with Force.com SOAP API  and Java Apps using Eclipse IDE.

To get started, we'll run through the following steps:

1) Create an Apex webService class

Apex Code:
/********************************************************************************/
global class SuperClass{
    global class RequestClass{
        webService String accountName;
    }
    global class ResponseClass{
        webService String responseResultID;
        webService String responseResultName;
        webService String responseResultRecordType;
    }
    webService static ResponseClass behaviourOfWebService(RequestClass reqClass){
        Account acct = new Account();
        acct.Name = reqClass.accountName;
        insert acct;
        ResponseClass resClass = new ResponseClass();
        resClass.responseResultID = acct.Id;
        resClass.responseResultName = acct.Name;
        resClass.responseResultRecordType = acct.RecordTypeId;
        return resClass;
    }
}
/********************************************************************************/

2) You need to install "Java JDK (6 or 7)" in your machine.
3) Second you need to check whether "Java JDK (6 or 7)" has installed successfully or not?

Just type in the command prompt:
java -version

You will the result same as below:
It will show you:
java version "1.6.0_35"
Java(TM) SE Runtime Environment (build 1.6.0_35-b10-428-10M3811)
Java HotSpot(TM) 64-Bit Server VM (build 20.10-b01-428, mixed mode)

Note: If you get error then change your command prompt directory to the Java bin directory and test it again.

For Example:
C:\Program Files\Java\jdk1.6.0_45\bin> java -version

4) Download the "Enterprise WSDL" or "Partner WSDL" from your salesforce.com organization.

Log in into salesforce.com organization -> User Name ->  Setup -> App Setup section -> Develop -> API -> click on Generate Enterprise or Partner WSDL -> Save file with extension ".wsdl" as "enterprise.wsdl" or "partner.wsdl".

5) Download the Apex class "SuperClass" wsdl.

Log in into salesforce.com organization -> User Name ->  Setup -> App Setup section -> Develop -> Apex Classes-> click on SuperClass -> click Generate WSDL -> Save file with extension ".wsdl" as "mywebservice.wsdl".

6) Download the Web Services Connector (WSC) "wsc-20.jar" file from the URL "http://code.google.com/p/sfdc-wsc/downloads/list".

7) Now create JAR (Java ARchive) files for "enterprise.wsdl", "partner.wsdl" and "mywebservice.wsdl" files.

8) Copy the "tools.jar" file from the path where you have installed "Java JDK (6 or 7)".

For Example:
"C:\Program Files\Java\jdk1.6.0_45\lib\tools.jar" and paste it in your "E:\" drive. I am doing this just for safe side so we will not have any conflicts.

Note: 
(a) "tools.jar" and "wsc-20.jar" file both must be in the same directory otherwise, you will get an error "classpath: java.io.FileNotFoundException".
(b) Just for safe side I would recommend that your "E:\" drive must have "tools.jar", "wsc-20.jar", "enterprise.wsdl", "partner.wsdl" and "mywebservice.wsdl".

9) Execute the following commands in Command Prompt to generate JAR File "JAR file (Java ARchive)" for "enterprise.wsdl" or "partner.wsdl" and "mywebservice.jar".

For Example:
java -classpath wsc-XX.jar com.sforce.ws.tools.wsdlc enterprise.wsdl enterprise.jar

Real Example:
Generate enterprise.jar
java -classpath E:\tools.jar;E:\wsc-20.jar com.sforce.ws.tools.wsdlc E:\enterprise.wsdl E:\enterprise.jar

Generate partner.jar
java -classpath E:\tools.jar;E:\wsc-20.jar com.sforce.ws.tools.wsdlc E:\partner.wsdl E:\partner.jar

Generate mywebservice.jar
java -classpath E:\tools.jar;E:\wsc-20.jar com.sforce.ws.tools.wsdlc E:\mywebservice.jar.wsdl E:\mywebservice.jar

Now these commands will generate "enterprise.wsdl" or "partner.wsdl" and "mywebservice.jar".

Generate Java Code in Eclipse (Creating an Enterprise WSDL Application)

Now that your environment is ready to go, it's time to build a test application to see how things are working. Most developers build client applications with the enterprise WSDL, so we’ll start with that one first.
In Eclipse, complete the following steps to build a Java application based on the enterprise WSDL.
  1. Create a new Java project named “WSC - Enterprise” (click File | New | Java Project).
  2. Add the wsc-XX.jar and enterprise.jar to the project (click Project | Properties | Java Build Path | Libraries or External Libraries, then add the JARs to the project.
  3. Add a new folder, wsc, to the src folder in your app (right-click src in Package Explorer, then click New | Folder).
  4. Create a new class src/wsc/CallWS.java and paste in the code from the code listing that follows.
  5. Replace the stub user credentials in the code with your own user name and password with security token for the appropriate static members, then save your source code.
  6. Run the application.
Your Project in Eclipse IDE will look like below screenshot:
















Java Code:
/********************************************************************************/
package wsc;

import com.sforce.soap.SuperClass.SoapConnection;
import com.sforce.soap.SuperClass.Connector;
import com.sforce.soap.SuperClass.RequestClass;
import com.sforce.soap.SuperClass.ResponseClass;

import com.sforce.ws.ConnectionException;
import com.sforce.ws.ConnectorConfig;
import com.sforce.soap.enterprise.*;


public class CallWS {


  static final String USERNAME = "Your User Name";
  static final String PASSWORD = "You User Password + Your Security Token";

  static SoapConnection MyWebserviceWSconnection;
  static EnterpriseConnection enterpriseConnection;

  public static void main(String[] args) {

    ConnectorConfig config = new ConnectorConfig();
    config.setUsername(USERNAME);
    config.setPassword(PASSWORD);


    try {

      //create a connection to Enterprise API -- authentication occurs
      enterpriseConnection = com.sforce.soap.enterprise.Connector.newConnection(config);    
      // display some current settings
      System.out.println("Auth EndPoint: "+config.getAuthEndpoint());
      System.out.println("Service EndPoint: "+config.getServiceEndpoint());
      System.out.println("Username: "+config.getUsername());
      System.out.println("SessionId: "+config.getSessionId());


      //create new connection to exportData webservice -- no authentication information is included
      MyWebserviceWSconnection = Connector.newConnection("","");
      //include session Id (obtained from enterprise api) in exportData webservice
      MyWebserviceWSconnection.setSessionHeader(config.getSessionId());
      
      RequestClass reqClass = new RequestClass();
      reqClass.setAccountName("Account Created By Java Program");
      
      ResponseClass resClass = new ResponseClass();
      resClass = MyWebserviceWSconnection.behaviourOfWebService(reqClass);
      System.out.println("Record ID ---"+resClass.getResponseResultID());
      System.out.println("Record Name ---"+resClass.getResponseResultName());
      System.out.println("Record Record Type ---"+resClass.getResponseResultRecordType());

      //String result = MyWebserviceWSconnection.receiveData("test");
      //System.out.println("Result: "+result);


    } catch (ConnectionException e1) {
        e1.printStackTrace();
    }  
  }
}
/********************************************************************************/

Helpful Links:
http://wiki.developerforce.com/page/Introduction_to_the_Force.com_Web_Services_Connector
http://code.google.com/p/sfdc-wsc/downloads/list

http://boards.developerforce.com/t5/Java-Development/Trying-to-call-a-simple-Apex-Web-Service-method-from-Java/td-p/206407
http://boards.developerforce.com/t5/General-Development/How-to-Call-WebService-Method-in-Java/td-p/261755
http://kperisetla.blogspot.com/2011/09/creating-custom-apex-web-service-in.html
http://forums.crmsuccess.com/t5/forums/forumtopicprintpage/board-id/JAVA_development/message-id/5930/print-single-message/false
http://boards.developerforce.com/t5/Java-Development/Problem-Calling-Apex-WebService-from-Java/td-p/206637
http://stackoverflow.com/questions/11204614/access-salesforce-apex-soap-webservice-from-java

Monday, June 3, 2013

Integrate Force.com SOAP API with Java Apps Using Force.com Web Services Connector (WSC)

Services This blog post will describe you that how to integrate Salesforce - Force.com SOAP API with Java Apps.

Below is an example of how to integrate Force.com SOAP API with Java Apps using Eclipse IDE.

Introduction to the Force.com Web Services Connector

The Force.com Web Services Connector (WSC) is a code-generation tool and runtime library for use with Force.com Web services. WSC uses a high-performing Web services client stack implemented with a streaming parser. It is the preferred tool for working with salesforce.com APIs. You can write Java applications with WSC that utilize the Force.com SOAP API, Bulk API, and Metadata API. There are even runtime libraries that let you access the Force.com SOAP API from applications running on Google App Engine.

Using WSC, you can perform operations with a few lines of code that would take many more lines of code with other Web services clients.

This article provides an introduction to WSC. The WSC can be used to invoke any doc-literal wrapped Web service, but in this article we’ll focus on the SOAP API with both the enterprise and partner WSDLs, and the Metadata API. Along the way, you’ll learn how to get started with WSC, and see an example of a console application that demonstrates WSC functionality.

Introduction to Force.com
Force.com has several API's including:
  • Force.com SOAP (Simple Object Access Protocol) API
  • Force.com Metadata API
  • Force.com Bulk API
  • Force.com Streaming API
  • Force.com REST (Representational State Transfer) API
  • Force.com Chatter API
Preparing to Integrate Java Apps with Force.com APIs:
I am assuming you have some experience building Java applications with Force.com APIs.

To get started, we'll run through the following steps:

1) First you need to install "Java JDK (6 or 7)" in your machine.
2) Second you need to check whether "Java JDK (6 or 7)" has installed successfully or not?

Just type in the command prompt:
java -version

You will the result same as below:
It will show you:
java version "1.6.0_35"
Java(TM) SE Runtime Environment (build 1.6.0_35-b10-428-10M3811)
Java HotSpot(TM) 64-Bit Server VM (build 20.10-b01-428, mixed mode)

Note: If you get error then change your command prompt directory to the Java bin directory and test it again.

For Example:
C:\Program Files\Java\jdk1.6.0_45\bin> java -version

3) Download the "Enterprise WSDL" or "Partner WSDL" from your salesforce.com organization.

Log in into salesforce.com organization -> User Name ->  Setup -> App Setup section -> Develop -> API -> click on Generate Enterprise or Partner WSDL -> Save file with extension ".wsdl" as "enterprise.wsdl" or "partner.wsdl".

4) Download the Web Services Connector (WSC) "wsc-20.jar" file from the URL "http://code.google.com/p/sfdc-wsc/downloads/list".

5) Now create JAR (Java ARchive) files for "enterprise.wsdl" and "partner.wsdl" files.

6) Copy the "tools.jar" file from the path where you have installed "Java JDK (6 or 7)".

For Example:
"C:\Program Files\Java\jdk1.6.0_45\lib\tools.jar" and paste it in your "E:\" drive. I am doing this just for safe side so we don't have any conflicts.

Note: 
(a) "tools.jar" and "wsc-20.jar" file both must be in the same directory otherwise, you will get an error "classpath: java.io.FileNotFoundException".
(b) Just for safe side I would recommend that your "E:\" drive must have "tools.jar", "wsc-20.jar", "enterprise.wsdl" and "partner.wsdl".

6) Execute the following command to generate JAR File "JAR file (Java ARchive)" for "enterprise.wsdl" or "partner.wsdl".

For Example:
java -classpath wsc-XX.jar com.sforce.ws.tools.wsdlc enterprise.wsdl enterprise.jar

Real Example:
Generate enterprise.jar
java -classpath E:\tools.jar;E:\wsc-20.jar com.sforce.ws.tools.wsdlc E:\enterprise.wsdl E:\enterprise.jar

Generate partner.jar
java -classpath E:\tools.jar;E:\wsc-20.jar com.sforce.ws.tools.wsdlc E:\partner.wsdl E:\partner.jar

Now these commands will generate "enterprise.wsdl" or "partner.wsdl".

Generate Java Code in Eclipse (Creating an Enterprise WSDL Application)

Now that your environment is ready to go, it's time to build a test application to see how things are working. Most developers build client applications with the enterprise WSDL, so we’ll start with that one first.
In Eclipse, complete the following steps to build a Java application based on the enterprise WSDL.
  1. Create a new Java project named “WSC - Enterprise” (click File | New | Java Project).
  2. Add the wsc-XX.jar and enterprise.jar to the project (click Project | Properties | Java Build Path | Libraries or External Libraries, then add the JARs to the project.
  3. Add a new folder, wsc, to the src folder in your app (right-click src in Package Explorer, then click New | Folder).
  4. Create a new class src/wsc/Main.java and paste in the code from the code listing that follows.
  5. Replace the stub user credentials in the code with your own user name and password with security token for the appropriate static members, then save your source code.
  6. Run the application.
Your Project in Eclipse IDE will look like below screenshot:










/********************************************************************************/
package wsc;

import com.sforce.soap.enterprise.Connector;
import com.sforce.soap.enterprise.DeleteResult;
import com.sforce.soap.enterprise.EnterpriseConnection;
import com.sforce.soap.enterprise.Error;
import com.sforce.soap.enterprise.QueryResult;
import com.sforce.soap.enterprise.SaveResult;
import com.sforce.soap.enterprise.sobject.Account;
import com.sforce.soap.enterprise.sobject.Contact;
import com.sforce.ws.ConnectionException;
import com.sforce.ws.ConnectorConfig;

public class Main {

static final String USERNAME = "YOUR-USERNAME";
static final String PASSWORD = "YOUR-PASSWORD&SECURITY-TOKEN";
  static EnterpriseConnection connection;

  public static void main(String[] args) {

    ConnectorConfig config = new ConnectorConfig();
    config.setUsername(USERNAME);
    config.setPassword(PASSWORD);
    //config.setTraceMessage(true);
 
    try {
   
      connection = Connector.newConnection(config);
   
      // display some current settings
      System.out.println("Auth EndPoint: "+config.getAuthEndpoint());
      System.out.println("Service EndPoint: "+config.getServiceEndpoint());
      System.out.println("Username: "+config.getUsername());
      System.out.println("SessionId: "+config.getSessionId());
   
      // run the different examples
      queryContacts();
      createAccounts();
      updateAccounts();
      deleteAccounts();
   
   
    } catch (ConnectionException e1) {
        e1.printStackTrace();
    }

  }

  // queries and displays the 5 newest contacts
  private static void queryContacts() {
 
    System.out.println("Querying for the 5 newest Contacts...");
 
    try {
     
      // query for the 5 newest contacts    
      QueryResult queryResults = connection.query("SELECT Id, FirstName, LastName, Account.Name " +
      "FROM Contact WHERE AccountId != NULL ORDER BY CreatedDate DESC LIMIT 5");
      if (queryResults.getSize() > 0) {
        for (int i=0;i<queryResults.getRecords().length;i++) {
          // cast the SObject to a strongly-typed Contact
          Contact c = (Contact)queryResults.getRecords()[i];
          System.out.println("Id: " + c.getId() + " - Name: "+c.getFirstName()+" "+
              c.getLastName()+" - Account: "+c.getAccount().getName());
        }
      }
   
    } catch (Exception e) {
      e.printStackTrace();
    }  
 
  }

  // create 5 test Accounts
  private static void createAccounts() {
 
    System.out.println("Creating 5 new test Accounts...");
    Account[] records = new Account[5];
 
    try {
     
      // create 5 test accounts
      for (int i=0;i<5;i++) {
        Account a = new Account();
        a.setName("Test Account "+i);
        records[i] = a;
      }
   
      // create the records in Salesforce.com
      SaveResult[] saveResults = connection.create(records);
   
      // check the returned results for any errors
      for (int i=0; i< saveResults.length; i++) {
        if (saveResults[i].isSuccess()) {
          System.out.println(i+". Successfully created record - Id: " + saveResults[i].getId());
        } else {
          Error[] errors = saveResults[i].getErrors();
          for (int j=0; j< errors.length; j++) {
            System.out.println("ERROR creating record: " + errors[j].getMessage());
          }
        }  
      }
   
    } catch (Exception e) {
      e.printStackTrace();
    }  
 
  }
}
/********************************************************************************/
Helpful Links:
http://wiki.developerforce.com/page/Introduction_to_the_Force.com_Web_Services_Connector
http://code.google.com/p/sfdc-wsc/downloads/list

http://boards.developerforce.com/t5/Java-Development/Trying-to-call-a-simple-Apex-Web-Service-method-from-Java/td-p/206407
http://boards.developerforce.com/t5/General-Development/How-to-Call-WebService-Method-in-Java/td-p/261755
http://kperisetla.blogspot.com/2011/09/creating-custom-apex-web-service-in.html
http://forums.crmsuccess.com/t5/forums/forumtopicprintpage/board-id/JAVA_development/message-id/5930/print-single-message/false
http://boards.developerforce.com/t5/Java-Development/Problem-Calling-Apex-WebService-from-Java/td-p/206637
http://stackoverflow.com/questions/11204614/access-salesforce-apex-soap-webservice-from-java