Wednesday, February 25, 2015

, , ,

Code and Visualforce Optimization using Custom Component and Abstraction


This post aims at minimizing Apex code and reusing visual force construct using custom components.

Let us start with a straight forward implementation, forgetting about any optimization. My requirement is I want to display an Account's Annual revenue only on a button click via a custom page.
I want do the same on the Contact page as well, here showing the associated Account's annual revenue.
I create two separate visualforce pages and two separate apex controllers to support them.
I added the visual force pages as inline to the Account layout and the Contact layout respectively.
Page 1: GetAccountAnnualRevenue
<apex:page standardController="Account" extensions="AnnualRevenueController">
<apex:form >
    <apex:pageBlock >
        <apex:pageBlockButtons location="top">
            <apex:commandButton value="Click Here" action="{!fetchAnnualRevenue}"/><br/><br/>
            <apex:outputText value="Annual Revenue   " />
            <apex:outputText value="{!annualRevenue}" label="Annual Revenue"></apex:outputText><br/>
        </apex:pageBlockButtons>
    </apex:pageBlock>
</apex:form>
</apex:page>


Controller 1: AnnualRevenueController 
public with sharing class AnnualRevenueController {

  public String annualRevenue {get;set;}
  public Id objectId {get;set;}
  public Account account {get;set;}
  
  public AnnualRevenueController(ApexPages.StandardController stdController){
    account = [SELECT Id,Name,AnnualRevenue
                  FROM Account WHERE Id =: ApexPages.currentPage().getParameters().get('id')];
  }
  
  public void fetchAnnualRevenue(){
    annualRevenue = account.AnnualRevenue.toPlainString();
  }
}

Page 2: GetContactAnnualRevenue
<apex:page standardController="Contact" extensions="ContactAnnualRevenueController">
<apex:form >
    <apex:pageBlock >
        <apex:pageBlockButtons location="top">
            <apex:commandButton value="Click Here" action="{!fetchAnnualRevenue}"/><br/><br/>
            <apex:outputText value="Annual Revenue   " />
            <apex:outputText value="{!annualRevenue}" label="Annual Revenue"></apex:outputText><br/>
        </apex:pageBlockButtons>
    </apex:pageBlock>
</apex:form>
</apex:page>

Controller 1: ContactAnnualRevenueController
public with sharing class ContactAnnualRevenueController {
  public String annualRevenue {get;set;}
  public Id objectId {get;set;}
  public Contact contact {get;set;}
  
  public ContactAnnualRevenueController(ApexPages.StandardController stdController){
    
    contact = [SELECT Id,Name,Account.AnnualRevenue
                  FROM Contact WHERE Id =: ApexPages.currentPage().getParameters().get('id')];
  }
  
  public void fetchAnnualRevenue(){
    annualRevenue = contact.Account.AnnualRevenue.toPlainString();
  }
}

The Account Page shows the Annual revenue something like this:
And on click


Now, we are doing the same thing for two different pages, the only difference is the way we pull in the Annual Revenue data. Once from an Account record and the second time from a Contact record.
We display the exact same thing, but have ended up putting in the same lines for the two different pages. If we tomorrow decide to show the same for an Opportunity record, we will mimic all the lines of code in another page. Unnecessary.
Now, let us collate these together for a more precise solution.
First, what we show in both the pages, and perhaps multiple other pages in future, come into a component as below:
<apex:component >
<apex:attribute name="revenueController" description="This is the Controller" type="AnnualRevenueController" required="true"/>
<apex:form >
    <apex:pageBlock >
        <apex:pageBlockButtons location="top">
            <apex:commandButton value="Click Here" action="{!revenueController.fetchAnnualRevenue}"/><br/><br/>
            <apex:outputText value="Annual Revenue   " />
            <apex:outputText value="{!revenueController.annualRevenue}" label="Annual Revenue"></apex:outputText><br/>
        </apex:pageBlockButtons>
    </apex:pageBlock>
</apex:form>
</apex:component>

Now, the Visualforce page can be concised to as :
<apex:page standardController="Account" extensions="AnnualRevenueController">
<c:commonannualrevenuedisplay revenueController="{!this}"></c:commonannualrevenuedisplay>
</apex:page>

Ok, let's see what we did. The Visualforce component does all the work. From the page we just assign the instance of the AnnualRevenueController class to the revenueController attribute of the component. Using the revenueController the component can fetch and display the revenue.
The actual Annual Revenue is fetched from database by the AnnualRevenueController.
To make this work, add the below lines to your AnnualRevenueController 
//returns the instance of this class
    public AnnualRevenueController getThis(){
      return this;
    }

This above snippet of code, basically, returns the current instance of the AnnualRevenueController class to the visualforce page and in turn the component.

So, we slimmed down the visualforce page. However, we still have a problem here.

We arrived at a station but not our destination. What happens to our Contact page? I have passed the Account related controller to the component, and hence it would work only for the Account page.
Here, we do another trick - one of the strongest tool OOPs provides - "ABSTRACTION"
We create an abstract class to fetch and initialize the Annual revenue from the page. See below:
public abstract class AbstractAnnualRevenueController{
    abstract String getAnnualRevenue();
    public String annualRevenue{get;set;};
    
    public void fetchAnnualRevenue(){
        annualRevenue = getAnnualRevenue();
    }
}

