Sunday, 14 October 2018
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.
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){
}
}
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){
}
}
Database.Callouts
Database.Allowscallouts allows us to use a callout in batch Apex.Callouts include HTTP
requests as well as methods defined with the webservice keyword.
How to make webservice callout from scheduler
scenario-1 : if scheduler doesn't depends on Batch or Queueable(depends on future methods)
scenario-2 : If Scheduler depends on Batch
scenario-3 : If Scheduler depends on Queueable
Note :
if we try to make a call from scheduler,we will get the below exception:
system.calloutException: callout form scheduled Apex not supported
Reason : All we know that we cannot schedule a class which contains callout.
The only solution for this is to use @future annotation to enforce(for Normal apex classes)
but we cannot process future methods inside batch.
Scenario -1 :
if scheduler doesn't depends on Batch or queueable
ex :
//Scheduled Apex
public class DemoScheduler1 implements Schedulable{
public void execute(SchedulableContext sc){
system.debug('*******Going to call future method ');
DemoAsynchronousTest.futureMethodCallFromScheduler();
}
}
//apex class containing future method
public class DemoAsynchronousTest{
@future
public static void futureMethodCallFromScheduler(){
system.debug('******futureMethodCallFromScheduler get called');
}
}
Scenario -2 :
if scheduler depends on Batch
ex :
public class ExampleScheduler implements Schedulable, Database.AllowsCallouts, Database.Batchable<sObject> {
public void execute(SchedulableContext SC) {
Database.executebatch(new ExampleScheduler());
}
public Iterable<sObject> start(Database.Batchablecontext BC){
ExampleHelper.makeWebserviceCallout();
return null;
}
public void execute(Database.BatchableContext BC, List<sObject> scope){
}
public void finish(Database.BatchableContext info){
}
}
public class ExampleHelper{
public static void makeWebserviceCallout(){
HttpRequest req = new HttpRequest();
req.setEndpoint('http://www.yahoo.com');
req.setMethod('GET');
String username = 'myname';
String password = 'mypwd';
Blob headerValue = Blob.valueOf(username + ':' + password);
String authorizationHeader = 'BASIC ' +
EncodingUtil.base64Encode(headerValue);
req.setHeader('Authorization', authorizationHeader);
// Create a new http object to send the request object
// A response object is generated as a result of the request
Http http = new Http();
HTTPResponse res = http.send(req);
System.debug(res.getBody());
}
}
Scenario-3 :
if scheduler depends on queueable
public class ExampleScheduler implements Schedulable{
public void execute(SchedulableContext SC) {
System.enqueueJob(new ExampleQueueable());
}
}
public class ExampleQueueable implements Queueable, Database.AllowsCallouts {
public void execute(QueueableContext context) {
ExampleHelper.makeWebserviceCallout();
}
}
or
global class SampleCalloutCls implements Queueable, Schedulable, Database.AllowsCallouts{
//variable declaration
private List<Account> accountList ;
//Queueable interface method
public void execute(QueueableContext QC){
// Perform callout here to get the accounts from external system.
//Calling batch process if list contains records.
if(!accountList.isEmpty()){
Database.executeBatch(new SampleBatchCls(accountList));
}
}
//Method to Schedule the current class
global void execute(SchedulableContext sc) {
system.enqueueJob(new SampleCalloutCls());
}
}
//End of class
requests as well as methods defined with the webservice keyword.
How to make webservice callout from scheduler
scenario-1 : if scheduler doesn't depends on Batch or Queueable(depends on future methods)
scenario-2 : If Scheduler depends on Batch
scenario-3 : If Scheduler depends on Queueable
Note :
if we try to make a call from scheduler,we will get the below exception:
system.calloutException: callout form scheduled Apex not supported
Reason : All we know that we cannot schedule a class which contains callout.
The only solution for this is to use @future annotation to enforce(for Normal apex classes)
but we cannot process future methods inside batch.
Scenario -1 :
if scheduler doesn't depends on Batch or queueable
ex :
//Scheduled Apex
public class DemoScheduler1 implements Schedulable{
public void execute(SchedulableContext sc){
system.debug('*******Going to call future method ');
DemoAsynchronousTest.futureMethodCallFromScheduler();
}
}
//apex class containing future method
public class DemoAsynchronousTest{
@future
public static void futureMethodCallFromScheduler(){
system.debug('******futureMethodCallFromScheduler get called');
}
}
Scenario -2 :
if scheduler depends on Batch
ex :
public class ExampleScheduler implements Schedulable, Database.AllowsCallouts, Database.Batchable<sObject> {
public void execute(SchedulableContext SC) {
Database.executebatch(new ExampleScheduler());
}
public Iterable<sObject> start(Database.Batchablecontext BC){
ExampleHelper.makeWebserviceCallout();
return null;
}
public void execute(Database.BatchableContext BC, List<sObject> scope){
}
public void finish(Database.BatchableContext info){
}
}
public class ExampleHelper{
public static void makeWebserviceCallout(){
HttpRequest req = new HttpRequest();
req.setEndpoint('http://www.yahoo.com');
req.setMethod('GET');
String username = 'myname';
String password = 'mypwd';
Blob headerValue = Blob.valueOf(username + ':' + password);
String authorizationHeader = 'BASIC ' +
EncodingUtil.base64Encode(headerValue);
req.setHeader('Authorization', authorizationHeader);
// Create a new http object to send the request object
// A response object is generated as a result of the request
Http http = new Http();
HTTPResponse res = http.send(req);
System.debug(res.getBody());
}
}
Scenario-3 :
if scheduler depends on queueable
public class ExampleScheduler implements Schedulable{
public void execute(SchedulableContext SC) {
System.enqueueJob(new ExampleQueueable());
}
}
public class ExampleQueueable implements Queueable, Database.AllowsCallouts {
public void execute(QueueableContext context) {
ExampleHelper.makeWebserviceCallout();
}
}
or
global class SampleCalloutCls implements Queueable, Schedulable, Database.AllowsCallouts{
//variable declaration
private List<Account> accountList ;
//Queueable interface method
public void execute(QueueableContext QC){
// Perform callout here to get the accounts from external system.
//Calling batch process if list contains records.
if(!accountList.isEmpty()){
Database.executeBatch(new SampleBatchCls(accountList));
}
}
//Method to Schedule the current class
global void execute(SchedulableContext sc) {
system.enqueueJob(new SampleCalloutCls());
}
}
//End of class
Thursday, 23 August 2018
Differences between Enterprise and Parter WSDL
Enterprise WSDL
1.Is strongly typed
2.Contains the metadata about all standard and custom fields and objects
3.Can only be used against your Salesforce instance
Partner WSDL
1.Is loosely typed
2.Takes an array of key-value pairs
3.Does not contain metadata about objects and fields
4.Can be used against many Salesforce.com organizations
Subscribe to:
Posts (Atom)
