September 29, 2011

JSON parsing in Apex, a developer’s nightmare :( Winter’12 release I badly need you !

Today I stumbled upon a requirement to parse JSON in Apex. I was happy about the fact that I know there is a cool open source library called JSONObject, that will do all the heavy lifting of JSON parsing and another more cooler native JSON parser is lined up in coming winter'12 release.

I was able to quickly setup the web service fixture using all goodness of dependency injection for callouts in apex, as discussed in this post.
 

“JSON response vs JSONObject Parser” the bloody war !

The real pain started when I started parsing JSON response. I met a series of awesome exceptions and errors, leaving me confused about who is wrong JSON or Parser :-?
I firstly got this exception about “Missing Value”

image
After doing some googling, I found this post, where the code snippet indicated that newlines might be an issue with the parser. So I removed both “\r” & “\n” chars from the JSON response, why would machine require a pretty printed JSON :) Then life moved on for a while, until I got this exception

“FATAL_ERROR|superpat.JSONObject.JSONException: Expected a , or }”

I was again thinking, now what who’s wrong here JSON or Parser :-? Again after some fighting with code, I ended up on google searching for the same and luckily found metadady already fixed this one. Many thanks to metadady, for fixing this issue and submitting a patch, I don’t know why this patch is still not applied on JSONObject since Jan 24, 2011.


Again, life moved a bit ahead, until the JSONObject started parsing some Unicode chars like “\u0026”, in the response. Again Metadady was nice enough to mention this issue with his patch, but it seems there is no clean way to handle unicode chars in Apex. So I decided to get rid of them, I really can live without these special creatures in String :(
So, I kicked off all unicode awesomeness in JSON response with something like

“jsonstring.replaceAll('\\\\u.{4}', '')”
Next, life moved really good and my JSON was parsed successfully, I was having tears of joy in my eyes :) But those tears of joy turned into tears of sorrow, when I saw the debug logs
  • it took around 10+ seconds and
  • “154574” script lines for parsing a moderate json string.
Number of script statements: 154574 out of 200000 ******* CLOSE TO LIMIT

It was a strange feeling of loosing everything after you won, words can’t express it.

I was having some hope, that I can get rid of it. But but but, it was all lost when I read this post from legendary Jeff Douglas. It was an unlucky Googling day for me, if this Jeff’s post could have appeared earlier, I could be more happy guy by EOD.

Is Game over ?

Anyway, game is not over yet. I am waiting for winter’12 release and native JSON parser i.e. SYSTEM.JSON to come. Thanks to Salesforce team for finally adding a native JSON parser to the Apex library.

Fixing connection issues with Salesforce Servers in browser & Force.com IDE.

If you are guy who “loves to” or ”has to” work from multiple locations i.e. home, office, client site & coffee shops etc. Then you might have faced the problem connecting to Salesforce and some other web destinations.

For me this problem appears sometimes in browser, but most of the times in Force.com IDE, when a page/class/trigger is saved or refreshed, it either

  • fails to connect to salesforce api serves i.e. na7-api.salesforce.com etc.
  • shows this progress forever “Polling Server 'na7-api.salesforce.com' for response(2)”
  • Response time for refresh/save is difference across spaces, for ex. runs faster in coffee shop but, runs slower in office network.

Fortunately for me the fix was very simple, I just need to execute this command to flush the DNS cache, after this it starts working well with immediate effect. Here is the command that can solve the problem in Mac OS (Snow Leopard+) :

$ dscacheutil –flushcache

I haven’t tried it on other platforms. So to flush DNS cache, for older mac versions, linux and windows, one can try commands mentioned in this link : http://www.tech-faq.com/how-to-flush-dns.html

More thoughts ?

Do you have any easier fix for this, please share !

September 24, 2011

Is Apex System.runAs() not resetting the context for CRUD/FLS changes in profile ?

