A blog dedicated to Salesforce Ohana

Implementing Singleton Design Pattern in Apex - Use Case I


This post is part of the series - Design Pattern in Apex
Singleton Design Pattern is pretty popular and one of the simplest design pattern available.
I will start with the statement from “The Gang of Four” as it describes Singleton Pattern as  –
“Ensure a class has only one instance, and provide a global point of access to it.”

In this post, I will explain why we need to have Singleton Design Pattern in Apex and how to implement the same.

Sometimes it is very much required to have only instances of the class – Logger, Window Manager etc. Typically, these type of objects where only one instance is sufficient to handle the requirements, are called Singleton.

With Singleton Design Pattern, you can –
  • Ensure that only one instance of class is getting created.
  • Provide a global point of access to the object.
There are many ways to implement Singleton Pattern in apex. Let’s start with few case scenarios:

Use Case:
Consider the below requirement -
Whenever a new account is getting inserted to Salesforce, it should be synced with MDM(Master Data Management) through integration. But if MDM system is down, then Salesforce should not got for synchronization.

Let's start implementing the requirement -

Custom Settings - Integration - This will be used to identify whether MDM System is up and running. If MDM System is down, Admin will uncheck the value and then Salesforce will not try for synchronization. Below is how custom settings will look like -
AccountTriger-

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
trigger MyAccountTrigger on Account (before insert) {
 for(Account anAccount : Trigger.new){
  AccountHelper myAccountHelper = new AccountHelper();
  if(myAccountHelper.isSyncEnabled){
   //Call Sync Methods
  }else{
   //Do nothing
  }
 }
}

AccountHelper -

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public with sharing class AccountHelper {
 public Boolean isSyncEnabled {get;private set;}
 
 public AccountHelper(){
  Integration__c mdmIntegration = Integration__c.getValues('MDM');
  isSyncEnabled = mdmIntegration.isEnabled__c;
 }
}

Now if you test, this code will work fine. But this code is having a very basic problem.

Let's understand the problem first by going through the trigger. Consider line#2 where we are iterating through the list of accounts via Trigger.new. Now think of a scenario where we are inserting huge amount of accounts through dataloader. So in that case Trigger.new will return us huge list and we will iterate through each account and create an instance of our AccountHelper class.

Now inside AccountHelper class constructor, we are checking values from our custom settings.

So what will happen, for all the records, we will create a new instance and query custom object every time. Do you think this is really necessary?

Definitely not. But why? The reason is that in the same transaction, we don't need to create multiple instances and check custom settings every time. In a single transaction, if Trigger.new is returning us a list of 200 accounts, we should create a single instance of AccountHelper class which will query our custom objects once. Great!! But now the question is how we can achieve that ??

Below is the updated code -
AccountTrigger -

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
trigger MyAccountTrigger on Account (before insert) {
 for(Account anAccount : Trigger.new){
  AccountHelper myAccountHelper = AccountHelper.getAccountHelperInstance();
  if(myAccountHelper.isSyncEnabled){
   //Call Sync Methods
  }else{
   //Do nothing
  }
 }
}
AccountHelper -

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
public with sharing class AccountHelper {
 private static AccountHelper accountHelperInstance = null;
 public Boolean isSyncEnabled {get; private set;}
 
 private AccountHelper(){
  Integration__c mdmIntegration = Integration__c.getValues('MDM');
  isSyncEnabled = mdmIntegration.isEnabled__c;
 }
 
 public static AccountHelper getAccountHelperInstance(){
  if(accountHelperInstance==null){
   accountHelperInstance = new AccountHelper();
  }
  return accountHelperInstance;
 }
}

Below are the changes -
  • The static getAccountHelperInstance() method will only instantiate an instance of the class if it doesn't already exists. 
  • The constructor and accountHelperInstance variable is private, which will make sure that it cannot be instantiated outside of the getAccountHelperInstance() method.
