2

I wrote few days ago regarding strange behavior of describe method on quote that return unexpected fields. Now finally I was able to reproduce the issue in "clean" environment. Meaning, I wrote the code from scratch to eliminate the option it related to old code/trigger/workflow/etc.

My expected behavior is that when using getDescribe().fields.getMap(), it will behave according to the API version of the class. Means, if field was added in API 30, and my class is in API 29, the describe shouldn't return this field.

This is not always happen, as can be seen below.

Created 2 separated classes with similar code only different API version.

1.DescribeQuoteAPI18 API 18

public class DescribeQuoteAPI18{


    public static void loadMap(){

        Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();

        Schema.SObjectType QuoteSchema = schemaMap.get('Quote');
        Map<String, Schema.SObjectField> QuotefieldsMap = QuoteSchema.getDescribe().fields.getMap();


        system.debug('#### From DescribeQuoteAPI18:');

        system.debug('#### Total Quote fields: ' + quoteFieldsMap.size());

        system.debug('#### Contain billing address field? : ' + quoteFieldsMap.containsKey('billingaddress'));
    }

}

2.DescribeQuoteAPI39 - API 39

public class DescribeQuoteAPI39{

    public static void loadMap(){

        Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();

        Schema.SObjectType QuoteSchema = schemaMap.get('Quote');
        Map<String, Schema.SObjectField> QuotefieldsMap = QuoteSchema.getDescribe().fields.getMap();


        system.debug('#### From DescribeQuoteAPI39:');

        system.debug('#### Total Quote fields: ' + quoteFieldsMap.size());

        system.debug('#### Contain billing address field? : ' + quoteFieldsMap.containsKey('billingaddress'));
    }
}

Now running some test from console

1.only the class with API 18

DescribeQuoteAPI18.loadMap();

Gettig below output:

01:04:30:039 USER_DEBUG [13]|DEBUG|#### From DescribeQuoteAPI18:
01:04:30:039 USER_DEBUG [15]|DEBUG|#### Total Quote fields: 50
01:04:30:039 USER_DEBUG [17]|DEBUG|#### Contain billing address field? : false

2.Only the class with API 39

DescribeQuoteAPI39.loadMap();

Gettig below output:

01:06:03:051 USER_DEBUG [13]|DEBUG|#### From DescribeQuoteAPI39:
01:06:03:051 USER_DEBUG [15]|DEBUG|#### Total Quote fields: 70
01:06:03:051 USER_DEBUG [17]|DEBUG|#### Contain billing address field? : true

3.Running both, but first API 18 class:

DescribeQuoteAPI18.loadMap();
DescribeQuoteAPI39.loadMap();

output:

01:07:07:028 USER_DEBUG [13]|DEBUG|#### From DescribeQuoteAPI18:
01:07:07:029 USER_DEBUG [15]|DEBUG|#### Total Quote fields: 50
01:07:07:029 USER_DEBUG [17]|DEBUG|#### Contain billing address field? : false
01:07:07:040 USER_DEBUG [13]|DEBUG|#### From DescribeQuoteAPI39:
01:07:07:040 USER_DEBUG [15]|DEBUG|#### Total Quote fields: 64
01:07:07:040 USER_DEBUG [17]|DEBUG|#### Contain billing address field? : false

4.Running both, but first API 39 class:

DescribeQuoteAPI39.loadMap();
DescribeQuoteAPI18.loadMap();

ouput:

01:08:24:030 USER_DEBUG [13]|DEBUG|#### From DescribeQuoteAPI39:
01:08:24:030 USER_DEBUG [15]|DEBUG|#### Total Quote fields: 70
01:08:24:030 USER_DEBUG [17]|DEBUG|#### Contain billing address field? : true
01:08:24:037 USER_DEBUG [13]|DEBUG|#### From DescribeQuoteAPI18:
01:08:24:037 USER_DEBUG [15]|DEBUG|#### Total Quote fields: 54
01:08:24:037 USER_DEBUG [17]|DEBUG|#### Contain billing address field? : true

It seems that mainly there is some issue with the "Address_*" fields on quote that were added in API 30, or it's general issue in the describe- perhaps SF use some static reference to this, which being initialized according to the API of the first call. It doesn't seems like expected behavior. Seems more like bug, but I didn't find the correct documentation that can confirm it, so I hope maybe here someone can share if he had similar issue or familiar with the subject.

3

This is a Known Issue. It happens with queries and describes. The cause is that the first class that gets executed determines the API level for the entire transaction. It's currently under review, which means there's hope that it may be fixed in the future. In the meantime, the best advice I can give is to avoid version skew. Keep all of your code at the same API version, and you'll avoid nifty bugs like this. If you can't (say, because you need specific behavior that is only in some versions), then you'll have to write unit tests in all the possible API versions that your code might run in to make sure there's no unintended side effects. Note that most "versioned" things happen as you expect, but there appears to only be one specific metadata version active per transaction.

  • Thanks.Indeed I updated the APi version of trigger that was failing. It will be good to keep all your code in the same API version, but for system that is already 7 years old, and was maintain during years by so many developers, it's might be too complex task – Liron C May 6 '17 at 5:19
  • @LironC Yeah, it's one of those deals: the longer you wait, the more technical debt you acquire. You need to fix it sooner or later. – sfdcfox May 6 '17 at 6:12

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.