While writing an apex test case I noticed a strange behavior with System.runAs(). My tests were failing incorrectly, because system.runAs() was somehow not resetting the CRUD/FLS context for different profiles across same or different test method executions.

Here is the complete Test class with all comments and required code. To test it one can deploy this to their DE org directly, it has no dependencies.

@isTest
private class Test_System_RunAs {

/*
 This test class has two test methods, i.e.
  1. testWithSysAdmin() executes a FLS check with SYS Admin profile
  2. testWithChatterFree()  executes a FLS check with Chatter Free profile
  
  PROBLEM :
  Both of these methods doesn't execute correctly. 
  The one that executes first sets the profile context via System.runAs()
  and somehow its not reset internally for the second testMethod execution,
  this makes the testMethod executing later fail (as profile permissions mismatch)
  Though if we comment and execute both these testMethods one at a time, they will behave correct.
  So that means each of these testXXX() methods are correct, somehow context is not reset correctly
  when they execute one after another.
  
  QUESTION :
  
  Am I doing something wrong or is this some bug in System.runAs() context, I feel it takes care
  of sharing rules etc, but doesn't enforces the FLS correctly ?
  
*/

public static testMethod void testWithSysAdmin() {
  System.runAs(createMockUserForProfile('System Administrator')) {
    // This debug indicates different profiles
    System.debug('ProfileId:' +Userinfo.getProfileId());
    System.assertEquals(true, Account.BillingCity.getDescribe().isUpdateable());
  }          
}

public static testMethod void testWithChatterFree() {
  System.runAs(createMockUserForUserLicense('Chatter Free')) {
    // This debug indicates different profiles
    System.debug('ProfileId:' +Userinfo.getProfileId());
    // Chatter Free user has no permission on the Account, so it should be false
    System.assertEquals(false, Account.BillingCity.getDescribe().isUpdateable());
  }          
}

static User createMockUserForUserLicense(String licenseName) {
  Profile p = [SELECT Id FROM profile WHERE UserLicense.Name like :licenseName LIMIT 1];
  return createMockUser(p.id);
}

static User createMockUserForProfile(String profileName) {
  Profile p = [SELECT Id FROM profile WHERE name like :profileName];
  return createMockUser(p.id);
}

static User createMockUser(Id profileId) {
  User u = new User(alias = 'newUser', email='newuser@tgerm.com.test',
  emailencodingkey='UTF-8', lastname='Testing', 
  languagelocalekey='en_US', localesidkey='en_US', profileid = profileId,
  timezonesidkey='America/Los_Angeles', username= System.now().millisecond() + 'newuser@tgerm.com.test');
  insert u;
  return  u; 
}
}

Your views and comments

Looking forward for your views on this. But this seems to be a bug in System.runAs() implementation, what do you say ?

Posted the same as a question on Apex development boards here

Dependency Injection for ease in Testing Apex WebService Callouts !

Apex developers, who are using Http Restful classes know that testing the callouts is not allowed in Apex. People came up with there own smart ways to handle this restriction. For ex.
Scott from ArrowPointe suggested this nice approach : http://sfdc.arrowpointe.com/2009/05/01/testing-http-callouts/
I found some scope of improvement in this approach for a couple of reasons like
  • It can be simplified now after availability of Test.isRunningTest() method, this method came in recent Salesforce release and was not available at the time Scott wrote the post(May 2009).
  • Testing the web service code with variety of XML/JSON responses, status codes, and response headers. One can change it to return different xml responses for each test method but using variety of status codes, response headers etc is not easy job.

 

Fixing the problem with Dependency Injection

Dependency Injection is a cool pattern to reduce coupling. In this scenario the biggest coupling to break was dependency on Apex HTTP class to make the callout. Here is my attempt to do the same using Manual Dependency Injection.
To do the same I defined contract for two key players/dependencies in HTTP callout flow i.e.
  1. IHttpResponse
  2. IHttpCallout
Please Note: Throughout the code samples coming below, I tried adding a lot of inline comments rather blog text to make the explanation easy.

