Wednesday, September 30, 2015

The Trace Flag and Debug Level in Salesforce Force.com

This feature wasn't in  before until I noticed it in Sep 2015, round about the Dreamforce. And I somewhat figured it out myself navigating here and there in the Debug Log screen.

So when you go to Setup - Monitoring - Debug Log, we only used to see the "DEBUG LOG" section.

Now we see two sections, the "USER TRACE FLAGS" section and we have the legacy "DEBUG LOG" section right below it.

To debug your Apex code, click on the 'NEW' button in the USER TRACE FLAGS section.

Now this new feature is powerful. The Trace Entity dropdown will allow you to select User, Apex Class, Apex Trigger, which means you can debug your code in a more granular fashion by targeting what you want user/component to debug.

Now say you are debugging a functionality in your Salesforce org for a specific user, select "USER" in the dropdown and specify that user's name.

The start date & end date cannot be more than 24 hours apart. Salesforce still wants to track on how much we can debug at a time. In short, there is still a limit on how much we can debug.

The Debug Level is something new you will see here. In the beginning, you wont have any Debug Level of your own. You will have to create your own customized Debug Levels here. So for that, click the Search button on the Debug Level field and this will open a popup for you.

Because you do not have any debug level to start with, you really cant search and go. So click on 'New'.

Here you can define your own name for your choice of Debug Level.

Next, you can select your debug choice from each of the following dropdowns available: Database, Workflow, Validation, Callout, Apex Code, Apex Profiling, Visualforce, System.

Thats it, Save your Debug Level. Go back to the Trace Flags screen and save your settings.

Once done, you can start debugging the code for the user you specified.

Go get better at freaking debugging.


Friday, August 14, 2015

Tuesday, March 31, 2015

How to drink a beer and sleep well while your Apex Jobs are running?

Catching Job Errors and Re-firing them using Apex Scheduler


Pain, pain, pain, oh sometimes it pains in the ass when no matter what you do, no matter how much you brain it out and architect the delicate pillars to build a huge Apex batchable job that processes tons and tons of records, there are many times your batch job might fail. And that failure could throw you out of your job if your batch job fails to execute an ultra-important business calculation that the business folks were relying on. The damn bloody error could be because of a CPU timeout, a concurrency lock error, or a Salesforce Internal Server Error due to a SOQL query that is taking more time to execute than allowed by the god damn governor limits. And you cant be bloody monitoring the job waking up in the middle of the night, to re-fire it manually when you realize it didn't fire the automated way. Sometimes it might even happen that the error handler in your code's Exception block might not fire because of an Internal Server Error. And you were expecting like an idiot an email to your inbox that would tell you what's the status of the job - Completed or Aborted? 

So what can you do to handle such crazy scenarios?

Well the following approach is a bit of a work-around, until you manage to build a Cadillac out of your code, simply check for errors and re-fire your batch job if it didn't run successfully in the last fire.

Now here comes to rescue the super duper AsyncApexJob sObject. Simply query it, ask it if your darling job fired. To start with, I must say I love this object for many reasons that I can keep on going on.

Enough of shit stories, here is the approach:
* Query the AsyncApexJob object to find out the status of the last fired instance of your batch class
* If the job didn't run happily, just refire your job.

Now say the name of your batchable job is MyDearBatchable. And you or some external source like an ETL fired MyDearBatchable to run. But then due to some stupid bloody reason, MyDearBatchable didn't run successfully.

So what you do is create a Schedulable job like the one below:

global class MyDearSchedulable implements Schedulable{
    global void execute(SchedulableContext ctx) {
        // Fetch status of the MyDearBatchable job that ran last
        List<AsyncApexJob> listStatusOfBatch = [SELECT Id, MethodName, JobItemsProcessed, ApexClassId, ApexClass.Name, CompletedDate, NumberOfErrors, Status, ExtendedStatus, TotalJobItems FROM AsyncApexJob where ApexClass.Name='MyDearBatchable' order by CompletedDate Desc Limit 1 ];
        
       Boolean refire1 = false; // status flag for refiring IntradayEmailBatchable
        for(AsyncApexJob j1:listStatusOfBatch){
            if(j1.Status=='Aborted'){
              refire1 = true; 
            }
         }
        
        // Refire MyDearBatchable 
        if((refire1==true){
            Database.executeBatch(new MyDearBatchable(null), 200);
        }
    }

}

Now you can schedule this class to run by navigating to Setup -> Apex Classes and then click on "Schedule Apex Jobs", or alternatively, schedule it to run using the Developer Console using the following command:

MyDearSchedulable m = new MyDearSchedulable(); 
string sch = '0 20 10,14,16 * 1,2,3,4,5,6,7,8,9,10,11,12 ? 2015'; // You can set your own CronExpression here to set the time you want it to fire in Queue 
system.schedule('MyDearSchedulable', sch, m);

And thats it. You can sleep happily ever after. You just need to know & guess when to schedule this job.

Have a beer & sleep well.

Cheers!
Vishal Khanna



Tuesday, December 2, 2014

No Clean Data Column Found - weird error in Salesforce

I work in an Unlimited version Org where the limit for the number of Contact custom fields is 800. And I ran into it. We were in a process of deleting around 300 and we deleted so. After thinking that we are now back to 500 fields and we can create 300 more, we ran into the following error:

"No Clean Data Columns Found"

This is a weird kind of error. After diagnosing and breaking and cracking and thrashing my neurons into it, I realized there are three stages of deletion.

Soft Delete (You delete it and it goes in the Recycle Bin)

Hard Delete (You go to the Recycle Bin and click on Erase). Now here is the big pain. There is currently no interface in the Salesforce recycle bin that allows a mass Erase of the deleted fields. So I went about erasing each field one by one.

The third delete is called a Physical Delete. For this, you got to call the Salesforce support team as they do it for you and you cant do it yourself, unless you wait 45 days when it automatically gets deleted, and I'm sure no one can afford waiting that long.

Here is a reference to the stages of deletions: https://help.salesforce.com/apex/HTViewSolution?urlname=How-to-retrieve-my-records-and-data-that-has-been-lost-or-deleted-1327108681812&language=en_US

So if you ever come across the error message "No Clean Data Columns Found", the only thing you can currently do is to get in touch with Salesforce support and ask them to Physically Delete the Erased fields.

Be sure to mention your Org Id otherwise they might physically delete your darling fields from a different sandbox.

There is another mention about this error here : https://help.salesforce.com/apex/HTViewSolution?id=000126971&language=en_US  which doesnt really talk about the physical deletion of fields.

Once Salesforce folks physically deletes these field, you should get rid of this error in most of the cases.

Cheers!

Monday, March 7, 2011

Passing values between pages in Visualforce

I read a lot of information over the web scattered here and there. So I decided to blog about this. Often developers try to figure out what are the different ways through which values can be passed between pages in Visualforce. Well, there might be a number of them, but I would like to talk about the two most common ways to transfer data between the Visualforce web pages.


Method 1. Passing variable value between two pages that implement the same controllers and extensions.
Method 2. Passing values using a Querystring.


Method 1


In order to use the first method above, we need to ensure that the two pages in context need to have the same controller. This might be a Standard controller or a Custom controller.


Say we have to pages Page1 and Page2. Let the Visualforce syntax be as below:


Code for Page1
<apex:page controller="customcontroller1">
   <apex:inputtext id="inpEmployeeName" value="{!EmployeeName}"/><br/>
   <apex:CommandButton value="Next" action="{!next}" id="cmdNext" />
</apex:page>


Code for Page2

<apex:page controller="customcontroller1">
   .The employee name is {!EmployeeName}
</apex:page>

Code for customcontroller1
public with sharing customcontroller1
{
  public string EmployeeName {get;set;} 
  
  // Function for navigating to next page
  public PageReference next()
  {
     PageReference nextpage = new PageReference('/apex/Page2');
     return nextpage;
  }
}

Now there are a few points worthy to note out here. You need to be careful of the method nextpage.setRedirect(true) , a method used to redirect from one page to another. Use it only when you use querystrings in the URL. If you use this method in the method above, it will wipe out all the data stored in variables in page1 being transferred to page2, as page2 in such a scenario will loose all the variable data of the controller, when this page2 loads.


Method 2

This method involves transferring variable data from one page to another, using a query string. This method should be used when the controller of the pages are different. See example below:

Say we have two pages, Page3 and Page4.

Code for Page3
<apex:page controller="customcontroller3">
   <apex:inputtext id="inpEmployeeName" value="{!EmployeeName}"/><br/>
   <apex:CommandButton value="Next" action="{!next}" id="cmdNext" />
</apex:page>

Code for Page4
<apex:page controller="customcontroller4">
   .The employee name is {!EmployeeName}
</apex:page>

Code for customcontroller3
public with sharing customcontroller3
{
  public string EmployeeName {get;set;} 

  // Function for navigating to next page
  public PageReference next()
  {
     PageReference nextpage = new PageReference('/apex/Page4?EN=' + EmployeeName);
     return nextpage.setRedirect(true); //Note that setRedect method is used here
  }
}


Code for customcontroller4
public with sharing customcontroller4
{
  public string EmployeeName {get;set;} 
  
  //Constructor
  public customcontroller4()
  {
    String strEmpName = ApexPages.currentPage().getParameters().get('EN');
  }
 }

This way, you can transfer data from a page to another even if they don't have the same controller. 

There is another way to transfer data between pages, and that is using Javascript and hidden fields in the form. I will blog on that in my coming posts.

Till then, happy reading. Cheers!

Vishal

Saturday, March 5, 2011

Working with the Salesforce.com Database

Salesforce.com comes with its own database. Salesforce defines a database as "an organized collection of information". Databases in the real world are used to pile up information about real world objects such as employees, students, account holders, company names, industry related data etc. In a typical database such as an Oracle SQL Server or a  Microsoft SQL Server, a database is a collection of related tables, collectively called a schema. Each table contains information about one subject such as student information, where in the table name will typically be named as 'student' or 'table_student' because student is the main subject of importance in this table. The subject of importance is also known as an entity. When we talk about the same stuff in the world of Salesforce, we call this as an object. So basically we can also say that an object is a category of information.

It is worth to know here that there are pre-built objects in the Salesforce.com platform, that we call as sObjects (a short for Salesforce Objects). Beyond these pre-built objects, developers can create custom objects of their own. Thats the power of Salesforce.

A table is comprised of rows (the records) and columns (the fields). The same way, an object is also comprised of records and fields. 

The Salesforce.com is powered by the Force.com platform, a platform through which applications can be built using in built wizards, or through the combination of Visualforce (the pages) and Apex (the programming language). Apex is leveraged by a query language called SOQL (Salesforce Object Query Language) that allows querying objects in Salesforce.

However, it is important to note that SOQL does allow DML statements (such as insert, update, delete, upsert) but does not allow DDL statements (such as create, drop, alter).

Now that objects have been discussed, lets talk about what are fields. In short, fields are the column headers that signify what data about that object is there in that column. For example, we can have an object by the name "Employee" and we can have fields defined against this object, such as "Employee Name", "Age", "Designation", "DOB", "DOJ", "Department" etc. 

Moving on to the next level, a database comprises of multiple objects. This is to ensure that everything (ie every piece of data) is not packed into one object. For such scenarios, Salesforce.com allows relating tables. For example, we may associate a Manager with an Employee. That means we are talking about two objects here, the Employee object (that will house all the employees information) and the Manager object (that will house all the managers information).

Now to relate objects, we need unique columns in each table. This can be done by marking one column in a table as a primary key, and the corresponding column on the other object as the foreign key. 


In my next posts, I'm going to talk about the different types of relationships that can be created using the Force.com platform. 




Sunday, February 27, 2011

Ways to deploy Apex to a Sandbox org

The greatness of working on the Force.com platform is that it allows you to work on different environments. This means you can create your environment for Testing, a separate one for Training, and separate ones for Development and Production. A Developer usually works on the Developer org or the Sandbox org.

In this blog post, I'm going to point out the different ways through which deploy Apex code to a Sandbox Organization from your Force.com IDE (i.e. your local environment in Eclipse).

The first way is to use the Force.com Component Deployment Wizard. This allows developers to select only the Metadata components that need to be deployed, on the Sandbox org. Checkout this link for more details: http://wiki.developerforce.com/index.php/Deploy_Force.com_Applications_Faster

The second way is to use the deploy() metadata API call. This method allows moving metadata (XML files) from the local system to the Salesforce organization. Checkout this link for more details: http://www.salesforce.com/us/developer/docs/api_meta/Content/file_based.htm

Basically, this command can be executed in a console window. On a similar note, the retrieve() API call is used to pull data from the Salesforce org to the local environment.

Happy reading.