I hope this will help you to understand why we need Singleton Design Pattern. I will write few more use cases in my next posts. Till then if you have any feedback, please let me know. 

Wishing you a happy learning.


           
Share:

How to handle DUPLICATE_USERNAME error while performing deployment


Recently, while doing deployment through change set, I faced an issue -
System.DmlException: Insert failed. First exception on row 0; first error: DUPLICATE_USERNAME, Duplicate Username.
Another user has already selected this username.
Please select another.: [Username]"


The username used in test classes were definitely unique, but still my test classes were failing with the below error message. After spending some quite amount of time, I have understood the problem. So thought of putting this in my blog hoping that it may help someone in future.

So here it goes -
Error message -
System.DmlException: Insert failed. First exception on row 0; first error: DUPLICATE_USERNAME, Duplicate Username.
Another user has already selected this username.
Please select another.: [Username]"


Reason -
Usernames are always shared across instances, but not across environments. It means if a user is having username as test@test.com in any sandbox, then this same username you can't use in any other sandbox instances (CS*), but you can user the same username in production sandboxes (NA*, EU*, AP*). 

Uniqueness is always checked during deployment when tests are run. So an insert from test class will also fail if the username is already registered in another org in the same environments. So we need to make sure the uniqueness in maintained in test classes.

Resolution -
To be 100% sure that the username used in test classes are unique, you should follow the below approach to define the username -

    String orgId = UserInfo.getOrganizationId();
    String dateString = String.valueof(Datetime.now()).replace(' ','').replace(':','').replace('-','');
    Integer randomInt = Integer.valueOf(math.rint(math.random()*1000000));
    String uniqueName = orgId + dateString + randomInt;


Below is the link which you can check. Link

Share:

"The Power of One" in Salesforce Formula Field


Most administrators think formula field is a way to do calculation in the pages such as finding out the final price after deduction, calculate date operation etc. But in Salesforce, formula field can be utilised to do more powerful stuffs. In today's post, I will explain the "The Power of One" in Salesforce Formula Field.

Business Case -
Company "Universal Bank" is using Salesforce's out of the box contact and activity standard object to track the each contact's activities. Now a contact can have multiple activities. So the requirement is to run a report which will tell the total number of distinct contacts having some activities. 

Implementation -
Now if you run a report, you will get something like this below -
Now if you see the report is showing grand total as 12 as we have many contacts having more than one activities. But our requirement is to show total number of distinct contacts having some activities.

And here comes "The Power of One". This will help us to achieve our requirement. 
First we need to create a formula field in Contact object as shown below -

Point to be noted - the value of the formula is field is 1 and that is why the name is "The Power of One". Cool.
Now add this field in the report and do Summarize by this field using Sum option. Picture is shown below.
One done, save and run the same report. Below is what you will get -
Now you can see the report is showing 5 as the right bottom of the report which is showing the number of distinct contacts having some activities.

Awesome. So this trick is always useful when you are dealing with multiple objects in the report and you want a count of some object other than the one the report is originally based on i.e. activities.
Share:

Importance of Equals and Hashcode in Apex

Recently while doing code review, I found that all developers should have fundamental understanding of "Why we should implement always Equals and Hashcode in Apex?"

In this post, I am going to share my knowledge with few examples to understand the importance of Equals and Hashcode in Apex.

Apex provides you an option to define an equal method in your custom types. This Equals method along with Hashcode is must when you are going to use your custom types in Sets and as Map keys. I would recommend to make this approach (Implementation of Equals and Hashcode) as best practice. Equality operator (==) is going to use the Equals operator if it is defined.

Why we need this Equals method?
Let me start with one example to show you the problem if Equals method is not implemented. Below is the custom type I am having -

Now below is the test class to compare two instances of MyCustomType. Both the instances of MyCustomType is having myField value set to 10. So my expectation is that when I will compare both the instances, they should return true. Let's see what will happen. Below is the test class.