1. IHttpResponse

As name indicates its an interface that defines contract for HTTP response. For least learning curve, all methods of this interface are exactly similar to what Apex HttpResponse class offers.
/**
  Contract for HTTPResponse. To avoid learning and confusions this interface is exposing
  all the methods available in Apex HTTPResponse class(http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_classes_restful_http_httpresponse.htm)
  Test classes can override and implement them as required       
  
*/
public interface IHttpResponse {
  
  String getBody();
  
  Dom.Document getBodyDocument();
  
  String getHeader(String key);
  
  String[] getHeaderKeys();
  
  String getStatus();
  
  Integer getStatusCode();
  
  Xmlstreamreader getXmlStreamReader();
  
  // have to name it toStrings() instead of toString(), as the later
  // is reserved by Apex
  String toStrings();
}

2. IHttpCallout

This interface abstracts out the real webservice action i.e. the calling mechanism. This calling mechanism is the point where Apex test code is limited and it can’t do. In normal Apex we achieve this callout using Http class as follows:
Http http = new Http();
HttpRequest req = new HttpRequest();
req.setEndpoint('http://www.tgerm.com/mycoolws.xml');
req.setMethod('GET');
// This is where Apex tests are restricted
HttpResponse res = http.send(req);
This interface is having a single method with arguments similar to the Apex Http class, only difference is in the return type i.e. IHttpResponse.
/**
  Contract for a simple web service callout using Apex.
  Only a single method is available for abstracting the stuff out for ease of Testing.
  Test classes can provide implmentations of this interface to return custom/fake/mock HTTP responses.
*/
public interface IHttpCallout {
  /**
    Accepts a ready to send requests and makes a callout using that.
  */
  IHttpResponse send(HttpRequest req);
}

 

Implementing contract for both Real World & Test Simulation !

OK, we have figured out dependencies now and defined a clear contract for both too. Now its time to implement the same contract for both the Apex real and test execution.

Real World Implementation.

