Showing posts with label Fact. Show all posts
Showing posts with label Fact. Show all posts

19 December 2014

Your runAllTests request is using too many DB resources

A couple of months ago, I have encounter a very strange error when deploying components in Production where Salesforce is throwing an error message saying "Your runAllTests request is using too many DB resources". Digging deeper on the error message, I came upon this knowledge article that mentions of a limit 350,000 of DML rows on all test classes. What's fascinating is that the limit is not in the documentation. From what I understood, the limit is associated with the oracle database rollback used in the backend.

This is really a big issue specially if there are a lot of applications on your instance and you plan to add one. Also, regardless whether you optimise your code to limit data created on test classes, it would be a matter of time before you reach the limit. If your environment is not yet enabled for FAST deploy as discuss in my previous blog post, you will not be able to do regular deployment.

As of right now there is no fool-proof solution for this. However, there are a couple of things I would recommend you check in case you are getting the error message.


  1. Check if your environment is loading bulk data from static resource. I'm not a big fan of the Salesforce documentation because some of the information are vague (at least for me) and having to clarify to support how salesforce computes, let's say a limit is so slow and takes weeks to confirm based on my experience. Basically loading data from static resource using Test.loadData are computed as part of this overall DML row limit.
  2. Are you using Custom Settings as holder of your environment variables? One of the things I learned from previous Dreamforce sessions is that you can use custom settings as holder of environment variables so that you don't need to maintain static values on a class since its hard to redeploy components in Production environment and using custom labels to do this may not be the best solution (and using custom labels for storing such values are not good since it should be used for multi-lingual content). This is a similar pattern used for Java and even .NET that is handy. However you may want to review this pattern because it will be a liability at the end because of the limit.
  3. Consider Multi-Org Setup. I'll be honest, as of right now I haven't implemented this on a client but having said that, having multiple instances definitely means you have separate limits for each of your unrelated applications. If for somehow some of your applications are connected then maybe you can take a look at Salesforce to Salesforce feature. 
  4. Use SeeAllData=true. I don't really recommend this since it slows down processing of test classes and it is not a best practice but it can be a temporary workaround specially if you are loading a lot of test records from your test classes regardless if its coming for custom settings or coded in the class.
  5. Check with if Managed Package will help. Now this is something I'm not sure will work and you may want to check with Salesforce but from what I understand, managed package has its own limits with unmanaged package. (I would appreciate if someone can confirm if it would work or not.)

I hope you find the list above helpful. Let me know if you encounter the same issue and if you have any thoughts on how to fix the issue. In addition, please vote my idea on removing DML row limit for loading data using static resource.

11 August 2012

You have reached the maximum number of 10 object references on Child


The error "You have reached the maximum number of 10 object references in <Object Name>" refers to the maximum number of unique relationship name you can refer to using formula fields meaning the '__r' on the formula.

For example I created 11 lookup fields on the same object. I named it Parent__c, Parent_2__c ... Parent_11__c and want to reference a field on that object for all lookup fields.

This won't be possible as I can only create up to 10 relationship formula fields for these lookup. Trying to create a formula for Parent_11__r will give an error similar to the below: 



So what's the solution?