But unfortunately, below is what you will get -
You see our test class is failing. Do you know the reason? Let me tell you the reason. The reason for this comparison to fail is that I don't have the Equals method in my MyCustomType implemented. If the Equals method is not implemented, then exact equality operator (===) will be used. As Salesforce's documentation states -

Exact Equality Operator (===)  always checks the exact same memory location. So if X and Y reference the exact the same memory location, then Exact Equality Operator (===) will return true, otherwise false.

But in the above case, I don't have Equals method implemented in my MyCustomType. So it will go for exact equality operator (===), but myCustomType1 and myCustomType2 are not referencing the same memory location. So the expression (myCustomType1 == myCustomType2) returns false.
Solution to the above problem -
Let me implement the Equals method in  and execute the same test method. Let's see what will happen then.

After implementing Equals method, the test will pass. Great.
Now I will explain Equals method in details. If you are coming from Java background, it is little different. So it makes sense to understand the concept well.
Deep Dive into Equals Method -
The method signature is: public Boolean equals(Object o). Very easy right!!!. But as a developer, you need to be aware of something. You can't write equals method like public Boolean equals(MyCustomType o). The reasons are -
  • The above implementation will not overwrite Object implementation and will not work with arguments other than of type MyCustomType 
  • The == operator will not use the equals(MyCustomType o) implementation.
Another point to notice at line# 5 (this === o). Here I have used exact equality operator (===) instead of == operator. The reason is if I have used == operator, then that operator will use the Equals method again. So it will become a recursive call and very soon we will hit by stack overflow.

There is another point to remember. As per the specification, the equals method should return null if null is passed. This is getting checked @ line# 8. But the point to make here is that "null instanceof anything will return false" this is available from API version 32.0 and above.
Before API 32.0, it is not available. So there you need to modify your line#8 like below -
if( ( o == null ) || !(o instanceof MyCustomType))
Great, but why we need this Hashcode then?
Apex documentation states that "If two objects are equal, based on the equals method, hashCode must return the same value".
So you should implement Hashcode also.

There is a good documentation on Salesforce. Here is the link . CLICK HERE.
I recommend everyone to read Effective Java by Joshua Bloch.

Share:

Salesforce Summer 15 New Feature || Now we can use Location and Distance Variables in SOQL and SOSL Queries

With Salesforce Summer'15 release, now we can use location and distance variable in SOQL and SOSL queries.

To know more about location and distance variable, I will request to check Salesforce's documentation @

Location-Based SOQL Queries


Now let me explain this new feature with a small code snippet.
In my account object, I have created one custom field of type Geolocation with name Head Office Location (API Name: Head_Office_Location__c).

Below is the code snippet -
As you can see in the above code what I am trying to find all the accounts whose head office is located within 1 miles from my current location. To achieve this, I have used my current location's latitude and longitude as apex bind variable in SOQL query.

The way DISTANCE and GEOLOCATION function work are given below -
  • DISTANCE(mylocation1mylocation2, 'unit')
  • GEOLOCATION(latitudelongitude)
Now after Summer'15, you can replace any of the parameters used in the above two functions by apex bind variable.

So to me, it is really a good feature. What do you guys think? Please provide your feedback. Thanks.

Share:

Follow Me

Enter your email address:

Delivered by FeedBurner

Popular Posts

Labels

