Salesforce custom settings are nice in development env. But you get Null Pointer Exception in orgs where we deploy the same code, this is because Custom Settings need at least a single record to give a valid Sobject handle for CustomSetting__c.getInstance() call. Here is the sample scenario that covers this issue and shows solution.
Custom Setting
Screen cast show a Custom setting named “MyCustomSetting__c” created.
Custom Setting’s – Custom field
A single custom field named “Config_Field_1__c” is defined for the custom setting above. Please note that its value is defaulted to ‘Hello World’.
Code accessing Custom Setting
Here is the sample code that tries to read the value of the custom setting defined above.
System.debug('MY CUSTOM SETTING VALUE : ' + MyCustomSetting__c.getInstance().Config_Field_1__c);
Upon execution it will throw Null Pointer exception if there is no value defined at organization, matching profile or user level. The fix to this issue is simple you can add this single line of code before accessing the custom setting value.
if (MyCustomSetting__c.getInstance() == null)
upsert new MyCustomSetting__c (SetupOwnerId=UserInfo.getOrganizationId());
If the custom setting type is “LIST” you need to change the above one liner a little. This is because for “LIST” type custom settings Name is a mandatory attribute. Here is the code snippet.
if (MyCustomSetting__c.getInstance() == null)
upsert new MyCustomSetting__c (Name = ‘MyCustSettingName’, SetupOwnerId=UserInfo.getOrganizationId());
This code just creates an organization wide value for your custom setting, if that doesn’t already exists. So now accessing this code prints “Hello World” on console.
Important Notes
Success of the above approach depends on the way you configured your Custom Setting’s Field. Its highly recommended you create custom setting’s fields with some intelligent default values.
Create a Singleton class called CustomSettingsHelper to encapsulate all custom setting’s access logic in one place. This will also give you a chance to put this single liner code in single place, so that you don’t need to make call to this one liner before accessing any custom setting field. Here is a sample
public class CustomSettingsHelper { /** The SINGLETON handle to the instance */ private static CustomSettingsHelper self; public static CustomSettingsHelper self() { if (self != null) return self; // To create org wide defaults in new org automatically. This // will prevent NPE's in future. if (MyCustomSetting__c.getInstance() == null) { upsert new MyCustomSetting__c (SetupOwnerId = Userinfo.getOrganizationId()); } self = new CustomSettingsHelper(); return self; } // No body needs to construct it, a single reference will suffice. private CustomSettingsHelper() { } // This method can be used to access the custom settings public String getConfigField1() { return MyCustomSetting__c.getInstance().Config_Field_1__c; } // Client Code that shows how to access the custom setting public static testmethod void testCustomSetting() { System.assertEquals('Hello World', CustomSettingsHelper.self().getConfigField1()); } }
Comments (6)
Anonymoussays:
April 5, 2010 at 2:10 pmI had some rubbish code in to cope with this but am now using your “if null insert it” pattern. Much cleaner – thanks.
Anonymoussays:
April 5, 2010 at 2:24 pmWelcome @Force201, nice to see that this technique helped you.
Anonymoussays:
May 11, 2010 at 5:20 pmI'm afraid I've now run into trouble with this when packaging. Please add a comment to this if you have any ideas:http://community.salesforce.com/t5/Apex-Code-Development/Custom-settings-initialization-failing-on-package-re-install-if/td-p/183770The problem occurs whether I use insert or upsert.
Anonymoussays:
May 11, 2010 at 6:52 pmAdded my response to the forum page : http://community.salesforce.com/t5/Apex-Code-Development/Custom-settings-initialization-failing-on-package-re-install-if/td-p/183770
Anonymoussays:
November 4, 2010 at 6:08 amcustom setting values is avialble in vf pages?
Anonymoussays:
November 4, 2010 at 6:27 amyou can't directly do $CustomSetting in VF page. Thumb rule is to treat Custom Setting as SObject for getting values in visualforce pages. So one needs to create an class attribute and access it, as shown below:Controller===========public class SomeController {public MyCustomSetting__c setting {get ;set;}public SomeController () {this.setting = MyCustomSetting__c.getInstance();}}VF Page:=========I used MyCustomsetting__c as explained in the post above.