Now, abstract class is a class which cannot be initialized. Simply put, this class is incomplete. We have declared a method getAnnualRevenue, but never defined what is does.
Here,is where, abstraction starts, as we mark this method as abtract, we need not define it, but we enforce other classes (child) who extend this class to define this method.
The individual classes can decide what to do inside and what final value to return. 
So, the trick is let the page get the details from the same attribute/methos. Internally, you channel your method to fetch the actual relevant data.

Now,let us see what changed in our controller classes


public with sharing class AnnualRevenueController extends AbstractAnnualRevenueController{

   public Account account {get;set;}
        
    public AnnualRevenueController(ApexPages.StandardController stdController){
        account = [SELECT Id,Name,AnnualRevenue
                                  FROM Account WHERE Id =: ApexPages.currentPage().getParameters().get('id')];
    }            
    //returns the instance of this class
    public AnnualRevenueController getThis(){
      return this;
    }
    
    public String getAnnualRevenue(){
        return account.AnnualRevenue.toPlainString();
    }
}



public with sharing class ContactAnnualRevenueController  extends AbstractAnnualRevenueController {
    
    public Contact contact {get;set;}    
    public ContactAnnualRevenueController(ApexPages.StandardController stdController){
        
        contact = [SELECT Id,Name,Account.AnnualRevenue
                                  FROM Contact WHERE Id =: ApexPages.currentPage().getParameters().get('id')];
    }    
    //returns the instance of this class
    public ContactAnnualRevenueController getThis(){
      return this;
    }
    
    public String getAnnualRevenue(){
        return contact.Account.AnnualRevenue.toPlainString();
    }
}

As simple as that, and now we make a very small change in our component


<apex:attribute name="revenueController" description="This is the Controller" type="AbstractAnnualRevenueController" required="true"/>

Our contact page can also be concise now:


<apex:page standardController="Contact" extensions="ContactAnnualRevenueController">
<c:commonannualrevenuedisplay revenueController="{!this}"></c:commonannualrevenuedisplay>
</apex:page>

And that completes our goal. Our Account and Contact page successfully renders the Annual Revenue : 


We reused a single component and an abstract class to create a custom page displaying the Annual revenue for an Account, a Contact and in future can plug in any object to show its Annual revenue. 
All we need to do is extend the class AbstractAnnualRevenueController and override the method getAnnualRevenue. Voila!!
Try doing this for an Opportunity record. It will be a cake walk.

Hope all of you enjoyed this, do post your comments and any queries.


Saturday, February 14, 2015

, , ,

Using Hierarchical Custom Setting to your Advantage



Salesforce gives you many a construct to make your life easier and present your users a very customized and relevant UI to work on.
To begin my Salesforce post, I will start with such a one - Hierarchical Custom Settings.
The Salesforce Hierarchical custom settings gives you a way to use the Salesforce profile and user variations to make your UI more relevant and useful to a particular user or type of user.
To demonstrate the power of Hierarchical custom settings, let us take up a very simple and basic example.
I have a custom object called Survey in my org. The object records are visible to all users in the org, however, I want only a specific type of user - Recruiters to be able to delete any irrelevant survey.
Even as a recruiter deletes a survey, I have a set of additional logic running behind the screen to do so.
I override my standard Survey detail page with a Visualforce page to begin with, as I want some additional UI customizarions.
To begin with, I remove the standard delete button from my Survey page layout.

I just add the below to my Visualforce page, to display the basic fields on the Survey Detail Page

<apex:page standardController="Survey__c">
  <apex:detail relatedList="false" />
</apex:page>

Now, as any type of user I will only see the 'Edit' and 'Submit for Approval' buttons on the Survey detail page

Now, we go ahead and create a new Hierarchical Custom Setting to be used to make my Visualforce page display a Delete button only for a Recruiter.

We create a new Checkbox field in the Custom settings

With 'Manage' we set the 'canDeleteSurveyRecords' value to true/checked only for a Recruiter

Now, a very important aspect of Hierarchical Settings.Your next thought may come to the point, that your org or any org may have several Profiles and hundreds of users to work with.
Do we set the fields of a custom settings for all the profiles and users ?!
The Answer is NO.
We use the Default Organization Level Value of a Hierarchical custom setting.


In our case we want it to be false for any one else so we leave the check box unchecked.

Now we change our visualforce page, I have added an additonal text just to print the value of the settings for convenience
<apex:page standardController="Survey__c">
  <apex:detail relatedList="false" />
  <apex:form >
  <apex:pageBlock>
  <apex:pageBlockSection >
      <apex:outputText label="Value on Hierarchy Setting" value="{!$Setup.UserAccessSettings__c.canDeleteSurveyRecords__c}"/>
      <apex:commandButton value="Delete" rendered="{!$Setup.UserAccessSettings__c.canDeleteSurveyRecords__c}"/>
  </apex:pageBlockSection>
  </apex:pageBlock>
  </apex:form>
</apex:page>
This does nothing, just makes the commnadbutton 'Delete' rendered based on the value of the Hierarchical custom setting - canDeleteSurveyRecords field.
Now, we login as System admin the page will look like
However, as a Recruiter, I see

So, with intelligent use of Hierarchical Custom settings, you can customize your visualforce pages, with no additional lines of logic in your page.
Similarly, you can branch out your Apex code and and its flow based on a User or a User profile using the very effective Hierarchical Custom settings.

Hope this helps you to design more intelligent and manageable pages and classes.

In my next post, I will be talking about how to make your email templates display your desired information.