Thursday, September 12, 2013


Well finally with time I am learning a thing or two about creating apps. Yes apps, I always tried to build some apps that can be used by different developers/ clients. Although todays topic "MapMyObject" was never going to be app, it was just an experiment to create a reusable component to integrate Google Maps with Force.com and guess what ? the initial results were awesome!. This inspired me a lot to convert this one into a app that can pull Geolocation Data(lat/lang) from any Sobject into a Google maps, where you can visualize them, edit them and even create new records.

Today I am releasing a beta version of this "MapMyObject" which can be installed in a DE org or in a sandbox.

Some of the features

  • Visualize data from any Sobject into a Google Map
  • Edit records from Map
  • Create new records from Map
  • Highly configurable : You can select permission based on Config/Custom Settings, whether a particulat map will allow editing, creation of new record or view existing records.
  • Uses Google Maps API V3
Some Screens
Showing Records

Create New Record

Update Records


Well there are lot more possibilities with this app/component like dashboards, demographics,  Data distribution map.  Well that was lot of bragging about the app! to install the same and to know more about the app please follow the below link : 

Tuesday, September 10, 2013


So here we go, a Visualforce component to show the images from attachment as a slider . This Slider "VFAttachmentSlider" can be used in a inline VF pages and as well as on standalone pages to render a beautiful image slider by pulling images from attachment of a record

VF Attachment Slider


The component uses FlexiGrid2 and jQuery to render the slider, which  itself is very easy to implement. This component "VFAttachmentSlider" goes one step further and makes displaying images from attachment super easy. It pulls all the related attachment of the passed record and queues them into a slider.


Features

  • Easy Syntax : Just pass the Id of the parent record containing the images in attachments to the component and guess what you have a awesome looking Slider.

    Example :
      <c:VFAttachmentSlider recordId="a0190000006ppB5"/>
    *replace the harcoded Id with a merge field or an Id.
  • Prev & Next : Has easy navigation support for previous and next.
  • Pagination : Shows the current page.
  • Responsive Design :  This is something which is also inherited from Flexslider. The image slider automatically adjust according to the size of the images.

Some Examples

  • Using VFAttachmentSlider in inline Page 
    • Account Inline Page :
       <apex:page sidebar="false" standardController="Account">  
         <c:VFAttachmentSlider recordId="{!Account.Id}"/>    
       </apex:page>  
    • Similarly for Contact
       <apex:page sidebar="false" standardController="Contact">  
         <c:VFAttachmentSlider recordId="{!Contact.Id}"/>    
       </apex:page>  
    • Similarly you can use the slider for any Custom Object
       <apex:page sidebar="false" standardController="MyCustomObject__c">  
         <c:VFAttachmentSlider recordId="{!MyCustomObject.Id}"/>    
       </apex:page>  

Sunday, September 1, 2013



Salesforce Rest Services are a powerful as well as convenient way to expose web services from a organization. It uses simple HTTP methods like GET , POST etc. to access and manipulate data. The data exchange format is in the form of JSON generally. 

The following is a sample apex class which illustrates the POST method to post details and GET method to retrieve details from an outside application.


Sample Rest Apex Class:


/*  
   The urlMapping acts as an accessible endpoint and adds to the full URL used to call this webservice from an external point  
   For example, something like "https://ap1.salesforce.com/services/apexrest/Account"  
 */  
 @RestResource(urlMapping='/Account/*')  
 global with sharing class callAccount {  
  /*  
   HttpPost method is used to capture a HttpPost request has been sent to our rest apex class.  
   Used to retrieve data coming in the request body and performing corressponding actions  
  */  
  @HttpPost  
   global static String doPost() {  
     /*  
       RestContext Class - Allows us to access the RestRequest and RestResponse objects in your Apex REST methods.   
       RestRequest class - Allows us to pass request data into our Apex RESTful Web service method.  
       RestResponse class - Allows us to pass or send back response data from our Apex RESTful web service method  
     */  
     //Returns the RestRequest object for our Apex REST method.  
     RestRequest request = RestContext.request;  
     //Returns the RestResponse for our Apex REST method.  
     RestResponse response = RestContext.response;  
     //Access the request body with input data coming in the JSON format  
     String jSONRequestBody=request.requestBody.toString().trim();  
     //Deserializes the input JSON string into an Account object  
     Account accObj = (Account)JSON.deserializeStrict(jSONRequestBody,Account.class);  
     //insert the account object and return the account ID   
     insert accObj;  
     return accObj.Id;  
   }  
   /*  
   HttpGet method is used to capture a HttpGet request has been sent to our rest apex class.  
   Used to request data on the basis of a parameter sent in the URL  
  */  
  @HttpGet  
   global static Account doGet() {  
   /*  
       RestContext Class - Allows us to access the RestRequest and RestResponse objects in your Apex REST methods.   
       RestRequest class - Allows us to pass request data into our Apex RESTful Web service method.  
       RestReponse class - Allows us to pass or send back response data from our Apex RESTful web service method  
     */  
     //Returns the RestRequest object for our Apex REST method.  
     RestRequest request = RestContext.request;  
     //Returns the RestResponse for our Apex REST method.  
     RestResponse response = RestContext.response;  
     //Retrieve the parameter sent in the URL  
     String accountId = request.requestURI.substring(request.requestURI.lastIndexOf('/')+1);  
     //query the account on the basis of id sent and return the record  
     Account acc= [SELECT Id, Name, Phone, Website FROM Account WHERE Id = :accountId];  
     return acc;  
   }  
 }  


