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

Tuesday, 22 May 2018

Converting Curl Request into Apex HTTP Request #Salesforce

Recently in a project I was working with a requirement, where we need to integrated Salesforce with that system, when I started going through the API documentation of the another system, they have provided everything with the curl request and response was in JSON.




So many of you guys might have already explored curl and converting the request as per another system requirement, but for me this was the first time. So if any of you have better approach then the one I am going to explain, please let me know.

So What is Curl ?

"cURL is a command line tool for getting or sending files using URL syntax.
Since cURL uses libcurl, it supports a range of common Internet protocols, currently including HTTP, HTTPS, FTP, FTPS, SCP, SFTP, TFTP, LDAP, DAP, DICT, TELNET, FILE, IMAP, POP3, SMTP and RTSP.
cURL supports HTTPS and performs SSL certificate verification by default when a secure protocol is specified such as HTTPS. When cURL connects to a remote server via HTTPS".

Wiki Link

So here is of the curl request that I was dealing with, and I have taken a normal one which can be easily converted to apex.


So in above request the main thing to be taken care is to identify the parameter, header, body, method and endpoint. To identify these you need to look for -X -u -d -H

-x stands for request method
-u stands for authorization header
-d stands for body of the request
-H also stands for header

So by knowing the parameter defined in the curl request you can easily and quickly create a request in apex. So the request in apex format looks like below




So here is an small description of curl request formatting.
Thank you!

Sunday, 28 August 2016

Delete Duplicate Records Having Same External Id #Salesforce

Hey everyone, if you find a situation where there is duplicate data having a unique field in common, and you want to delete all and let the unique record be in the org, then this below apex is for you, I am using external Id field which is not unique, which is common in duplicate records.

We have many tools to handle duplicates on creation but few to remove duplicates.

So the scenario is I have below data

Account Name         External Id
Chris x                      12345
Chris x                      12345
Chris x                      12345

After running the code we will have

Account Name       External Id
Chris x                    12345


Here is the below code, you can do tweeks according to you scenario

      //Collections that we are using  
      Map<String, List<Id>> mapsOfAccountOfAccount = new Map<String, List<Id>>();  
      List<Account> accountToDelete = new List<Account>();  
      //Looping through the accounts records which has external ID  
      for(Account ac : [Select Id, External_Salesforce_Id__c From Task Where External_Salesforce_Id__c != null]) {  
           //Creating a map with External as key and list of duplicate records in values  
           if(mapsOfAccount.containsKey(ac.External_Salesforce_Id__c)) {  
                mapsOfAccount.get(ac.External_Salesforce_Id__c).add(ts.Id);  
           } else {  
                mapsOfAccount.put(ac.External_Salesforce_Id__c, new Set<Id>{ac.Id});  
           }       
      }  
      //Here we are populating a list with those records that we want to delete  
      for(String ky : mapsOfAccount.keySet()) {  
           integer i=0;  
           for(Id ids : mapsOfAccount.get(ky)) {  
                if(i>0)     {  
                     //Create and instance of the records to delete and add to list  
                     accountToDelete.add(new Account(Id = ids));  
                }  
                i++;  
           }  
      }  
      delete accountToDelete;  


Hope it helps someone
Thank you

Tuesday, 9 August 2016

Description and Resolution of System.SObjectException: Field is not writeable

Was working on the apex, and found this error, its a System exception, so you cannot handle it easily until you resolved it.

So basically this error comes when you are trying to re-assign the parent record on child object, in a master detail relationship.

For the resolution you can do "Allow  reparenting" is one of the resolution by which in the apex you can re-assign the parent field.

You can go to the child object and on the master-detail field, and check Allow reparenting.




Thank you.!!

Thursday, 17 December 2015

Bootstrap Modal Using AngularJS and Javascript in #Salesforce

This blog is about using bootstrap modal using AngularJS and Javascript, there are two different ways of using the modal and fetching the values from the modal.

I have added few fields in the modal and accessing the fields from the modal using two different buttons, below are the buttons

Modals code is same but only the function of fetching the values is different.
Here is how the modal looks


Here is the code of the page with the modal code and accessing the values of the modal in different ways.
Check out the code and if any issue or queries just comment I would be happy to help.

