Sunday, January 18, 2015

Curious Case of Disappearing ID

Problem

Last week, I was deploying some changes to the recently deployed Apex classes into the production, but somehow it was failing on previously migrated test classes that were not related to the changes being deployed. To confirm that it had something to do with production environment, rather than the new code, I ran those pre-existing test classes in the production environment, and they were indeed failing even without the changes (I also had them run in Sandbox and confirm that they passed).  My initial suspicion was that someone had added something like a validation rule on the sObjects for which I was generating test data.  Although it was related to the test records being generated, the problem, it turned out, was not related to the validation rule, but something rather more strange.

The test classes had a structure similar to the following where I had a static method to generate test data for all the test methods and a test method that queries for the test data.
@isTest private class TestCustomController {   static void createBackground() {     List<Account> testAccts = new List<Account> {       new Account(Name = 'Test Account 1'),       new Account(Name = 'Test Account 2')};     Database.insert(testAccts);
    List<Account_Child__c> children = new List<Account_Child__c> {       new Account_Child__c(Name = 'Child 1', Account__c = testAccts[0].id)};    Database.insert(children);   }
  static testMethod void manipulateCustomController() {     TestCustomController.createBackground();
    Account queriedAcct = [SELECT Id FROM Account WHERE Name = 'Test Account 1'];
    // Initialize custom controller, pass on the account ID,     //and call method to query for the children of the accounts.   } }
To debug the problem in the production, I had put breakpoints in the createBackground() method after the insertion of the account and in the manipulateCustomController() method after query for the account through Developer Console and ran this test class.  What I found out was that the ID of the Test Account 1 in the createBackground() didn't match the ID in the manipulateCustomController()!

Workaround

I tried moving the code in the createBackground() method into the manipulateCustomController() method, and that did resulted in the ID being consistent through out the run of that test method.  However, this did not completely solve the test failure as I had another weird issue where the symbol table not showing some properties of an in-memory instance of a sObject, while it showed in the heap.

Takeaway

This does demonstrate that there are major differences in the internal implementation of the Test and "Production" environments of the Salesforce, mainly that the Test environment is somewhat unstable and has weird kink in it.  Also, it does demonstrate how valuable breakpoints can be when debugging problem in the Production org. 

Thursday, January 1, 2015

Incrementing Instance Variable of Virtual Class

Problem

I had following piece of code that increments the instance variable in the parent class within the for-loop of the child class:

public virtual class ParentClass {
  public Integer mapIndex{get; set;}
}
public class ClassWithError extends ParentClass {
  


  public ClassWithError {
    Integer mapSize;
    ...
    for (mapIndex = 0; mapIndex < mapSize; mapIndex++) {
      ...
    }
    ... 
  }
  ...

}
which resulted in following error:
Unknown error: virtual class data member of the parent in for-loop

Solution

The fix is to simply create a temporary variable to do the increment and assign the value of the temporary variable to the instance variable inside the for-loop:

public virtual class ParentClass {
  public Integer mapIndex{get; set;}
}
public class ClassWithError extends ParentClass {
  


  public ClassWithError {
    Integer mapSize;
    ...
    mapIndex = 0;
    for (Integer tempIndex = 0; tempIndex < mapSize; tempIndex ++) {
      mapIndex = tempIndex;
      ...
    }
    ... 
  }
  ...

}

Do Not Expect - Trouble with HTTP


This is a bit of old issue, but I making this post as it does drive home an important lesson regarding Salesforce.com custom code development.  For one of our customer, there was this legacy code that used HTTP Callouts, which has been working for several years.  However, around the time of Winter '14 Release, the users started reporting that that piece of code was not working.

After digging through it, I was able to narrow it down the problem to following error on response from the callout to the external web service - a standard non-descriptive error message that appears for pretty much all error with HTTP callout:
Read Timeout Error
Unexpected End of Element...

Because the way Apex parses the response,  I couldn't find out much more from the debug log.  As a next step, I tried to find out if the issue was related to how Apex handles the Callout or if it was something wrong with the web service itself by duplicating the request that the Apex code is suppose to generate within SoapUI.  However, from SoapUI, we were getting the response that we expect to get, leading us to go back to the Salesforce side of things.

This time around, what I did to find the issue in the Callout was to strip down the Callout message to bare bones to see if it would work and then adding the elements back to the message one at a time.  The bare bone message did indeed work from Salesforce, and it turned out that problem was caused by following header:
Expect: 100-Continue

The fix for this problem was simply removing that header.  I don't know for sure if this issue was introduced with Winter '14 Release or through the changes to the external web service (btw, this limitation is now documented here).  However, this does provide a reminder on the dangers of using custom code in terms of its fragility when it comes to upgrade either to Salesforce or external service it interfaces.