Call the Rest  WebService
Set up in salesforce org
1.        Go to Setup, click Create | Apps, and in the Connected Apps section, click New to create a new Connected App.

2.        Enter a Connected App name.
3.        Enter the contact email, as well as any other information appropriate to your application.
4.        Under Section ‘OAuth Settings’, mark the enable OAuth Settings checkbox and enter a Callback URL for example:  https://ap1.salesforce.com/services/oauth2/token



5.        Enter an OAuth scope. Select :




a.        Perform requests on your behalf at any time (refresh_token)
b.        Provide access to your data via the Web (web)
c.        Access and manage your data (API)
6.        Click Save. The Consumer Key is created and displayed, and a Consumer Secret is created (click the link to reveal it).


Call webservice using cURL

To call the rest apex class from outside salesforce, we either need to set up cURL or a client/system capable of making http request. Here is an example showing how to use cURL to call the REST service. 

FIRST we need to download the curl executable file (SSL enabled), preferably from http://curl.haxx.se/download.html (corresponding to the OS and the version) . cURL has some user friendly commands to call the rest service with OAuth authentication.

1.       Command to receive the authorization token :


 curl --form client_id=[Your client Id] --form client_secret=[Your client secret] --form grant_type=password --form username=[Your Username] --form password=[Your Password+Your Security Token] -k https://[Your salesforce instance].salesforce.com/services/oauth2/token  

For example :
curl --form client_id=3MVG9_7ddP9KqTzd_3A4dh9sZ4fpxuyOxHUCQ.GRu6EY7ETY2xFAGBrkv8BO17HmOR_X47cahreAbO7WjQgLd --form client_secret=2607521253690956513 --form grant_type=password --form username=test@gmail.com --form password=password1$RjzaF3v6HahniNEWpxUlUIoG -k https://cs10.salesforce.com/services/oauth2/token  


2.        Use cURL to call the webservice
a.       Command to GET account details using the authorization token received from the above command :

 curl -X GET https://[Your salesforce instance].salesforce.com/services/apexrest/ [URI Mapping] /[account Id] -H "Authorization: OAuth [Your authorization token]" -k  

For example :
 curl -X GET https://ap1.salesforce.com/services/apexrest/Account/0019000000Nah1a -H "Authorization: OAuth 00D90000000kIy777RYAQGVLW60UaT.yKMONqfjztdq1__6SGL70qOVFtwvYwj_4oykw7_QgKOTbl6jhZDAaYgtTW0ZR9THihS29MwPHAEuyxFbM" -k   


b.      Command to POST and create account using the authorization token received from the above command :

Suppose we use a JSON file with the following input:

  
 {  
             “Name”:”testaccount”,  
             “Phone”:”1234567890”  
 }  

 curl https://[Your salesforce instance].salesforce.com/services/apexrest/ [URI Mapping] /[account Id] -H "Authorization: OAuth [Your authorization token]" -H "Content-Type: application/json" -d @[Name of JSON file] -k  

For Example :
curl https://ap1.salesforce.com/services/apexrest/Account/ -H "Authorization:OAuth 00D90000000kIy777RYAQGVLW60UaT.yKMONqfjztdq1__6SGL70qOVFtwvYwj_4oykw7_QgKOTbl6jhZDAaYgtTW0ZR9THihS29MwPHAEuyxFbM" -H "Content-Type: application/json" -d @account.json -k  

This demo demonstrates how to create/query account using simple HTTP calls. This example can be extended further to accomplish more complex tasks.

Further JSON support makes REST Webservices excellent way to integrate with External Systems including legacy systems.  REST Webservices can be used to integrate two different Salesforce Org and let them talk seamlessly. In next part we will be covering How to use Rest Webservices to integrate two different Salesforce Orgs. 




Tuesday, June 25, 2013




Well here is a much awaited and the needed update for the PageBlockTable Enhancer plugin. Ever since I coded the first version, there were request for many features and this 2.2 version brings down some of them.