1:  <apex:page sidebar="false" showHeader="false" docType="html-5.0" standardStylesheets="false" applyBodyTag="false" applyHtmlTag="false">  
2:    <html lang="en">  
3:      <title>Manage Users</title>  
4:      <head>  
5:        <meta charset="utf-8"></meta>  
6:        <meta name="viewport" content="width=device-width, initial-scale=1"></meta>  
7:        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"></link>  
8:        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>  
9:        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>  
10:        <script>  
11:          $(document).on("click","#myReset",function() {  
12:            $('#myModal').modal('hide');  
13:          });  
14:          //click to save data filled in the modal using javascript  
15:          $(document).on("click", "#btnCreateContact", function(event){  
16:            var fn = document.getElementById("firstname").value;  
17:            var ln = document.getElementById("lastname").value;  
18:            var ph = document.getElementById("phone").value;  
19:            var em = document.getElementById("email").value;  
20:            var title = document.getElementById("title").value;  
21:            if(em == '' || ln == '' || fn == '' || title == '') {  
22:              alert('First Name, Last Name, Email and Title are required.');  
23:            } else {  
24:              //calling remote action  
25:              YOUR_APEX_CLASS.REMOTE_ACTION_METHOD(fn, ln, em, title, ph, function(response,event) {   
26:                $('#myModal').modal('hide');    
27:                if (event.status) {  
28:                  //debugger;   
29:                  if (response == null || response == '') {  
30:                    //Reload window and close modal  
31:                    //window.location.assign(window.location.href);  
32:                    window.location.reload(true);  
33:                    $('#myModal').modal('hide');  
34:                  } else {  
35:                    $('#myModal').modal('hide');  
36:                    alert(response);  
37:                    window.location.reload(true);  
38:                  }  
39:                } else {  
40:                  $('#myModal').modal('hide');  
41:                  alert(event.message);  
42:                  window.location.reload(true);  
43:                }  
44:              },{escape:false, buffer: false});  
45:            }  
46:          });  
47:          // USING ANGULAR NOW  
48:          //Initialling controller  
49:          myapp.controller('MainController',['$q','$log','$scope',function($q,$log,$scope){  
50:            $scope.firstname = '';  
51:            $scope.lastname = '';  
52:            $scope.phone = '';  
53:            $scope.email = '';  
54:            $scope.title = '';  
55:            //CALL REMOTE ACTION METHOD   
56:            MY_CLASS_NAME.REMOTE_ACTION(firstname, lastname, phone, email, title, function(response,event) {   
57:              // DO YOUR STUFF HERE  
58:            });  
59:          }]);  
60:         </script>  
61:      </head>  
62:       <!-- Modal -->  
63:       <div class="modal fade" id="myModal">  
64:        <div class="modal-dialog">  
65:         <!-- Modal content-->  
66:         <div class="modal-content">  
67:          <div class="modal-header">  
68:           <button type="button" class="close" data-dismiss="modal">&times;</button>  
69:           <h4 class="modal-title">Contact Details</h4>  
70:          </div>  
71:            <div class="col-xs-12 form-group">  
72:            </div>  
73:            <div class="col-xs-12 form-group">  
74:              <label>First Name<font color="red">*</font></label>  
75:              <input class="form-control" id="firstname" value="" ng-model="firstname"/>  
76:            </div>  
77:            <div class="col-xs-12 form-group">  
78:              <label>Last Name<font color="red">*</font></label>  
79:              <input class="form-control" id="lastname" value="" ng-model="lastname"/>  
80:            </div>  
81:            <div class="col-xs-12 form-group">  
82:              <label>Email<font color="red">*</font></label>  
83:              <input class="form-control" id="email" value="" ng-model="email"/>  
84:            </div>  
85:            <div class="col-xs-12 form-group">  
86:              <label>Title<font color="red">*</font></label>  
87:              <input class="form-control" id="title" value="" ng-model="title"/>  
88:            </div>  
89:            <div class="col-xs-12 form-group">  
90:              <label>Phone</label>  
91:              <input class="form-control phone" id="phone" onchange="formatPhone(this);" ng-model="phone"/>  
92:            </div>  
93:            <div class="btn-group" align="center">  
94:              <button id="btnCreateContact" class="btn btn-primary btn-md center-block" style="margin-left: 216px;">Save</button>  
95:              <a href="#" id="myReset" class="btn btn-primary btn-md center-block" style="margin-left: 15px;">Cancel</a>  
96:            </div>  
97:            <br></br>  
98:            <br></br>  
99:            <div class="modal-footer">  
100:            </div>  
101:           </div>  
102:         <br></br>  
103:       </div>  
104:       <br></br>  
105:      </div>  
106:      <br></br>  
107:      <div >  
108:       <div class="container">  
109:         <div class="panel panel-default">  
110:           <br></br>  
111:           <div class="btn-group" align="center" style="left: 27%;">   
112:             <button id="blocds" data-toggle="modal" data-target="#myModal" class="btn btn-primary btn-md center-block" style="margin-left: 15px;">Modal Using Javascript</button>   
113:             <button id="blocds" data-toggle="modal" data-target="#myModal" class="btn btn-primary btn-md center-block" style="margin-left: 15px;background-color:#DF4720">Modal Using AngularJS</button>   
114:           </div>  
115:           <br></br>  
116:           <br></br>     
117:         </div>  
118:       </div>  
119:      </div>   
120:    </html>   
121:  </apex:page>  

Happy coding!!

Monday, 2 November 2015

FIND MY PARENT SALESFORCE USERS BY ROLE HIERARCHY

Was looking into a blog post of jeff douglas on FIND MY SALESFORCE USERS BY ROLE HIERARCHY, its an awesome utility code for fetching the child users in the hierarchy, so thought of righting a same kind of code to get all the parent users in current user's hierarchy, when I started writing it then I realized it is not that much easily, have to give some time to it.

So here I am, below is the code for fetching the Parent user's id in hierarchy, the method will the return a map of user on the key and the set of Id's of the parent user in the values.