DefHttpResponse implements IHttpResponse
This implementation is a simple wrapper over existing Apex Httpresponse class.
/**
  Default wrapper implementation over standard Apex HttpResponse class.
  Reference : http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_classes_restful_http_httpresponse.htm
  All contract methods of IHttpResponse are delegated to the wrapped Apex HttpResponse instance. 
*/
public virtual class DefHttpResponse implements IHttpResponse {
  public Httpresponse resp;
  
  public DefHttpResponse(HttpResponse resp) {
    this.resp = resp;
  }
  
  public String getBody() {
    return resp.getBody();
  }
  
  public Dom.Document getBodyDocument() {
    return resp.getBodyDocument();
  }
  
  public String getHeader(String key) {
    return resp.getHeader(key);
  }
  
  public String[] getHeaderKeys() {
    return resp.getHeaderKeys();
  }
  
  public String getStatus() {
    return resp.getStatus();
  }
  
  public Integer getStatusCode() {
    return resp.getStatusCode();
  }
  
  public Xmlstreamreader getXmlStreamReader() {
    return resp.getXmlStreamReader();
  }
  
  public String toStrings() {
    return resp.toString();
  }
}
DefHttpCallout implements IHttpCallout
This implementation is a delegate again to standard Apex Http class for the critical “send(HttpRequest)” operation. Please note DefHttpCallout.send() doesn’t returns HttpResponse, instead its returning IHttpResponse.
/**
  Default implementation meant for use in actual apex code. It runs out of 
  standard Apex Http Class (http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_classes_restful_http_http.htm)
*/
public class DefHttpCallout implements IHttpCallout {
  public IHttpResponse send(HttpRequest req) {
    Http http = new Http();
    return new DefHttpResponse(http.send(req));
  }
}
The whole package of above interfaces/classes is available as GIST on github here : https://gist.github.com/1238904#file_ws.java
Sample callout to Amazon Web Services
AWS class below explains all in full glory. This class restructures the same good AWS callout example available on DeveloperForce WIKI here : http://wiki.developerforce.com/index.php/Apex_Web_Services_and_Callouts
The same is available as GIST here : https://gist.github.com/1238904#file_aws.java
public with sharing class AWS {
/**
  Handle to easily switch between natural HTTP callout and Mock Callouts for test cases.
  Those who love patterns, can use Factory if required to achieve the same. But I find
  it really handy in test cases to change.
  for ex. My test code can just replace the IHttpCallout impl as:
  AWS.CALLOUT = new MockAWSCallout();
  
  Here MockAWSCallout is a fake implementation that will simulate HTTP callout for sake of test cases.
  
*/
public static WS.IHttpCallout CALLOUT = new WS.DefHttpCallout();


public String serviceEndPoint = '<SET IT HERE>';
public String bucket = '<SET IT HERE>';
public String key = '<SET IT HERE>';
/*
 Example AWS callout code taken from this awesome WIKI page :
   http://wiki.developerforce.com/index.php/Apex_Web_Services_and_Callouts
 Please Note: this method is just for illustration purpose, not ready to be used as it is.
*/ 
public void store(String body) {
  
  HttpRequest req = new HttpRequest(); 
  //Set HTTPRequest Method
  req.setMethod('PUT');
  //Set HTTPRequest header properties
  req.setHeader('content-type', 'image/gif');
  req.setHeader('Content-Length','1024');
  req.setHeader('Host','s3.amazonaws.com');
  req.setHeader('Connection','keep-alive');
  req.setEndpoint( this.serviceEndPoint + this.bucket +'/' + this.key);
  //Set the HTTPRequest body  
  req.setBody(body);   
  
   try {
 
    //Execute web service call here    
    // 
    // PLEASE NOTE : here we have used the static variable 
    //          CALLOUT here
    //
    WS.IHttpResponse res = CALLOUT.send(req);  

    //Helpful debug messages
    System.debug('STATUS:'+res.getStatus());
    System.debug('STATUS_CODE:'+res.getStatusCode());
    
    /// Do what else is biz requirement with the response.
    // ...
    //.....
    //
    
  } catch(System.CalloutException e) {
    //Exception handling goes here....
  }        
}

}

Testing Simulation for Amazon Sample above

MockHttpResponseBase  implements IHttpResponse
For starting up with test cases, an intermediate base class is introduced that gives a complete virtual implementation of IHttpResponse. By complete virtual I mean, any operation will throw exception, as its virtual. This class is meant to give a full virtual implementation of IHttpResponse, so that test cases can only override the response methods as required. For ex. in most of the cases we need only HttpRespone.getBody() or HttpResponse.getStatusCode() only.
/**
  Indicator for operation being accessed is virtual as of now.
*/
public class VirtualOperationException extends Exception {}

/**
  Meant to be base/parent class for Apex test case simulations.
  Its a mock implementation of IHttpResponse, it gives a virtual body
  of all contract methods in IHttpResponse, and throws VirtualOperationException
  for every method call. Using this class as parent, subclasses would be easy i.e. just
  override the methods required, instead of implementing the whole IHttpResponse contract.
  For ex. in most of the cases, one will override getStatusCode() and getBody() for testing purposes.
*/
public virtual class MockHttpResponseBase  implements IHttpResponse {
  public virtual String getBody() {
    throw new VirtualOperationException('No implementation available !');
  }
  public Dom.Document getBodyDocument() {
    throw new VirtualOperationException('No implementation available !');
  }
  public virtual String getHeader(String key) {
    throw new VirtualOperationException('No implementation available !');
  }
  public virtual String[] getHeaderKeys() {
    throw new VirtualOperationException('No implementation available !');
  }
  public virtual String getStatus() {
    throw new VirtualOperationException('No implementation available !');
  }
  public virtual Integer getStatusCode() {
    throw new VirtualOperationException('No implementation available !');
  }
  public virtual Xmlstreamreader getXmlStreamReader() {
    throw new VirtualOperationException('No implementation available !');
  }
  public virtual String toStrings() {
    throw new VirtualOperationException('No implementation available !');
  }
}
This class and fixture is common to all apex test cases. So its body is kept together in same Apex class i.e. WS here : https://gist.github.com/1238904#file_ws.java
MockHttpResponse extends WS.MockHttpResponseBase
For the AWS sample, we need to work with three response param i.e. body, status and statuscode. So this class utilizes the MockHttpResponseBase and gives implementation of the required methods.
/** 
  Please note we have extended WS.MockHttpResponseBase
  instead of implementing ws.IHttpResponse, because we want to 
  override three methods only
*/
public class MockHttpResponse extends WS.MockHttpResponseBase {
  public String body;
  public String status;
  public Integer statusCode;
  
