10

We have created a hierarchy custom setting to store some data instead of hard-coding it into our managed package.

Had I known that SF only auto-deploys the setting itself and NOT an Organization level record I would have NOT made that decision. But the beauty of Managed Packages is I am stuck with all previous incorrect decisions made so here I am.

But I digress...

In my APEX code that needs the setting to exist I want to check if there is an Org-level setting for the custom setting and if not get it created and set the fields to the values that I wanted to deploy with the managed package.

At first I tried:

       Equipment_Chatter_Settings__c ecs = Equipment_Chatter_Settings__c.getInstance();
       if(ecs == null)
       {
           ecs = new Equipment_Chatter_Settings__c(setupOwnerId = System.Userinfo.getOrganizationId());
           ecs.Assignment_Chatter__c = TRUE;
           ecs.Loan_Return_Chatter__c = TRUE;
           ecs.Assignment_Body__c = 'Equipment ~1~ ~2~ was assigned on ~3~';
           ecs.Assignment_Return_Body__c = 'Assigned Equipment ~1~ ~2~ was returned on ~3~';
           ecs.Loan_Body__c = 'Equipment ~1~ ~2~ was loaned on ~3~';
           ecs.Loan_Return_Body__c = 'Loaned Equipment ~1~ ~2~ was returned on ~3~';
           insert ecs;
       }

It appears that my 'ecs' object is not null because I never get into the IF that would create the record.

So I did some reading and tried something different - tried 'getOrgDefaults' and then check each field in my custom setting and if it is null update it to the appropriate value.

       ecsupdate = FALSE;
       Equipment_Chatter_Settings__c ecs = Equipment_Chatter_Settings__c.getOrgDefaults();
       if (ecs.ELTON__Assignment_Chatter__c == null) {ecs.ELTON__Assignment_Chatter__c = TRUE; ecsupdate = true;}
       if (ecs.ELTON__Loan_Return_Chatter__c == null) {ecs.ELTON__Loan_Return_Chatter__c = TRUE; ecsupdate = true;}
       if (ecs.ELTON__Assignment_Body__c == null) {ecs.ELTON__Assignment_Body__c = 'Equipment ~1~ ~2~ was assigned on ~3~'; ecsupdate = true;}
       if (ecs.ELTON__Assignment_Return_Body__c == null) {ecs.ELTON__Assignment_Return_Body__c = 'Assigned Equipment ~1~ ~2~ was returned on ~3~'; ecsupdate = true;}
       if (ecs.ELTON__Loan_Body__c == null) {ecs.ELTON__Loan_Body__c = 'Equipment ~1~ ~2~ was loaned on ~3~'; ecsupdate = true;}
       if (ecs.ELTON__Loan_Return_Body__c == null) {ecs.ELTON__Assignment_Body__c = 'Loaned Equipment ~1~ ~2~ was returned on ~3~'; ecsupdate = true;}                      
       if (ecsupdate == TRUE) {update ecs;}

That was significantly worse - it compiles clean but when I try to run it I get...

Apex script unhandled exception Visualforce Page: /apex/elton__Assign_Equipment caused by: System.LimitException: ELTON:DML currently not allowed Class.ELTON.Assign_Equipment.Init: line 94, column 1 Class.ELTON.Assign_Equipment.: line 43, column 1 (The error is referring to the last line in the above code snippet)

One thing that I do NOT want to do is start creating User or Profile level custom setting records. Our customers if they choose are more than welcome to use those types of records in their instance of our application but all I need is a default org level record if one doesn't already exist (the likelihood of a customer wanting anything but an org level record for this is slim-to-none)

Can anyone point me in the right direction?

  • So, to clarify - you want a default org level custom setting created as a default when you install your package? – Phil Hawthorn Nov 1 '12 at 14:36
  • That would be even better but I was told that is not possible - managed packages deal with the custom setting itself being created but there is no way to create default records in the custom setting. – AngiB Nov 1 '12 at 14:41
  • Have you tried Equipment_Chatter_Settings__c ecs = Equipment_Chatter_Settings__c.getInstance( UserInfo.getOrganizationId() ) in your code...? I'm sure that works to set Org Level Custom Settings...unless I'm misunderstanding what you need. – Phil Hawthorn Nov 1 '12 at 14:53
13

If I'm understanding correctly, I think this will work:

   Equipment_Chatter_Settings__c ecs = Equipment_Chatter_Settings__c.getInstance( UserInfo.getOrganizationId() );
   if(ecs.Id == null)
   {
       ecs.Assignment_Chatter__c = TRUE;
       ecs.Loan_Return_Chatter__c = TRUE;
       ecs.Assignment_Body__c = 'Equipment ~1~ ~2~ was assigned on ~3~';
       ecs.Assignment_Return_Body__c = 'Assigned Equipment ~1~ ~2~ was returned on ~3~';
       ecs.Loan_Body__c = 'Equipment ~1~ ~2~ was loaned on ~3~';
       ecs.Loan_Return_Body__c = 'Loaned Equipment ~1~ ~2~ was returned on ~3~';
       insert ecs;
   }
  • I just tried the above and I am still getting the "DML currently not allowed" on the 'insert ecs;' statement when I try to run the VF page related to this controller. – AngiB Nov 1 '12 at 15:56
  • Ok, sorry - to be fair I only tried it from dev console in my dev org. – Phil Hawthorn Nov 1 '12 at 16:00
  • 1
    Oh hang on, have you seen this blog post: th3silverlining.com/2009/11/23/dml-currently-not-allowed - you're not falling foul of any of those are you? – Phil Hawthorn Nov 1 '12 at 16:02
  • The code above is the ANSWER to my originally posted question in terms of that code makes an Org level custom setting record appear. BUT so is Phil's comment about 'DML Currently Not Allowed'. I was trying to add this code to an 'Init()' mention in my page controller so I also had to add action="{!Init}" on the apex:page component. Prior to this I was calling the Init() method from the controller code itself. – AngiB Nov 1 '12 at 18:02
1

Very hacky but... Can you experiment with treating your custom setting as a normal sObject?

SELECT Id, Name, SetupOwnerId
FROM Equipment_Chatter_Settings__c
WHERE (NOT (Name LIKE '%(User)')) AND (NOT (Name LIKE '%(Profile)'))

No rows returned -> insert new one. Even better would be to be able to filter WHERE SetupOwnerId LIKE '00D%' (doesn't work) or just WHERE SetupOwnerId = :UserInfo.getOrganizationId() (see notes below). You could also retrieve them all (sorted?) and filter by Id manually.

Couple of points to consider:

  1. I have absolutely no idea if any magic happens to values in org-level custom setting when you refresh a (full) sandbox from prod. I've had a peek at my dev. sandbox and while the top level setting was there, the org id stayed with production value.
  2. Name fields used in WHERE don't seem to be affected by user's language (appear always in English).
  3. Check Install Handler interface, might be useful :)
  • I second the Install Handler interace. That's what the install handler is meant for, creating set up criteria like custom settings. – James Loghry Nov 2 '12 at 3:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.