If you want to populate the hypothetical field Parent_External_ID_11__c (not displayed above) you need to:
  1. Ask salesforce to increase it.  You can request to increase it up to 15 as of summer 12. See notes from product manager and consequence. http://success.salesforce.com/ideaView?id=08730000000gKsbAAE
  2. Remove unused formula fields if possible.
  3. Convert the field to its appropriate field type (in this case I'm just referencing a text so I need to change the field to Text) and then create an Apex Trigger to populate field on the before or after update event as needed.
Please note that you cannot use workflow rule and field update formula if you are referencing the same relationship because its also counted against the limit.

11 May 2011

Parameterized Custom Label

I still remember when custom labels where new and I have a requirement in which I wanted to create a VF email template in which non technical people wouldn't need to edit VF pages to update the email content.

Custom labels first came to mind. However, I thought that multiple custom labels will do the work in which I will concatenate each of them included values I wanted to insert in between words. Then I found out that this is not the best approach as SFDC impose limits to the number of custom labels per org.

Then I found what I'm looking for. It turns out that I can add parameter to custom labels and use the <apex:param> tag to update the value of the parameter in custom labels. To make the story short I created a sample for this entry.

First we create a custom label similar to this:


Take note of the values denoted by the curly braces and the number inside of it. This values empowers the custom labels to accept parameters. Also, you noticed that it start with the number 0. This is the default, as the first parameter you will add on your VF pages <apex:outputText> or any tags that will be displayed on that merge field (I'm calling it merge field).

Next we create a simple VF email template.


For the purpose of this example, I just created an email template that uses the recipientType and relatedToType to Contact. Basically I used the <apex:outputText> tag and add the custom label as its value. Then inside the <apex:outputText> tag, I added some <apex:param> tags with values. Note that the first param tag will be the value for the {0} merge field.

When you save the VF email template you will instantly see that the parameters was substituted by the values you added on the tags.

That's it. You have used parameters for your custom labels!

14 April 2011

How to Process Record using List Button and Visualforce

Long ago, if we want to process records from a record list we create a list button that executes a javascript. The javascript would then use the Salesforce AJAX Toolkit and use a merge field called GETRECORDIDS. However this proved to be slow since its running in client side.

The best way to workaround this is to use Visualforce and the StandardSetController.

Let's say for example that we wan't to update a set of contact via a button on the contact list. First we need to create a Visualforce page that uses its standard controller and creating an extension class.

So for example, we create a Visualforce page with the name ContactListUpdate similar to this:

<apex:page standardController="Contact" 
  extensions="ContactListUpdateExtension" 
  recordSetVar="c" action="{!updateContacts}">
    <apex:form >
        <apex:pageMessages />
        <apex:pageBlock >
            <apex:pageBlockButtons >
                <apex:commandButton value="Back" 
                                 action="{!returnPage}"/>
            </apex:pageBlockButtons>
            <apex:pageBlockSection columns="1">
                The selected contacts were updated. 
                                Please click the back button to return 
                                to the previous page.
            </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form>
</apex:page>

Take note of the 'RecordSetVar' attributes. Since we will be using the StandardSetController on our controller extension, then it is required.

Then we create our controller extension:

public class ContactListUpdateExtension {
  static string SECONDARY_CONTACT = 'Secondary';
  Contact[] arryContact;
  PageReference pgReturnPage;
  
  // Constructor
  public ContactListUpdateExtension(ApexPages.StandardSetController 
                                   cntlr){
    arryContact = cntlr.getSelected();
    
    // Build the return page 
    String returnUrl = ApexPages.currentPage().
      getParameters().get('retUrl');
    pgReturnPage = new PageReference(returnUrl);
        pgReturnPage.setRedirect(true);
  } 
  
  public void updateContacts(){
    List<Contact> lstContactUpdate = new List<Contact>();
    
    for(Contact c: arryContact){
      c.Level__c = SECONDARY_CONTACT;
      lstContactUpdate.add(c);
    }
    
    Database.Saveresult[] arryResult = 
       Database.update(lstContactUpdate);
    for(Database.SaveResult sResult : arryResult){
      if(!sResult.isSuccess()){
        Database.Error errMsg = sResult.getErrors()[0];
        ApexPages.addMessage(
           new ApexPages.Message(
              ApexPages.Severity.ERROR,
              errMsg.getMessage()));
      }
    }
  }
  
  public PageReference returnPage(){
    return pgReturnPage;
  }
}

In this example I am updating the contacts custom field Level__c to a value 'Secondary'.

As you can see, the constructor parameter accepts the ApexPages.StandardSetController type. This will help us access the selected records by accessing the getSelected() property.

We can now create a List Button whose content source = 'Visualforce page' and refer the previously created Visualforce page. You must also note that we want to have user the ability to select multiple records so we need to tick the 'Display Checkboxes (for Multi-Record Selection)' checkbox.




That's it. You are now processing multiple records on a List Button using Visualforce. Note that you need to add this button to its appropriate page layouts.

31 March 2011

Adding a checkbox on a PageBlockTable

One of the common use cases I experienced developing customization in Salesforce is the ability for end user to selected multiple records from a list and process them. In Salesforce you can do this via client-side scripting using JavaScript. However, it is slow and you don't really have full control of the selected records specially when your doing multi-paging list.

The best approach I believed on doing this is to create an Apex wrapper class. The wrapper class is a class that will represent data for your table with additional properties. An example of using wrapper class is when you want to display an accounts and then select them using a checkboxes. Let's see how we approach that below.

We first create a wrapper class similar to this:

public class AccountWrapperCls {
     public Boolean isSelected {get;set;}
     public Account cAccount {get;set;}

     public AccountWrapperCls(Account cAccount){
          this.cAccount = cAccount;
     }
}

As you can see above, the class contains an account and a boolean property. The isSelected property will be referenced by our Visualforce page and will be rendered as a checkbox. To use this wrapper class we need to create a Visualforce controller for our page that will use the class above.

public class MyAccountListCntrlr {
     // PROPERTIES
     public List<AccountWrapperCls> acctList {get;set;}
     public Set<String> selAccountNames {get;set;}
     public Boolean hasSelAcct {get;set;}

     // CONSTRUCTOR
     public MyAccountListCntrlr(){
          acctList = new List<AccountWrapperCls>();
          selAccountNames = new Set<String>();

          for(Account a : [SELECT AccountNumber, Name 
          FROM Account WHERE AccountNumber != NULL 
          LIMIT 5]){
               acctList.add(new AccountWrapperCls(a));
          }
     }

     // METHODS
     public void displaySelectedAccountNumbers(){
          selAccountNames.clear();
          hasSelAcct = false;
          for(AccountWrapperCls cWrapper : acctList){
               if(cWrapper.isSelected){
                    hasSelAcct = true;
                    selAccountNames.add(cWrapper.cAccount.
                             AccountNumber);
               }
          }
     }
}

As you can see above, we created a list of type AccountWrapperCls which represents the account record and the additional isSelected property. Please note that we add a method called displaySelectedAccountNumbers() which gets all the account records whose isSelected value is set to TRUE. It also adds those selected account's account number to a set variable we defined in our class which we will use to display account numbers on the page.

Below is our Visualforce page:

<apex:page controller="MyAccountListCntrlr" tabStyle="Account">
   <apex:form >
      <apex:pageBlock title="Account List">
         <apex:pageBlockButtons >
            <apex:commandButton 
               value="Show Selected Accounts" 
               action="{!displaySelectedAccountNumbers}"/>
         </apex:pageBlockButtons>

         <!-- ACCOUNT LIST -->
         <apex:pageBlockTable 
           value="{!acctList}" 
           var="acctWrapper">
            <apex:column >
               <apex:inputCheckbox 
                 value="{!acctWrapper.isSelected}"/>
            </apex:column> 
            <apex:column 
              value="{!acctWrapper.cAccount.AccountNumber}"/>
            <apex:column 
              value="{!acctWrapper.cAccount.Name}"/>
         </apex:pageBlockTable>

         <!-- SELECTED ACCOUNT INFO -->
         <apex:pageBlockSection >
            <apex:outputPanel 
              layout="block" 
              rendered="{!hasSelAcct}">
               <apex:outputText 
                 value="Below are the selected account:"/>
               <br/>
               <apex:outputText 
                 value="{!selAccountNames}"/>
             </apex:outputPanel>
             <apex:outputPanel layout="block" 
               rendered="{!NOT(hasSelAcct)}">
                <br/>
                <apex:outputText value="No account selected."/>
             </apex:outputPanel>
         </apex:pageBlockSection>
      </apex:pageBlock>
   </apex:form>
</apex:page>

Note that we referenced our list variable while using the properties of our wrapper class in the controller .