1:public static Map<Id, Set<Id>> getRoleParentSubordinateUsers(Set<Id> userId) {  
2:      Map<Id, Id> roleIds = new Map<Id, Id>();  
3:      Map<Id, Set<Id>> parentRoleIds = new Map<Id, Set<Id>>();  
4:      // get requested user's role  
5:      for(User usr : [select Id, UserRoleId from User where Id IN: userId and UserRoleId != null]) {  
6:        roleIds.put(usr.UserRoleId, usr.Id);  
7:      }  
8:      Map<Id, Set<Id>> parentids = new Map<Id, Set<Id>>();  
9:      for(Id ids : roleIds.keySet()) {  
10:        parentRoleIds.put(ids, getAllParentRoleIds(new Set<ID>{ids}));  
11:      }  
12:      for(Id kys : parentRoleIds.keySet()) {  
13:        for(Id ids : parentRoleIds.get(kys)) {  
14:          if(!parentids.containsKey(ids)) {  
15:            parentids.put(ids, new Set<Id>{kys});    
16:          } else {  
17:            parentids.get(ids).add(kys);  
18:          }  
19:        }  
20:      }  
21:      Map<Id, Set<Id>> mapOfCurrentWithParentUsers = new Map<Id, Set<Id>>();  
22:      // get all of the ids for the users in those roles  
23:      for(User us : [Select Id, Name, Region__c, State__c, UserRole.Name, UserRoleId From User where IsActive = true AND (UserRoleId IN: parentids.keySet() OR UserRoleId IN :roleIds.keySet())]){  
24:        for(Id rids : parentRoleIds.keySet()) {  
25:          if(parentids.containsKey(us.UserRoleId)){  
26:            if(parentids.get(us.UserRoleId).contains(rids)) {  
27:              if(!mapOfCurrentWithParentUsers.containsKey(roleIds.get(rids))) {  
28:                mapOfCurrentWithParentUsers.put(roleIds.get(rids), new Set<Id>{us.id});   
29:              } else {  
30:                mapOfCurrentWithParentUsers.get(roleIds.get(rids)).add(us.Id);  
31:              }  
32:            }  
33:          }  
34:        }  
35:      }  
36:      // return the ids as a set so you can do what you want with them  
37:      return mapOfCurrentWithParentUsers;  
38:    }  
39:    private static Set<Id> getAllParentRoleIds(Set<ID> roleIds) {  
40:      Set<ID> mapOfCurrentWithParentRole = new Set<Id>();  
41:      // get all of the roles underneath the passed roles  
42:      for(UserRole userRole :[select Id, ParentRoleID from UserRole where Id IN :roleIds AND ParentRoleID != null])  
43:        mapOfCurrentWithParentRole.add(userRole.ParentRoleID);  
44:       // go fetch some more rolls!  
45:      if(mapOfCurrentWithParentRole.size() > 0){  
46:        mapOfCurrentWithParentRole.addAll(getAllParentRoleIds(mapOfCurrentWithParentRole));  
47:      }  
48:      return mapOfCurrentWithParentRole;  
49:    }  

Happy Coding!!

Friday, 19 June 2015

Paging using AngularJS and Bootstrap in Salesforce


AngularJS is a toolset for building the framework most suited to your application development. It is fully extensible and works well with other libraries. Every feature can be modified or replaced to suit your unique development workflow and feature needs.
Want to know more and learn about angularJS Click here this is a re-post of the blog written by Vivek Deepak

Here is the page how its looks, the awesome thing about this page is angular the functionality in too much less coding, that what I just loved about AngularJS
Take a look at this


Here is the small controller class using remote Action to fetch the account records.

1:  global class BlogOneController {  
2:    @RemoteAction  
3:    global static List<Account> getAllAccounts() {    
4:      return [SELECT Id,Name,BillingStreet,BillingCity,BillingState FROM Account];  
5:    }  
6:  }  

Here is the code of the page using AngularJS to show the data on the page, using AngularJS and Bootstrap

1:  <apex:page showHeader="false" sidebar="false" docType="html-5.0" standardStylesheets="false" applyBodyTag="false" applyHtmlTag="false" controller="BlogOneController" >  
2:  <html ng-app="SampleApp" lang="en">  
3:    <apex:stylesheet value="{!URLFOR($Resource.bootstrap,'/boostrapStyle/css/bootstrap.css')}"/>  
4:    <apex:stylesheet value="{!URLFOR($Resource.bootstrap,'/boostrapStyle/css/ng-table.min.css')}"/>  
5:    <head>  
6:    <!-- Add CSS Files HERE -->     
7:    <script type="text/javascript">  
8:    var myapp = angular.module('SampleApp',['ui.bootstrap','mgcrea.ngStrap','ngTable']);  
9:      myapp.factory('FETCH_ACCOUNTS', ['$q','$log', function($q,$log){  
10:    var handleReq = function(remoteCall) {  
11:      var defer = $q.defer();  
12:        remoteCall(  
13:         function(result, event) {  
14:          if(event.status) {  
15:           defer.resolve(result);  
16:          }  
17:          else {  
18:           $log.error(event.message);  
19:           defer.reject(event.message);  
20:          }  
21:         },  
22:         {escape:false, buffer: false}  
23:        );  
24:        return defer.promise;  
25:       }  
26:    return {  
27:        getAllCustomers: function() {  
28:          return handleReq(BlogOneController.getAllAccounts);  
29:        }  
30:      }  
31:  }]);  
32:  myapp.controller('MainController',['$q','$log','$scope','FETCH_ACCOUNTS','ngTableParams',function($q,$log,$scope,FETCH_ACCOUNTS,ngTableParams){  
33:        $scope.loadingH = true;  
34:        var data = [];  
35:        var promise = FETCH_ACCOUNTS.getAllCustomers();  
36:        $scope.account_list = [];  
37:        promise.then(function(response){  
38:          data = response;  
39:              $scope.accountRecords.reload();  
40:          $scope.loadingH = false;      
41:        },function(error){  
42:          $log.error('ERROR' + JSON.stringify(error));  
43:          $scope.loadingH = false;  
44:        });  
45:        $scope.accountRecords = new ngTableParams({  
46:                 page: 1,      // show first page  
47:                 count: 5  
48:                           // count per page  
49:              }, {  
50:                 counts:[],  
51:                 total: data.length, // length of data  
52:                 getData: function($defer, params) {  
53:               params.total(data.length);  
54:                 $defer.resolve(data.slice((params.page() - 1) * params.count(), params.page() * params.count()));  
55:              }  
56:            });  
57:      }]);  
58:    </script>  
59:    </head>  
60:    <body ng-controller="MainController" >  
61:    <div class="panel panel-primary">  
62:       <div class="panel-heading">  
63:        <h3 class="panel-title">Account Information</h3>  
64:       </div>  
65:       <div class="panel-body">  
66:          <table ng-table="accountRecords" class="table table-striped table-hover">  
67:           <thead>  
68:            <tr>  
69:             <th>#</th>  
70:             <th>Account Name</th>  
71:             <th>Street</th>  
72:             <th>State</th>  
73:            </tr>  
74:           </thead>  
75:           <tbody>  
76:            <tr ng-repeat="account in $data">  
77:             <td>{{$index+1}}</td>  
78:             <td>{{account.Name}}</td>  
79:             <td>{{account.BillingStreet}}</td>  
80:             <td>{{account.BillingCity}}</td>  
81:            </tr>  
82:           </tbody>  
83:          </table>    
84:       </div>  
85:      </div>  
86:      <apex:includeScript value="{!URLFOR($Resource.bootstraptpls, 'bootrapangular/angular.min.js')}"/>  
87:    <apex:includeScript value="{!URLFOR($Resource.bootstraptpls, 'bootrapangular/angular-strap.min.js')}"/>  
88:    <apex:includeScript value="{!URLFOR($Resource.bootstraptpls, 'bootrapangular/angular-strap.tpl.min.js')}"/>  
89:    <apex:includeScript value="{!URLFOR($Resource.bootstraptpls, 'bootrapangular/ng-table.min.js')}"/>  
90:    <apex:includeScript value="{!URLFOR($Resource.bootstraptpls, 'bootrapangular/ui-bootstrap-tpls-0.11.0.js')}"/>  
91:  <!-- Add JS Files HERE -->  
92:  </body>  
93:  </html>  
94:  </apex:page>  

