This is driving me slightly crazy. I have a hierarchy type custom setting which has a currency field.

Inside a trigger I do the following:

Global_Settings__c gs = Global_Settings__c.getOrgDefaults();

if(gs.Id == null)
    gs.Minimum_Amount__c = 0;
    insert gs;

Double minimum = (Double) Global_Settings__c.getOrgDefaults().Minimum_Amount__c;

Pretty straight forward and works exactly as it should. Where it breaks down is when the trigger is fired from a test method. For some reason the last line is causing an internal server error, but I can't see any reason why it should do so (this is the same whether I insert a custom setting record in the test method body or not).

Major Update - New Question Below

So I took the red pill, carried on down the rabbit hole, and it turns out it's pretty deep. What I've managed to establish through the debug logs is that there's a problem comparing the value of the currency field in the settings with another.

Changing the cast from a double to a decimal in the original code doens't cause a problem, however, comparing that decimal to anything else does. Using this code to setup some values:

    Global_Settings__c gs = Global_Settings__c.getOrgDefaults();

    if(gs == null)
        gs = new Global_Settings__c();
        gs.SetupOwnerId = UserInfo.GetOrganizationId();

    gs.Minimum_Amount__c = 200.0;
    upsert gs;

    Decimal minimum = Global_Settings__c.GetOrgDefaults().Minimum_Amount__c;
    Opportunity op = new Opportunity(Amount = 100);
    Decimal a = Decimal.valueOf('' + minimum);

I then tested various options using these debug statements:

    System.Debug(op.Amount > a);       // All good, outputs "false" as expected
    System.Debug(op.Amount > minimum); // Blows up
    System.Debug('POW!');              // Never run

Even creating a new Decimal variable and assigning minimum to it doesn't work, though perhaps that's assigning a reference (I don't believe it is but this behaviour would indicated otherwise). So I can use the conversion to a String and back again for now... but the question is why is this causing an issue?

  • Support is realistically the best option. If you're feeling adventurous you can ask for the GACK details and if they're willing to share them it might give you a pointer in the right direction for a workaround. Jul 31 '13 at 5:24
  • 1
    Hm internal server error for this probably means raise a case :( Silly idea that probably won't work, but have you tried not casting to a Double, and/or changing the last line to simply refer to gs.Minimum_Amount__c?
    – jkraybill
    Jul 31 '13 at 5:25
  • Think it's going to have to be support. It does seem to be the that's the issue (see edit).
    – Matt Lacey
    Jul 31 '13 at 5:28
  • 2
    Looks like Summer '13 has some extra kinks that need working out. This seems to be a clear bug since primitives are always passed by value and you've eliminated any null possibilities with (effectively) "system.assert(false == (op.Amount > Decimal.valueOf('' + minimum)));"
    – Adam
    Jul 31 '13 at 16:46
  • 1
    If the code only fails in a test method I'd be suspect of the code that sets and updates the Minimum_Amount__c. Could you try with @SeeAllData=true and an existing valid currency value (I.e. don't set the test value in code). At a guess I suspect it isn't being stored as a valid decimal. Also, what are the length and decimal places on your currency? You aren't defining a value out of range by chance? Sep 17 '13 at 2:41

In version 21.0 of the API or later, getOrgDefaults() no longer returns a null. In other words, it always returns something, even an empty instantiated settings object in memory. Also, without seeAllData=true in your test you can't see the settings from your instance. In other words, your test appears to be returning an empty settings object and it's possible that your gack is in trying to cast a null Minimum_Amount__c field value.

  • Good suggestion, but the issue is occurring despite my test method inserting a populated settings object before the standard code blows up.
    – Matt Lacey
    Sep 17 '13 at 23:30
  • I'd be interested in seeing what you get by putting a debug right above Decimal minimum = ... to debug Global_Settings__c.GetOrgDefaults()
    – greenstork
    Sep 17 '13 at 23:35
  • You are upserting settings in this case without a SetupOwnerId, if you're on a recent API version since if(gs == null) will be false
    – greenstork
    Sep 17 '13 at 23:37
  • I've run the code without the if statement, forcing a value and setting SetupOwnerId to the org ID, and it still explodes. A debug line above the line that explodes prints out the value correctly (17:06:13.900 (900437000)|USER_DEBUG|[29]|DEBUG|Minimum Amount: 200.0)
    – Matt Lacey
    Sep 18 '13 at 0:08

Stupid simple answer, for desperate situations :

  • in your first question, have you tried setting gs.Minimum_Amount__c to 0.0 instead of 0 ?
  • in your second question, have you tried setting the opportunity ammount to 100.0 instead of 100 ?

It it works, dont't ask me why. It if doesn't ... well, I told you it was a stupid answer !

  • Yeah I did give that a go and no luck :( Even tried assigning to variables first and then to the record... pretty sure it's just some weird apex bug!
    – Matt Lacey
    Oct 8 '13 at 22:16

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.