  public MockHttpResponse(String body, String status, Integer statusCode) {
    this.body = body;
    this.status = status;
    this.statusCode = statusCode;  
  }
  
  public override String getBody() {
    return body;
  }
  
  public override String getStatus() {
    return status;
  }
  
  public override Integer getStatusCode() {
    return statusCode;
  }      
}

MockHttpCallout implements WS.IHttpCallout
This gives a mock implementation to the callout behavior. Here various test methods can tweak it easily to return the required Mock responses.
/**
  Mock Callout Implementation  
*/
public class MockHttpCallout implements WS.IHttpCallout {
  private MockHttpResponse resp;
  
  public WS.IHttpResponse send(HttpRequest req) {
    return resp;
  }
  
  /**
    This method was not part of original WS.IHttpCallout contract
    as its one of the way test case can pass mock response to it.
  */
  public void setResponse(MockHttpResponse resp) {
    this.resp = resp;
  }
}
Sample testXXX() method using this fixture
/*
  A test call to the store method in AWS class
*/
static testMethod void testStoreCall() {
  MockHttpCallout mockCallout = new MockHttpCallout();
  // Tell AWS Apex class to use Mock Callout instead of this one
  AWS.CALLOUT = mockCallout;
  
  AWS amazon = new AWS();
  // create a mock XML response you want the actual code to parse
  MockHttpResponse mockResp = new MockHttpResponse('<xml..> some xml response body', 'OK', 200);
  // tell callout to return this response when a request comes
  mockCallout.setResponse(mockResp);
  
  amazon.store('My Cool Body to preserve in Amazon S3 :)');
  // Please do some assertions
  // 
  System.assertEquals('Some Good Asserts here', 'No good asserts, writing those will be out of scope for this illustration');
  //
}

 

Did you noticed ?

I didn’t used Test.isRunningTest() anywhere in the code above to know if the code is in Test Context. This is a good api, but Apex gives decent inheritance and polymorphic behavior to achieve the same.

Source Code as GIST

Full source is available as GIST here : https://gist.github.com/1238904
To explore the code, please start in this order
  • WS.cls : WS is short form of WebService, it’s a sort of package class having all the core interfaces and default implementation classes as child classes.
  • AWS.cls : A class having sample callout illustration to Amazon S3. This class uses the WS.cls fixture.
  • Test_AWS.cls : Test cases indicating how the WS.cls fixture can be used for mocking up the callouts.

Feedback & Views

I hope this fixture will help making life simple with Apex Web Service callouts and testing. Looking forward for your views on this.

September 11, 2011

Seesmic CRM for Salesforce (Android Version) reviewed !

Seesmic CRM for Android and Ipad was announced near Dreamforce. The ipad version is coming soon, and Android one is available as beta in Android Market Place, one can download the android app from here.

Playing with Seesmic CRM for Android !

I spent some time with this app, here are some screenshots of what I did in order from left > right and top > bottom.
Please hold your mouse for a while on image for more details about it in tooltips.
Seesmic CRM Android App IconSeesmic CRM Add Account ScreenSalesforce Oauth login screenOauth Give permission to Seesmic to Access resourcesSeesmic takes some time to load after loginSeesmic home screen, post loading and loginSearch works across contacts, leads, accounts & opportunitiesContact detail record Activities open and history on ContactSeesmic shows chatter feed on object detail
Here is my opinion about this app