Here is what is new with this plugin
  1. Parameter to turn on and off Pagination.
  2. Support for specifying available page sizes.
  3. Support for choosing default page size on page load.

List o Parameters
  • targetPbTableIds : comma-separated Ids of the target Pageblock tables
  • paginate : Assign true if you want to use the pagination feature,default value is true.
  • pageSizeOptions : A comma seperated list of integer values that will displayed as dropdown for page size
  • defaultPageSize : Default page size that needs to be selected (at page load).
Ajax/Rerender support
  • This version brings in support for rendering, the earlier version wasn't able to handle this. So incase you are rerendering your table or the parent components, you can call the "initPageBlockTableEnhancer()" method from "oncomplete" even of your commandButtons/actionFunctions/actionSupport/commandLink .

    <apex:commandButton value="Rerender" reRender="mid" oncomplete="initPageBlockTableEnhancer()"/>
Basic Syntax
The basic syntax remains same, just few added params.

<c:PageBlockTableEnhancer targetPbTableIds="mid,mid2" paginate="true" defaultPageSize="5" pageSizeOptions="5,10,20,30,40,50,100"/>    
   <apex:pageBlock >   
     <apex:pageBlockTable value="{!accounts}" var="acc" id="mid">   
      <apex:column value="{!acc.Name}"/>   
     </apex:pageBlockTable>    
     <apex:pageBlockTable value="{!accounts}" var="acc" id="mid2">   
      <apex:column value="{!acc.Name}"/>   
     </apex:pageBlockTable>     
   </apex:pageBlock>  


Demo And Installation / Unmanaged Package: http://blogforce9dev-developer-edition.ap1.force.com/ProjectDetail?id=a0290000007rdwd
[Updated @ 27-Nov-2013 :  Bug Fixes related to sorting]

Thursday, June 6, 2013


What are wrapper classes?

Wrapper classes can be considered as user defined data types. Wrapper classes can enclose together many other variables/parameters to represent a object or a single entity. They can include primitive types, complex types, Sobject types and even other wrapper classes as their property.

Lets assume we want to define a Entity say "Student". So for this we have to define a Wrapper class "Student"with properties like RollNumber,Name,Email. The class will look like.

Public class Student{  
  public String RollNumber;  
  public String Name;  
  public String Email;  
 }  

Where we can use these wrapper classes ?

Lets consider a real life scenario where user is allowed to select some records from a pageblock table and is allowed to do some action on the selected records.

So in our case lets assume the Sobject is Account, user will be allowed to select some records from a list and say they will be allowed to delete the selected record using a button.



How to implement this ?

Well we can always fetch some records to the pageblocktable to display set of records in table, but how to bring back the selection to controller ? Well here comes the need of another property in picture which will bring back the selection to the controller. This can achieved by creating a extra checkbox field in sobject but doesnt sounds like a good plan. A new field just for selection ? well Wrapper classes will be a better option here. We will define a wrapper class with this additional property say "isSelected" and will use the same in the page.

So the wrapper class will look like

public class sObjectWrapper{  
  public boolean isSelected{get;set;}  
  public Account myAccount{get;set;}  
  public sObjectWrapper(Account myAccount,Boolean isSelected){  
   this. myAccount = myAccount;  
   this.isSelected = isSelected;  
  }  
 }  

Now how to populate this wrapper class ?

You may have to modify your code to populate List< sObjectWrapper > instead of List<SObject>. So lets say you have a method "getData" in controller that queries for the related records, you may want to modify the same to support wrappers.

So the controller will look something like this

public class WrapperDemo_Con {  
   /*List of wrappers*/  
   public List<sObjectWrapper> wrappers{get;set;}  
   /*Constructor*/  
   public WrapperDemo_Con(){  
     wrappers = getData();  
   }  
   /*method to delete the selected record*/   
   public void deleteRecords(){  
     List<Account> accToDel = new List<Account>();  
     for(sObjectWrapper wrap : wrappers){  
       /*Check if record is selected*/  
       if(wrap.isSelected){  
         accToDel.add(wrap.myAccount);  
       }  
     }  
     /*Delete the selected records*/  
     delete accToDel;  
     /*Referesh the data*/  
     wrappers = getData();  
   }  
   /*mehtod to query account and populate wrappers*/  
   private List<sObjectWrapper> getData(){  
     List<sObjectWrapper> wrappers = new List<sObjectWrapper>();  
     for(Account acc : [SELECT Name,Id,Phone, Description FROM Account]){  
       /*Create a new wrapper and add it to list*/  
       wrappers.add(new sObjectWrapper(acc,false));  
     }  
     return wrappers;  
   }  
   /*Wrapper class*/  
   public class sObjectWrapper{  
    public boolean isSelected{get;set;}  
    public Account myAccount{get;set;}  
    public sObjectWrapper(Account myAccount,Boolean isSelected){  
     this.myAccount = myAccount;  
     this.isSelected = isSelected;  
    }  
   }  
 }  

