Sunday, 4 November 2018

Force.com Integrations

Integrations :
==============
Force.com offers excellent support for integration with other platforms.

outbound :
==========
On the outbound side making callouts ,it supports both SOAP and REST ,or you can use direct web requests using Get or Post.

your ability to make callouts depends on the execution context.For example you cannot make callouts during a trigger.

Note : However,there is no limit to the number of callouts you can make over a 24-hour period.

Inbound :
==========

The salesforce Platform supports many different APIs that external applications and services can use to call into your organization.

1.Standard APIs

 Metadata ,Tooling and Apex APIs    :
===========================
The metadata API allows you to import, export and modify system metadata.

The Tooling API and Apex APIs also allows you to work with metadata but are particularly intended for use by external developer tools allowing you,for example,to run unit tests and review code coverage results.

 Analytics API  :
==============

The analytics API allows you to run reports and view the resulting data sets.

Streaming and Bulk APIs :
=====================

The streaming API allows you to subscribe to an org and watch for changes in org data.

The bulk API provides a mechanism for transferring large amounts of data to and from an org.

 Partner API,REST API and Enterprise APIs :
=================================

The partner API,REST API and Enterprise APIs allow external applications to perform direct operations on your organization data much as you would in Apex.

They can query for describe information to find out about the objects and fields defined in an org.

They can query and search for data.They can perform DML operations to retrieve,set and delete data.

The partner API is a SOAP API whose WSDL you can obtain using the API settings in your
salesforce org.

The REST API has comparable functionality for those who prefer to use REST instead
of SOAP.

Note : REST API is newer and may not support all of the features of the platform API,nor does anyone guarantee that every feature in the REST API is implemented in the partner API.


The Enterprise API is also SOAP based, but the WSDL it generates is specific to the organization from which it is downloaded.

it reflects the organization's metadata,and this provides data types that correspond to the specific objects,fields and metadata in an organization

This can simplify the external programming considerably as the generated proxy
object will contain elements that correspond exactly to the objects and fields in the specific org.

Note : we Typically prefer to use the Enterprise API when writing an external application that is specific to one org or customer.

The partner API when creating external applications designed to work with salesforce orgs in general.



Partner,Enterprise and REST API :
=========================
Partner API

soap
describe,query,DML on any org.

Rest API

HTTP/REST

Describe,query,DML on any org

Enterprise API

SOAP
Describe,query,DML on specific org.

Custom API :
=============
Define your own SOAP or REST
endpoints using Apex.

Thursday, 1 November 2018

Custom Settings vs Custom Metadata in Salesforce


Custom Settings :
===============

You can deploy the custom setting definition between orgs,but the data must be transferred separately.

Records can be created,modified and deleted using Apex DML.

Preferred for managed packages and scenarios with custom configuration UI in visualForce or Lightning.

Custom Metadata :
================

You can deploy the custom metadata types and the custom metadata records between orgs.

Records can be created,modified and deleted from the UI or metadata API-but not through Apex.

Preferred for development in specific organizations where custom configuration UI is not required.

Saturday, 6 October 2018

Lightning Component For Custom RecordType Selection

Apex Controller:

Here, we are getting List of RecordTpes from Account Object.

public class RecordTypeSelectorController {
 
    @AuraEnabled
    public static List<RecordType> getListOfRecordType(){
        String query = 'SELECT Id,Name FROM RecordType WHERE SobjectType =\''+'Account'+'\' ';
        List<RecordType> rtNames = new List<RecordType>();
        Schema.SObjectType  objType = Account.SObjectType;     
        for(RecordTypeInfo rt : objType.getDescribe().getRecordTypeInfos()){
            System.debug('rt.getName()'+rt.getName());
            rtNames.add(new RecordType(Id = rt.getRecordTypeId(),Name = rt.getName()));
            System.debug('rtNames'+rtNames);
        } 
        return rtNames; 
    }
}


Lightning Component:

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes" controller="RecordTypeSelectorController" access="global">
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" access="public"/>
    <aura:attribute name="recordTypes" type="String[]" access="public"/>
    <div class="slds">
        <div class="demo-only" style="height: 640px;" id="newClientSectionId">
            <section role="dialog" tabindex="-1" aria-labelledby="modal-heading-01" aria-modal="true" aria-describedby="modal-content-id-1" class="slds-modal slds-fade-in-open">
                <div class="slds-modal__container">
                    <header class="slds-modal__header">
                        <button class="slds-button slds-button_icon slds-modal__close slds-button_icon-inverse" title="Close">
                            <lightning:icon iconName="utility:clear" size="small" alternativeText="Indicates approval"/> 
                            <span class="slds-assistive-text">Close</span>
                        </button>
                        <h2 id="modal-heading-01" class="slds-text-heading_medium slds-hyphenate">RecordType Selection</h2>
                    </header>
                    <div class="slds-modal__content slds-p-around_medium" id="modal-content-id-1">
                        <aura:iteration items="{!v.recordTypes}" var="rt">
                            <ol class="slds-list--vertical slds-list--vertical-space">
                                <input type="radio" value="{!rt.Name}" name="recordTypeRadio" id="{!rt.Id}" style="margin-right: 5px;" />{!rt.Name}
                            </ol> 
                        </aura:iteration>
                    </div>
                    <footer class="slds-modal__footer">
                        <button class="slds-button slds-button_brand" onclick="{!c.createRecordFun}">Next</button>
                    </footer>
                </div>
            </section>
            <div class="slds-backdrop slds-backdrop_open"></div>
        </div>
    </div>