What I liked about Seemic CRM for Android !

  • Good to have it in free on Android
  • Has a sleek and simple interface
  • Doesn’t asks you for password, uses oauth.
  • Gives across object search in leads, contacts & opps etc.
  • Shows Chatter feed and activity log together with object details as shown in above images.
  • Logs events like phone call & emails as activity. Please refer to above image collection for details

Issues and Challenges for Seesmic CRM

  • Very buggy beta release, don't want to discuss the bugs here. I hope next update will fix most of the issues.
  • Its still not at all close to what Salesforce Mobile is giving already to iPhone, Blackberry and Windows Mobile users.
    Though it comes at some cost, but that is not always the case.
    • “Salesforce Mobile Lite” is free for all editions of Salesforce
    • “Salesforce Mobile” is free for Unlimited Edition customers; available in Professional Edition and Enterprise Edition for $50/user/month.
  • Salesforce Touch i.e. http://touch.salesforce.com seems to be something really huge and generic for all mobile platforms like phones & tables. The features and quality of interface seems mind blowing with Salesforce touch, its really a giant killer for Seemic CRM App. So with Seesmic having native apps for Android/ipad vs single Salesforce touch app being available to handle all mobile platforms is a big gap to fill, it would be almost next to impossible for Seesmic’s native CRM apps to match up “Salesforce Touch”. This video shows how awesome its going to be

 

Feedback

Looking forward for your thoughts on this post.

September 6, 2011

Playing FullScreen in Force.com IDE (Eclipse) for Mac OS X Lion !


One of my favorite feature in Mac OS X Lion is support for Full Screen Apps. I very much wanted the same support in Force.com IDE (Eclipse). As Eclipse indigo was released a bit before Mac-Lion, so it missed that support.


Good news : A small eclipse plugin can easily enable full screen support on Eclipse 3.6+. Here is the link to that plugin in Eclipse Marketplace.

Sad News : Those who are using standalone Force.com IDE, will not be able to get this update. As the force.com IDE version is still based on Eclipse 3.5.2 (Galileo). You guys can try updating the Eclipse base to 3.6 or 3.7 if possible, though the cleanest and easiest move is to move to latest Eclipse(or STS) download and install Force.com IDE as a plugin to that. You will loose nothing, just point your previous Force.com IDE workspace to the new Eclipse installation (do this after installing Force.com IDE plugin for better experience).

Installing the full screen plugin 
Those who are on normal Eclipse 3.6+ IDE or STS(Spring Tool Suite) distribution can install this plguin easily. You just need to add this update site : http://github.bandlem.com/ and install the plugin available there.
Here are detailed steps :

1. Goto menu Help > Install New Software

2. Add a new update site with any good name and location as  http://github.bandlem.com/
3. Hit Next button and complete the rest of the wizard to complete the installation. Post restarting the eclipse as part of plugin installation you will see the standard full screen stuff like this

Standard Full Screen Button


Full Screen Pleasure of Coding !

Feedback 
This plugin is nice, only issue I felt is the standard ESC button behavior. Pressing escape resumes to normal screen mode like other full screen apps, though it disturbs the flow of work sometimes.

Would be looking forward for your views and experiences with this !



September 4, 2011

Apex inheritance – Extending managed package abstract/virtual classes & interfaces !

In my recent project, I came across a requirement to create a base class in a managed package with child extension packages would extend to add their value to it.

Before starting the actual work, I thought of googling about experiences of force.com community members about the same. Interestingly I found one relevant link only i.e. this force.com discussion board question. I became doubtful about this working after reading this post, so thought of giving a quick try, before doing it for our customers. The good news in advance is that “this managed package inheritance works”. The fixture for this POC experiment is explained below.