For the Angular and Boostrap files please click here

Happy coding!!



Wednesday, 10 June 2015

Improved SAQL in Spring'15

The SAQL language is a real-time query language that enables ad hoc analysis of data that’s stored in dataset
SAQL is influenced by the Pig Latin programming language, but their implementations differ and they aren’t compatible.
SAQL is procedural, which means that you describe what you want to get from your query. Then, the query engine decides how to serve it efficiently. SAQLis compositional. Every statement has a result, and you can chain statements together.
Salesforce Analytics Query language (SAQL)
We already know about SOQL and SOSL. This is new Query language for Analytics cloud to enable ad hoc analysis of data stored in dataset. This is still in pilot.
 IDENTIFIERS Identifiers are case-sensitive. They can be unquoted or quoted. Unquoted identifiers can’t be one of the reserved words and must start with a letter (A to Z or a to z) or an underscore. Subsequent characters can be letters, numbers, or underscores. Unquoted identifiers can’t contain spaces. Quoted identifiers are wrapped in single quotes (') and can contain any character that a string can contain. 





Happy Coding!!
Cheers


Saturday, 18 April 2015

Replicating one Salesforce org to another + Mass Deployment + Best Practice + Salesforce

Recently I was trying to replicate one Salesforce Sandbox org to Developer edition org, Sandbox was fully developed, sandbox had many components + dependecies, you cannot just deploy everything in one shot, So you need to make a checklist before the deployment for the components you are going to deploy.

Start checking in the components in order of below list

  • Check Appexchange apps installed.
  • Standard Object Modifications i.e Custom Fields or Field History Tracking or Assignment Rules (Suggestion is to use IDE for this).
  • Custom Objects i.e Custom Object and Custom Settings ( Here you can face issue if you have formula fields which is using related objects field values like CustomObject__r.Phone__c in the formula field )
  • Remote Site Settings, Static Resources, Roles Custom Button and Custom Links etc
  • Now Trigger, Apex Classes, Test classes and Visualforce Components and Visualforce pages.


I am using ANT and IDE, if you are using ANT please specify the profiles each and every time in your package.xml file.

In writing its looks too less but it would be too much at the time of deployment, While deploying keep this in mind that we are not using change sets, now your only hope is ANT and IDE.
for ANT users while deploying specific Standard objects custom Fields and that is 50 in count and pasting the custom fields name in package file, that is seriously annoying process I feel. So according to the list we should deploy all the Standard and Custom object fully using IDE, below is the process of deployment using IDE, after that there is an ANT package file snippet that you can use to deploy everything from one org to another org.

Process of fetching all the components in the IDE for the deployment (Specificaly fetching Standard Objects custom Fields).

i. Go to IDE open you Project

ii. Right click on the Project and click on Force.com followed by Add/Remove Metadata Components.


iii. Now click on Add/remove button highlighted below


you will get this notification message click ok



iv. Now select those components that you want to add the metadata in your IDE, like I have select Standard Object and the fields.





v. After selecting the components, you can see the selected componenets then click Apply


vi. Now you have added the components in your IDE.


vii. Right click on the object and select FORCE.COM and Deploy to Server


viii. Pass you credential of the dev org.


ix. Click NEXT


X. Click NEXT and you are done now



I have shown the above process to deploy standard Objects fields and then Custom object in sequence without wasting you time in the creation of the of the package.xml file.

Now just put the below code format in your package.xml file keeping in mind the deployement is done of the dependent components according to list in the starting I mentioned.

1:       <types>  
2:      <members>*</members>  
3:      <name>ApexClass</name>  
4:    </types>  
5:    <types>  
6:      <members>*</members>  
7:      <name>ApexComponent</name>  
8:    </types>  
9:    <types>  
10:      <members>*</members>  
11:      <name>ApexPage</name>  
12:    </types>  
13:    <types>  
14:      <members>*</members>  
15:      <name>ApexTrigger</name>  
16:    </types>  
17:    <types>  
18:      <members>Lead.104</members>  
19:      <name>AssignmentRule</name>  
20:    </types>  

NOTE : Put star(*) when you want to deploy all the components.

The above process will surely help you, when you are mass deploying
Please go to these links for more information and expertise in ANT TOOL

Installing the Force.com Migration Tool
Force.com Migration Tool Guide
Using the Force.com Migration Tool

I am a great fan of ANT tool, and anybody will also become when we will use ANT AT ITS BEST.

Enjoy the force !!!

Monday, 23 March 2015

Calling Apex method from List View button having Parameters

Recently I was trying to call an Apex method in List view method and want to pass the parameters from the method from the List View button whatever the records have been selected.

You can say I am dump, but when I selected a single record in the List view it works perfect, but when I selected more then one, it started showing error. I tried putting alerts and tried to check why its not taking the multiple record Ids, this is the code I wrote

1:  //Fetch Id of the selected Record  
2:  var records = {!GETRECORDIDS($ObjectType.Contact)};   
3:  //Check for selected record size  
4:  if(records.length <= 4) {   
5:       //Calling Apex method  
6:       sforce.apex.execute("MyApexClass","myApexMethod", {ids:records });   
7:  } else {   
8:       alert('You can validate only 4 records at a time');   
9:  }  

Above code was not working with the multiple records, it was showing error


So finally I got the thing that RECORDS was returning a list of Ids of the selected records, then the code needs manipulation, I end up doing this below code and this was working like charm

1:  //Fetch Id of the selected Record   
2:  var records = {!GETRECORDIDS($ObjectType.Contact)};   
3:  if(records.length <= 4) {   
4:       var res = "";   
5:       var i;   
6:       //Loop through the records Id selected by the user  
7:       for (i = 0; i < records.length; i++) {   
8:            res += records[i] + ";";   
9:       }   
10:       sforce.apex.execute("MyApexClass","myApexMethod", {ids:res });   
11:  } else {   
12:       alert('You can validate only 4 records at a time');   
13:  }  

Happy Coding!!

Friday, 27 February 2015

Visualforce Remote Objects -- Query Records & Insert Record


Using Visualforce Remote Objects consists of implementing two separate pieces of functionality on the same page.
Access definitions, written in Visualforce with the Remote Objects components. These components generate a set of JavaScript proxy objects that you can use in step 2.
Data access functions, written in JavaScript. These functions use the proxy objects that are made available by the access definitions to perform create, retrieve, update, and delete operations on your data.
Your page then uses the data access functions to respond to user interaction, such as form submissions or controls changes, or to perform periodic actions in response to timers, or most anything that you can write in JavaScript.

Behind the scenes, the Remote Objects controller handles sharing rules, field level security, and other data accessibility concerns. Pages that use Remote Objects are subject to all the standard Visualforce limits, but like JavaScript remoting, Remote Objects calls don’t count toward API request limits.

Inserting Record in Contact using Visualforce Remote Object

Here how it looks provide the values of Contact then click on the button to save the data


Here is the code of the above page...

1:  <apex:page standardStylesheets="false" DocType="html-5.0">  
2:    <!-- Bootstrap -->  
3:    <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css" rel="stylesheet" media="screen"/>  
4:    <link href="//getbootstrap.com/examples/signin/signin.css" rel="stylesheet" media="screen"/>  
5:      <apex:remoteObjects jsNamespace="RemoteObjectModel">  
6:        <apex:remoteObjectModel name="Contact" fields="Id,FirstName,LastName">  
7:        </apex:remoteObjectModel>  
8:      </apex:remoteObjects>  
9:    <script>  
10:      function remot() {  
11:                alert(document.getElementById("name").value);  
12:        var ct = new RemoteObjectModel.Contact({   
13:          FirstName: document.getElementById("name").value,  
14:          LastName: document.getElementById("lName").value,   
15:          Phone: document.getElementById("phon").value,  
16:        });  
17:        ct.create();  
18:      }  
19:    </script>  
20:    <div class="col-xs-12">  
21:    <div class="panel-body">  
22:      <label for="name">First Name</label>  
23:      <br></br>  
24:      <input type="text" class="form-control col-lg-10" id="name" name="fname" placeholder="First Name"></input><br></br>  
25:      <label for="name">Last Name</label>  
26:      <input type="text" class="form-control col-lg-10" id="lName" name="Last Name" placeholder="Last Name"></input><br></br>  
27:      <label for="name">Phone</label>  
28:      <input type="text" class="form-control col-lg-10" id="phon" name="phone" placeholder="Phone"></input><br></br>  
29:      <br></br>  
30:      &nbsp;  
31:      <p> <button onclick="remot()">Insert Contact</button>  
32:      </p>  
33:      </div>  
34:     </div>  
35:  </apex:page>  

Showing record on page using Visualforce Remote Object

Now querying the records of Account and showing on the page, its having the limit of 10, just take a look at the awesome functionality of remote object of Salesforce.

Here how it looks


Here is the code of querying the records and showing it on the page

1:  <apex:page >  
2:    <apex:includeScript value="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.2.min.js"/>  
3:    <apex:remoteObjects >  
4:     <!--query records-->  
5:     <apex:remoteObjectModel name="Account" jsShorthand="acc" fields="Id,Name,Phone"/>  
6:    </apex:remoteObjects>  
7:    <script>   
8:     function clearList() {  
9:       if(!$('#accList').empty()) {  
10:         $('#accList').empty();  
11:       }  
12:     }  
13:     var DML = function(){  
14:     clearList();  
15:       var data = new SObjectModel.acc();  
16:       data.retrieve({ limit: 10 } ,function(err, records){  
17:         if(err) alert(err.message);  
18:         else {  
19:           populate(records);      
20:         }  
21:       });  
22:       function populate(records)  
23:       {  
24:         var ul = document.getElementById("accList");  
25:         records.forEach(function(record) {  
26:           var nam = record.get("Name");  
27:           nam += " -- ";  
28:           nam += record.get("Phone");   
29:           var brs= document.createElement("br");  
30:           var li = document.createElement("li");  
31:           li.appendChild(document.createTextNode(nam));  
32:           ul.appendChild(li);  
33:           ul.appendChild(brs);  
34:         });  
35:       }  
36:     }  
37:    </script>  
38:    <div>  
39:     <div>  
40:       <p> <button onclick="DML()">Show Accounts</button>  
41:       </p>  
42:     </div>  
43:    </div>  
44:    <div class="wrapper">  
45:     <ul class="list-inline" id="accList"></ul>  
46:    </div>  
47:  </apex:page>  

Hope this helps someone
Happy Coding cheers..!!

Sunday, 25 January 2015

Using JSON.deserializeUntyped to create dynamically records from JSON

Few days ago, got a requirement of the webservice for the creation of the records from the data in the JSON response. Tried some old fashioned code that use object instance to insert the records, but I was not feeling to fulfill to use that one.

So I started doing some search on JSON de-serializing method of salesforce and then I got this one.
In the starting this method seems to be not that much helping, but later one found out that "deserializeUntyped" is one of the best method for JSON de-serialization.

Code Scope : This below code will dynamically create Salesforce Object records without specifying their instance in the code and field specified in the json response will be responsible for the field value of the records.
Its a generic code that can be used whenever you are creating a webservice for the creation of the records in Salesforce.

Here is code...

1:  public class DynamicRecordCreationFromJSONResponse {  
2:    
3:       public static void parseJSONCreateRecords() {  
4:              
5:            String jsonInput = '{\n' +  
6:                                  ' "Account" : [ ' +   
7:                                                            '{"Name":"Sample Account","CustomField__c":"BR22RRR","CustomBooleanField__c":true,"Lookup_Field__c":"a08g0000006c9EH"}, \n' +  
8:                                                            '{"Name":"Sample Account2","CustomField__c":"Peroni"} ],\n' +  
9:                                     ' "CustomObject__c" : [ ' +   
10:                                                            '{"Name":"Sample Record 1"}, \n' +  
11:                                                            '{"Name":"Sample Record 2","Activity_Description__c":"Testing"} ]\n' +  
12:                                     '}';  
13:              
14:            // Parse entire JSON response using deserializeUntyped  
15:         Map<String, Object> mapOfNameWithRecords = (Map<String, Object>)JSON.deserializeUntyped(jsonInput);  
16:            System.debug('mapOfNameWithRecords::::::::' + mapOfNameWithRecords.keySet());  
17:              
18:            //List of Objects  
19:            List<sObject> objList = new List<sObject>();  
20:            Map<String, List<String>> fieldswithDataType = new Map<String, List<String>>();  
21:                             
22:            //Loop through mapOfNameWithRecords  
23:            for(String objName : mapOfNameWithRecords.keySet()) {  
24:                   
25:                 //process to get the name of the object by removing curly braces  
26:                 String str = objName.replace('{',' ');  
27:                 String finalstr = str.replace('}',' ');  
28:                 finalstr = finalstr.trim();  
29:                   
30:                 //Get the records of the object from the json  
31:                 List<Object> recordList = (List<Object>)mapOfNameWithRecords.get(finalstr);  
32:                 System.debug('recordList::::::::' + recordList);  
33:              
34:                 //Loop through the list of records of JSON  
35:                 for(Object obj : (List<Object>)mapOfNameWithRecords.get(finalstr)) {  
36:                        
37:                      //Create new sObject instance  
38:                      SObject sobjectInstance = Schema.getGlobalDescribe().get(finalstr).newSObject();  
39:                        
40:                      //Populating map with field name and values  
41:                      Map<String, Object> a2 = (Map<String, Object>)obj;  
42:                        
43:                      //Loop through the keySet  
44:                      for(String st : a2.keySet()) {  
45:                           sobjectInstance.put( st, a2.get(st));  
46:             }  
47:                        
48:                      //Add to list of sObjectk  
49:                      objList.add(sobjectInstance);  
50:                 }  
51:            }  
52:            System.debug('objList::::::::' + objList);  
53:              
54:            //Check for list size and insert  
55:            if(objList.size() > 0) {  
56:                 insert objList;  
57:            }  
58:       }  
59:  }  

Note : Date formate should be taken care of as it varies from Local of Salesforce User, so do provide right format for the Date and Date Time fields.

Thanks
Happy Coding...cheers!!!


Sunday, 4 January 2015

Passed Salesforce DEV 501 Multiple Choice - Sharing my experience

I passed Salesforce Certified Force.com Advance Developer Multiple Choice First of all, don't go without experience and preparation, its not that easy, being a hard core coder doesn't mean that you will go and pass, its not about coding knowledge, its all about coding basics i.e. Apex and Visualforce pages and Salesforce life cycle knowledge and best practice.

According to Study Guide for Salesforce.com Certified Force.com Advanced Developer

Development Lifecycle                          13%                   9 Questions
Force.com Code (Apex)                         33%                  23 Questions
Force.com Pages (Visualforce)             38%                  26 Questions
Testing and Debugging                         16%                  11 Questions

Above table shows area covered in exam.

Listing out the high topics

1. Apex class basics and Best practice
2. Visualforce pages and tags, Templates.
3. Test classes - best practice.
4. Migration tool.
6. Sandbox and capabilities
7. Force.com IDE
8. Developer Console
9. Types of Controller

Here is the list of the things need to study with small descriptions as well. These are the high points that I feel should be at one place.

Sandboxes Types -- Developer Sandbox

Refresh Interval -- 1 day
Storage Limits -- 200 mb data and 200 mb file storage
Data Copy -- Metadata only
Sandbox Templates -- Not included

Description -- Developer sandbox environments are intended for coding and testing by a single developer. Multiple users can log in to and share a single Developer sandbox, but the primary purpose of a Developer sandbox is to provide an environment in which changes under active development can be isolated until those changes are ready to be shared. Developer sandboxes copy all of your production organization’s metadata, or Setup data. This includes custom settings, custom object definitions, Apex classes and triggers, Visualforce pages, reports, dashboards, price books, and so on.
Developer sandboxes provide a limited amount of file and data storage, which is enough for many development and testing tasks. 

Developer Pro Sandbox

Refresh Interval --- 1 day
Storage Limits --- 1 GB of data storage and 1 GB of file storage
Data Copy --- Metadata only
Sandbox Templates --- Not included
Description --- Developer Pro sandbox environments provide the same functionality as Developer sandboxes do, with increased file and data storage. With the added storage, a Developer Pro sandbox can host larger and more complete data sets, so you can use it for additional tasks such as data load and integration testing and user training.

Partial Copy Sandbox
Refresh Interval -- 5 days
Storage Limits -- 5 GB of data storage and 5 GB of file storage
Data Copy --- All metadata and sample of object data
Sandbox Templates --- Required
Description --- Partial Copy sandbox environments include all of your organization’s metadata and a sample of your production organization’s data that you define by using a sandbox template. To create a Partial Copy sandbox, you must apply a sandbox template at creation time. A Partial Copy sandbox is, at its base, a metadata copy of your production organization, just like Developer and Developer Pro sandboxes. In addition, the sandbox copy engine samples data from your production organization based on what is defined by a sandbox template. For each selected object in the sandbox template, the sandbox copy engine samples up to 10,000 records. For example, when you use a template that includes only Accounts to create a Partial Copy sandbox, up to 10,000 Account records are copied into the new sandbox, but no other records are copied.
The sandbox copy engine has a special copy strategy to handle Partial Copy sandbox creation. The copy strategy understands the data relationships that are defined in your production organization’s standard and custom object schema. The copy strategy ensures that sample records maintain valid relationships as defined in your production organization’s standard and custom object schema. For example, if you create a sandbox template that includes two custom objects that are called Master and Detail, and these objects have a Master-Detail relationship, the copy engine ensures that every sampled Detail record points to a Master. The copy engine also understands required relationships between objects, whether they are Master-Detail or required Lookup relationships. The copy engine samples the master records first and then uses the IDs of the master records to sample related detail records.
When you use sandbox templates to create valid subsets of your organization’s data, you can use Partial Copy sandboxes for virtually any development, testing, or training purpose. The only task for which they aren’t well-suited is full performance and load testing.
Full Sandbox
Refresh Interval --- 29 days
Storage Limits --- Same as production organization
Data Copy --- All metadata and data
Sandbox Templates -- Available
Description --Full sandbox environments are a replica of your entire production organization and all its data, including standard and custom object records, documents, attachments, code, settings, and so on.
When you create a Full sandbox, you can apply a sandbox template to limit the data that is copied, so that your sandbox contains only the records that you need for testing or other tasks. For example, you can omit confidential or sensitive data if it’s not needed for testing. Create a sandbox template that includes everything except the sensitive data. When you apply a sandbox template to aFull sandbox, the sandbox copy engine copies all of the records for the selected objects in the template. For example, when you use a template that includes only Accounts to create a Full sandbox, all of the Account records are copied into the new sandbox, but no other records are copied.
When you create a Full sandbox, you also have to decide how much field tracking history and Chatter activity to include.
The default is to omit field tracking, but you can include up to 180 days of field tracking. This might be an excessive amount of data if you track field history for many objects in your production organization.
§ Chatter activity data can be extensive, which can add a significant amount of time to your Full sandbox copy.
Limit the amount of field history that you copy, and copy your Chatter data only if you need it for your testing use cases.
You can use Full sandboxes for many purposes, but the size of the sandbox and length of the refresh interval don’t produce an environment that stays current with your production organization. We suggest that you use Full sandboxes for data load testing, integration testing, user acceptance testing, performance and load testing, and staging purposes. In particular, this environment is the only one that can support full performance and load testing.

Understanding Sandbox Refresh Intervals
The refresh interval for each sandbox environment is calculated from when the actual sandbox copying process begins. This corresponds to when the sandbox status changes from Pending to Processing.
If other sandbox copy requests were made before yours, your sandbox might remain in the Pending status for some time. The refresh interval timer for your sandbox won’t start until your request leaves this state.

Future Annotation

Methods with the future annotation must be static methods, and can only return a void type.
The specified parameters must be primitive data types, arrays of primitive data types, or collections of primitive data types.
Methods with the future annotation cannot  take  sObjects or objects as arguments.
Specify (callout=true) to allow callouts in a future method. Specify (callout=false) to prevent a method from making callouts.
Methods with the future annotation cannot be used in Visualforce controllers in  either  getMethodName  or  setMethodName  methods, nor in the constructor.
·         You cannot call a method annotated with future from a method that also has the future annotation. Nor can you call a trigger from an annotated method that calls another annotated method.
§  The getContent and getContentAsPDFPageReference methods cannot be used in methods with the future annotation.

Defining Templates with <apex:composition>

Define the section of the template using <apex:Insert >
Then create template using <apex:composition> with required child <apex:define>
All templates defined using <apex:composition> must have one or more child <apex:insert> tags.
An <apex:insert> tag indicates to pages that import the template that a section needs a definition. Any Visualforce page that imports a template using <apex:composition> must use <apex:define> to specify the content of each <apex:insert> section of the template.
<apex:insert> : Define a named section in VF template
<apex:define>: Provide content for named section in VF template
<apex:composition>: A particular area/section of visualforce page where VF template is to be used


SOQL and SOSL

ALL ROWS - returns all rows including those in the recycle bin and archived activities
(Ex: System.assertEquals(2, [SELECT COUNT() FROM Contact WHERE AccountId = a.Id ALL ROWS]);)

FOR UPDATE - locks the record for update from other means while the execution is happening.
(Ex:  Account [] accts = [SELECT Id FROM Account LIMIT 2 FOR UPDATE]; )

getGlobalDescribe()

Returns a map of all sObject names (keys) to sObject tokens (values) for the standard and custom objects defined in your organization.


Understanding Apex Describe Information

You can describe sObjects either by using tokens or the describeSObjects Schema method.
Apex provides two data structures and a method for sObject and field describe information:
·         Token—a lightweight, serializable reference to an sObject or a field that is validated at compile time. This is used for token describes.
·         The describeSObjects method—a method in the Schema class that performs describes on one or more sObject types.
§  Describe result—an object of type Schema.DescribeSObjectResult that contains all the describe properties for the sObject or field. Describe result objects are not serializable, and are validated at runtime. This result object is returned when performing the describe, using either the sObject token or the describeSObjects method.

Order of Execution for Visualforce Page Get Requests

 A get request is an initial request for a page either made when a user enters an URL or when a link or button is clicked that takes the user to a new page. The following diagram shows how a Visualforce page interacts with a controller extension or a custom controller class during a get request:
1. Evaluates constructor on the controller and Extensions.
2. Custom Component on Page.
3. Evaluates action attribute on <apex:page>.
4. Checks for apex:form on page, to create view state.
Note : If the user is redirected to a page that uses the same controller and the same or a proper subset of controller extensions, a postback request is made. When a postback request is made, the view state is maintained.

Visualforce Email Templates

Although Visualforce email templates use standard Visualforce components, they are not created in the same way. Visualforce email templates always use components that are prefaced with the messaging namespace. In addition:
·         All Visualforce email templates must be contained within a single <messaging:emailTemplate> tag. This is analogous to regular Visualforce pages being defined within a single <apex:page> tag.
·         The <messaging:emailTemplate> tag must contain either a single <messaging:htmlEmailBody> tag or a single <messaging:plainTextEmailBody> tag.
§  Several standard Visualforce components are not available for use within <messaging:emailTemplate>. These include <apex:detail>, <apex:pageBlock> and all related pageBlock components, and all input components such as <apex:form>. If you attempt to save a Visualforce email template with these components, an error message displays.

apex:actionPoller

A timer that sends an AJAX request to the server according to a time interval that you specify. Each request can result in a full or partial page update.
An <apex:actionPoller> must be within the region it acts upon. For example, to use an <apex:actionPoller> with an <apex:actionRegion>, the <apex:actionPoller> must be within the <apex:actionRegion>.

apex:actionFunction

A component that provides support for invoking controller action methods directly from JavaScript code using an AJAX request. An <apex:actionFunction> component must be a child of an <apex:form> component.
Unlike <apex:actionSupport>, which only provides support for invoking controller action methods from other Visualforce components, <apex:actionFunction> defines a new JavaScript function which can then be called from within a block of JavaScript code.

apex:actionRegion

Note that an <apex:actionRegion> component only defines which components the server processes during a request—it does not define what area(s) of the page are re-rendered when the request completes. To control that behavior, use the rerender attribute on an <apex:actionSupport>, <apex:actionPoller>, <apex:commandButton>, <apex:commandLink>, <apex:tab>, or <apex:tabPanel> component.

 <apex:actionRegion>
    <apex:inputField value="{!opportunity.stageName}" id="stage">
    <apex:actionSupport event="onchange" rerender="thePageBlock"

                              status="status"/>
     </apex:inputField>
</apex:actionRegion>


apex:include

A component that inserts a second Visualforce page into the current page. The entire page subtree is injected into the Visualforce DOM at the point of reference and the scope of the included page is maintained.
If content should be stripped from the included page, use the <apex:composition> component instead.

Visualforce pages

Visualforce consists of a tag-based markup language that gives developers a more powerful way of building applications and customizing
the Salesforce user interface. With Visualforce you can:
• Build wizards and other multistep processes.
• Create your own custom flow control through an application.
• Define navigation patterns and data-specific rules for optimal, efficient application interaction.


Adding SOSL Queries to Unit Tests

To ensure that test methods always behave in a predictable way, any Salesforce Object Search Language (SOSL) query that is added to an Apex test method returns an empty set of search results when the test method executes. If you do not want the query to return an empty list of results, you can use the Test.setFixedSearchResults system method to define a list of record IDs that are returned by the search. All SOSL queries that take place later in the test method return the list of record IDs that were specified by the Test.setFixedSearchResults method. Additionally, the test method can call Test.setFixedSearchResults multiple times to define different result sets for different SOSL queries. If you do not call the Test.setFixedSearchResults method in a test method, or if you call this method without specifying a list of record IDs, any SOSL queries that take place later in the test method return an empty list of results.
The list of record IDs specified by the Test.setFixedSearchResults method replaces the results that would normally be returned by the SOSL query if it were not subject to any WHERE or LIMIT clauses. If these clauses exist in the SOSL query, they are applied to the list of fixed search results. For example:
@isTest                  
private class SoslFixedResultsTest1 {
    public static testMethod void testSoslFixedResults() {
       Id [] fixedSearchResults= new Id[1];
       fixedSearchResults[0] = '001x0000003G89h';
       Test.setFixedSearchResults(fixedSearchResults);
       List<List<SObject>> searchList = [FIND 'test' IN ALL FIELDS RETURNING    Account(id, name WHERE name = 'test' LIMIT 1)];
   }
}
                                                                                         

Contents to go through before exam -

1. Force.com Apex Code Developer's Guide and Visualforce Guide.
2. Force.com Developer Guide.
3. Salesforce Object Query Language.

Happy Coding..!!