</aura:component>

JavaScript Controller:

Here, we are using force:createRecord event. This event tells app to use standared create record page.

({
    createRecordFun : function (component, event, helper) {
        var rtDet = document.querySelector('input[name="recordTypeRadio"]:checked');
        if(rtDet != null) {
            document.getElementById("newClientSectionId").style.display = "none" ;
            var createRecordEvent = $A.get("e.force:createRecord");
            createRecordEvent.setParams({
                "entityApiName": "Account",
                "recordTypeId":rtDet.id
            });
            createRecordEvent.fire();
        } 
    },
    doInit : function(component, event, helper) { 
        helper.RecordTypeSelectorController(component); 
    }

})

JavaScript Helper:

({
   RecordTypeSelectorController: function(component) {
    var action = component.get("c.getListOfRecordType");
    action.setCallback(this, function(actionResult) {
        var infos = actionResult.getReturnValue();
        component.set("v.recordTypes", infos);
    });
    $A.enqueueAction(action);
  }

})

Note :

This force:createRecord event is handled by the one.app container.It's supported in Lightning Experience and salesforce1 only.This event presents a standard page to create a record.

Lightning:recordForm


"Lightning:recordForm" which suppresses using "lightning:recordEditForm and lightning:recordViewForm" separately to handle record view and edit.

"lightning:recordForm" is very powerful component for editing,viewing and adding
a record in lightning.

<aura:attribute name="fieldArray" type="String[]"
default="['Name','Email','Phone','AccountId']"/>

<lightning:recordForm aura:id="recordForm"
recordId="{!v.recordId}"
objectApiName="contact"
fields="{!v.fieldArray}"/>

Note : "ObjectApiName" is always required while using lightning:recordForm component.

Lightning Component Facets


A facet attribute is similar to any other component attributes,but instead of having a
primitive,collection,sObject or custom class type,it has an "Aura.Component[]" type.
And instead of holding those kind of data,it will hold HTML markups or even another
component.

Note :
A facet is implicitly defined in each component, the body facet.When we reference a subcomponent
writing some HTML markups between the tags that include the component into the container,
we are implicitly setting the body facet.

ex :

<!-- <c:SubComponent> -->


<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global" >
    <aura:attribute name="topArea" type="Aura.Component[]"/>
    <aura:attribute name="leftArea" type="Aura.Component[]"/>
    <aura:attribute name="rightArea" type="Aura.Component[]"/>
    <aura:attribute name="bottomArea" type="Aura.Component[]"/>
    <div class="mytop">
        {!v.topArea}
    </div>
    <div class="mymiddle">
        <div class="myleft">
            {!v.leftArea}
        </div>
        <div class="myright">
            {!v.rightArea}
        </div>
    </div>   
    <div>
        I am the body!: {!v.body}
    </div>
     <div class="mybottom">
        {!v.bottomArea}
    </div>
</aura:component>

<!--<c:BottomComponent/> -->

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global" >
<p>Bottom Area Component html text</p>
</aura:component>

<!--<c:ParentContainer/> -->

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global" >
    <c:SubComponent>
    <aura:set attribute="topArea">
        <h1>Top Area component</h1>
    </aura:set>
    <aura:set attribute="leftArea">
        <ul>
            <li>Left area app</li> 
            <li>Left area Menu</li> 
            <li>left area App Builder</li> 
        </ul>
    </aura:set>
    <aura:set attribute="rightArea">
            <p>Right area !</p>
        </aura:set>
        <aura:set attribute="bottomArea">
           <c:BottomComponent></c:BottomComponent>
        </aura:set>
    </c:SubComponent>
</aura:component>

Sunday, 26 August 2018

State Management In Batch Apex in Salesforce

State Management In Batch Apex in Salesforce


Each execution of a batch Apex job is considered a discrete transaction. For example, a batch Apex job that contains 1,000 records and is executed without the optional scope parameter is considered five transactions of 200 records each.

If you specify Database.Stateful in the class definition, you can maintain state across these transactions. This is useful for counting or summarizing records as they're processed. For example, suppose your job processed opportunity records. You could define a method in execute to aggregate totals of the opportunity amounts as they were processed.
If you do not specify Database.Stateful, all member variables in the interface methods are set back to their original values.
The following example summarizes a custom field total__c as the records are processed:

global class SummarizeAccountTotal implements Database.Batchable<sObject>, Database.Stateful{
global final String Query;
global integer Summary;
global SummarizeAccountTotal(String q){Query=q;
Summary = 0;
}

global Database.QueryLocator start(Database.BatchableContext BC){
return Database.getQueryLocator(query);
}

global void execute(Database.BatchableContext BC, List<sObject> scope){
for(sObject s : scope){Summary = Integer.valueOf(s.get('total__c'))+Summary;

}
}

global void finish(Database.BatchableContext BC){

}
}