Fixture for this experiment !

In a top level global class, all 3 types of inheritance forms are created as shown below

global class ManagedPackageInheritance {
   // Virtual Class
    global virtual class VirtualClass {
        global virtual void foo () {
            System.debug('#Foo from Managed Package !');
        }
    }
   
   // Interface
    global interface IInterface {
        void bar ();
    }
    
   // Abstract class
    global abstract class AbstractClass {    
        global abstract void foo() ;
    }
}

Inheriting from Managed package apex classes.

The above test fixture was packaged. This package was uploaded as a managed package with namespace prefix “abhinav” and was installed in some other salesforce DE org.

Here we created following child classes implementing/extending all the parent classes/interfaces in the managed package. Everything seems to be working fine, including calling parent class method using super.methodName(). All code shown below :

                        
// Extend Virtual class in managed package
global class PlayVirtualInheritance extends abhinav.ManagedPackageInheritance.VirtualClass {
   // override the virtual method
   global override void foo() {
    super.foo();
        System.debug('#Foo from Target Org !');
    }
}

// Implement interface in managed package
global class PlayInterfaceInheritance implements abhinav.ManagedPackageInheritance.IInterface {
    global void bar() {
    }
}

// Extend Abstract class in managed package
global class PlayAbstractInheritance extends abhinav.ManagedPackageInheritance.AbstractClass {
    global override void foo() {
        System.debug('#Foo from Target Org !');
    }
}

Please Note !

Inheritance in managed package, works but comes with two very important and strange warning(link to apex doc), shown below :

  • Classes defined with either virtual or abstract cannot also be defined as global in Developer Edition organizations. They can be defined as global in sandbox organizations. Only private and public classes can be defined as either virtual or abstract in Developer Edition organizations. However, a class defined as global can extend virtual or abstract classes in either Developer Edition organizations or sandboxes.
    • Abhinav: Strange, as I was able to create global classes both virtual & abstract from a DE org. The same was packaged as managed released. Seems this restriction is no more applicable. Salesforce team please confirm ?
  • You cannot add a method to an abstract or virtual class after the class has been uploaded in a Managed - Released package version. For more information about managed packages, see Developing Apex in Managed Packages.
    • Abhinav: This is very much true, so please do a lot for brain storming before finalizing design of classes and packaging it as managed released.

Feedback

Looking forward for your views and experiences on this topic !

September 3, 2011

More Apex Testing with SmartFactory !

Creating Mock objects for Apex test cases is a pain, SmartFactory from Matthew Botos is a great API that really simplifies this task. One can create standard and custom object with some sensible defaults for all fields with just one line of code, shown below
// create standard Account object
Account account = (Account)SmartFactory.createSObject('Account');
// Create a custom object
Custom_Object__c customObject = (Custom_Object__c)SmartFactory.createSObject('Custom_Object__c');

My journey with SmartFactory … !

We started using and liking SmartFactory internally on some of our projects. I was getting continuous feedback from my team about goods and gaps of this API. This attracted me towards this API, I became very much interested in this project and started contributing to fix those gaps for our self and community.
The first item fixed was “Field Describe limit reached with SmartFactory.”. Here caching support was added to save describe calls, on creating multiple instances of same object.
Moving next the items on list were following
I am glad to share with you all that, finally all these items are fixed and pull request is raised for merge into the main repos.
Most important of the above mentioned issues/items was Issue#6. Now apart from the ways described in code snippets above, one can also create mock Sobjects initialized with default values, as shown below
Map<String, Object> accValues = 
                   new Map<String, Object> { 'AnnualRevenue' => 20000.00,
                                        'Description' => 'My Account Description', 
                                        'Phone' => '123-234-2233' };
Account acc = (Account)SmartFactory.createSObject('Account', accValues); 
In the end, I would like to say that Matthew was really cooperative and open in adapting/discussing the changes, this is really appreciable to keep up the open source contribution spirit high !

References