Salesforce (105) Apex (44) admin (27) ADM (20) visualforce (20) dev 501 (19) integration (18) learn salesforce (18) 501 (16) SOAP (13) lightning (12) tutorial (11) Certification. (9) javascript (8) Trigger (7) test class (7) unit testing (7) Sharing and Visibility (6) design pattern (6) report (6) security (6) trailhead (6) Advanced Admin (5) Certification (5) Kitchener Developer Group (5) New Features (5) SOQL (5) css (5) dashboard (5) debug (5) developer (5) formula (5) mobile (5) salesforce release (5) service cloud (5) solution management (5) use case (5) JSON (4) Lightning Experience (4) Salesforce DX (4) WebSphere (4) best practice (4) cast iron (4) component (4) deployment (4) github (4) html (4) polymer (4) profiles (4) responsive (4) tdd (4) ui (4) Advanced Apex (3) Architect (3) Live Chat (3) Online Event (3) Performance (3) Products (3) Role (3) Sales Cloud (3) Scratch Org (3) Study Notes. (3) Summer15 (3) Tips (3) Web Technology (3) dynamic apex (3) event (3) license (3) map (3) mapbox (3) singleton (3) version controlling (3) Bulkify (2) Data Architecture and Management Certification (2) Devops (2) Distributed Version Controlling (2) ES6 (2) Eclipse (2) Einstein (2) Enterprise Territory Management (2) Financial Services Cloud (2) Force.com IDE (2) Governor Limit (2) Groups (2) IBM (2) Implicit Sharing (2) JourneyToCTA (2) Kitchener User Group (2) Lightning Design System (2) Live Agent (2) Metadata (2) Opportunity (2) Price Book (2) REST (2) SOSL (2) Sharing (2) Spring 15 (2) Summer17 (2) Territory (2) ant (2) automation tool (2) basic (2) chatter (2) coding (2) communication (2) console (2) controller (2) documentation (2) flow (2) git (2) jquery (2) logging (2) object (2) permission (2) process builder (2) release (2) salesforce1 (2) strategy (2) xml (2) Action Plan (1) Action Plan Template (1) Agent Productivity (1) Analytics (1) Apex Sharing (1) Arrow (1) Asynchronous callout (1) Aura Framework (1) Bots (1) Browser (1) Bulk data load (1) CTA (1) Calendar (1) Canon (1) Case Management (1) Cheat Sheet (1) Classic (1) Community (1) Constructor (1) Contact Center (1) Continuation (1) Continuous Integration (1) Convert (1) Cookie (1) Custom Metadata (1) Custom Object (1) Customer (1) Decorator Design Pattern (1) Dev Hub (1) Diwali (1) Email (1) FSC (1) Function (1) Goals (1) Guide (1) Household (1) Ideas (1) Improvement (1) KPIs (1) Large Data Volume (1) LastModifiedDate (1) Lightning Web Component (1) Manual Sharing (1) Metrics (1) New (1) OOPS (1) OWD (1) Omni-Channel (1) Partner (1) Person Account (1) Photo (1) Pipeline (1) Platform Developer I (1) Presentation (1) Product Schedule (1) Profile (1) Promise (1) Prototype (1) Public Site (1) Query Plan (1) QuickReference (1) Reports (1) Retrieve (1) Role Hierarchy (1) SFDX (1) Salesforce Optimizer (1) Session (1) Sharing Rule (1) Sharing Sets (1) Site (1) Skills (1) Snap-ins (1) Spring 17 (1) Summer14 (1) Summer16 (1) Switch (1) SystemModStamp (1) User License (1) Users (1) Webservice (1) Winter'15 (1) Winter'17 (1) access (1) agile (1) app (1) approval process (1) aura (1) awesome (1) backup (1) bitbucket (1) book (1) campaign (1) change set (1) code (1) code coverage (1) configuration (1) csv (1) custom button (1) custom settings (1) customization (1) data loader (1) database (1) delegate Admin (1) describe (1) dom (1) dreamforce (1) duplicate (1) dynamic (1) equals (1) error (1) field-level security (1) folder (1) ftp (1) generic (1) gift (1) global describe (1) hashcode (1) import wizard (1) jenkins (1) keynote (1) long running requests (1) monitoring (1) mysql (1) page layout (1) personal (1) power of one (1) record type (1) relationship (1) request (1) review (1) sub-tab (1) tab (1) username (1) visual workflow (1) workflow (1)

Total Subscribers

Total Pageviews