And the corresponding VF page will be

<apex:page controller="WrapperDemo_Con">  
   <apex:sectionHeader title="Demo" subtitle="Wrapper Class"/>  
   <apex:Form >  
     <apex:pageBlock title="Wrapper Demo">  
       <apex:pageBlockButtons >  
         <apex:commandButton value="Delete" action="{!deleteRecords}"/>  
       </apex:pageBlockButtons>  
       <apex:pageBlockTable value="{!wrappers}" var="wrap">  
         <apex:column headerValue="Select">            
           <apex:inputCheckbox value="{!wrap.isSelected}"/>  
         </apex:column>  
         <apex:column value="{!wrap.myAccount.name}"/>  
         <apex:column value="{!wrap.myAccount.phone}"/>  
       </apex:pageBlockTable>  
     </apex:pageBlock>  
   </apex:Form>  
  </apex:page>  


Now testing time! Select few records from the list and press the save button. The selected records should be delete d and page should reload with the current data set.

In a similar fashion you can wrap any Sobject or Even wrap another wrapper class to get desired result. May be something more complicated!

Saturday, May 18, 2013


Few days back I came across a requirement which where user needed a scheduled job, that invokes after x days of record creation and creates a clone record.

So my initial thought was Scheduled Apex job but that doesn't seem to fit for this case because of the limit on number of scheduled jobs that can be scheduled. So started thinking of another approach and solution was pretty simple

WorkFlow Time Trigger + Apex Trigger = Invoke Apex @ Future Date.

Wasn't the equation clear enough? 
Well let me explain the same in steps.

  • Define Workflow
    • Create a new workflow 
      • Specify a entry criteria that fits your requirement. In my case it needs to go inside the  workflow as soon as it is created. So I just used formula editor and entered formula as "TRUE" as Rule Criteria and Evaluation Criteria as "Created". 
    • Add Time Trigger
      • Add time trigger to the apex and provide appropriate time duration. In my case I chose 30 days from "Rule Trigger Date"(Which will be same as created date). 
    • Add a field Update to the time trigger
      • Now add a field update that will be used by Apex Trigger to execute a class. So In my case the custom object had a custom field with the name "invokeApex__c" which was by default set to "FALSE".
      • Create a field update that will set this to "TRUE"

Well now you are done with the configuration part. Lets write some code
  • Creating a APEX Trigger.
    • Sample trigger will look like
       trigger invokeApexCloning on Demo__c (after update__c) {  
         for(Demo__c demo : trigger.New){  
           if(demo.invokeApex__c != trigger.Old.get(demo.Id).invokeApex__c && demo.invokeApex__c == TRUE){  
             //invoke your action here  
             CloningUtil.clone(demo);  
           }  
         }  
       }  
      
       
    • Modified version if you want to bulkify the same
       trigger invokeApexCloning on Demo__c (after update__c) {  
         List<Demo__c> demoList = new List<Demo__c>();  
         for(Demo__c demo : trigger.New){  
           if(demo.invokeApex__c != trigger.Old.get(demo.Id).invokeApex__c && demo.invokeApex__c == TRUE){  
             demoList.add(demo);  
           }  
         }  
         //invoke bulk action from here  
         CloningUtil.clone(demoList);  
       }  
      
Well thats all we are set now. This code setup will let you clone the records after 30 days. Now you know the secret to mix Time Triggers with Apex Triggers ;)

Thursday, May 9, 2013


[Live Demo]

This is another blog regarding so called Easy Jquery Component.Now this component helps you to generate  the Jquery Tabs very easily in a Visualforce pages. Follows the same syntax as the standard component, with added Jquery goodness. Pretty straight forward and can include standard components inside the Jquery tabs.

How it looks like ?



How to use the components?

  • <c:Tabpanel> : A wrapper component that holds all the tab together inside a panel.
  • <c:Tab> : Represents a single Tab inside a tabpanel.
Below is a sample code to generate a Jquery Tab

<!--Tab Panel -->  
   <c:Tabpanel >  
     <!--First Tab-->  
     <c:Tab title="Tab 1">  
       This is a tab 1. You can add standard component inside also.  
       <apex:pageBlock title="Standard page block">  
         This is a pageblock component.  
         <br/>  
         <apex:pageBlockSection title="This is a section" collapsible="false">  
         </apex:pageBlockSection>  
       </apex:pageBlock>  
     </c:Tab>  
     <!--Second Tab -->  
     <c:Tab title="Tab 2">  
       This is a tab 2  
     </c:Tab>  
   </c:Tabpanel>  

Codebase