Friday, November 1, 2013

Winter 2014 - give me back my Code Coverage!!! (PART 2 - a follow-up)

Just noticed there is a new blog post that addresses my last topic here at http://kingkoo-salesforce.blogspot.com/2013/09/winter-2014-give-me-back-my-code.html on the code coverage since Winter 14 was introduced.

I urge you to go take a good look.

By now I am used to going to Eclipse or Developer Console to view the code coverage.  I still missed the fact I cannot see the information from my Apex Class page, but I think I am slowly understanding the reason behind it.

This blog was written by Josh Kaplan - he is the Product Manager for Apex at Salesforce.com

http://blogs.developerforce.com/engineering/2013/11/code-coverage-and-the-force-com-developer-console.html

Enjoy!

Thursday, September 19, 2013

Winter 2014 - give me back my Code Coverage!!!

Winter 14 is coming and for some it has already arrived.

While I was exploring some of the new exciting features of Winter 14, I was devastated to find that something has gone missing.

I have been writing a bit of Apex classes lately and as you may already know, Salesforce requires each Apex class to have accompanying test classes to test the code to ensure you have tested your code thoroughly before you deploy the code to production.

In the past, checking how well you have covered your code was a bliss.  All you needed to do was to go to App Setup -> Develop -> Apex Classes and the information would be right there, under the "Code Coverage" column, such as this:


In Winter 14, however, the page becomes this instead:

What?  The invaluable "Code Coverage" column has gone missing.  What is going on??!?

I have submitted a Case, and the reply I received was that it is indeed a new "feature".

For now the only workaround I can think of is to make use of Developer Console, so all is not lost.

All you have to do is to open your Developer Console, click the "Tests" tab at the bottom - NOTE not the "Test" tab (singular) at the top, but the "Tests" tab (plural) at the bottom.  A list of classes and the code coverage should be listed inside the right hand pane.

If you do not know where to find Developer Console, all you have to do is to click your name at the top left corner of the screen, and a pull down menu should pop up.  Developer Console should be one of the options.  Once you click it, a brand new window will appear.

Lastly, if you have any new development regarding this Code Coverage column, please drop me a note too!




Monday, May 20, 2013

Showing images in a list view - A picture IS worth a thousand words!


If you have been using Salesforce a lot, you are probably familiar with the list view by now.  That is what gets displayed when you click a tab, showing you a list of records that your organization has for an object.













You may have also tried to edit or even create a new view because the default view is not quite what you want.  You may want different data, or you may want the information presented in slightly different order.  However, no matter how you customize it, it's still showing you texts after texts after texts, which is rather dull.  You may have a list of all inventories you have in your warehouse, including its inventory count.  Unless you sort your list by quantity,  it may not be straightforward to see which inventory is running low.

Here is the good news:  you can actually use a few simple tricks to display some images in your list view.  Here is how.

For this example that I am using to track my inventory, let's say I want to use different colors to represent the level of inventory count.  So if my count for a product is less than 200, I should pay some attention to it; and if it falls below 50, I really need to do something immediately.  This is like the traffic light analogy.  Green represents safe, referring to merchandise that I have abundant supply of.  Yellow represents attention, referring to stock level between 50 and 200.  Lastly red represents warning, referring to stock level below 50.

Do you know that Salesforce comes with some predefined images?  You can find some of them by reading this document (NOTE:  it is a document from Salesforce dated back in 2005 so some information may have become out of date).  If you want more variety, you can download a Graphics Pack app from AppExchange that has even more images you can use.

For this example, I'm going to use the traffic lights which are readily available at Salesforce.com:


/img/samples/flag_green.gif

/img/samples/flag_yellow.gif

/img/samples/flag_red.gif
In order to use the image files, all you need to do is to create a formula field in the Merchandise__c object.  The output of the formula field will be a string that indicates the name of the filename of the image.  I am going to call this formula field Quanaity_Level__c.

This formula is going to make use of two functions, image() and if().

If you have done some programming at all, you probably can guess if().  The if(condition_test, condition_true, condition_false) function takes three arguments.  The first argument condition_test is the condition to check, the second argument condition_true is what you want to return if the first argument is true, and the third argument condition_false is what you want to return if the first argument is false.

The function image(image_url, image_text, image_height, image_width) takes four arguments.  The first argument image_url is the url to the image file.  The second argument image_text is the text to display if the image does not load for some reasons.  The last (optional) arguments image_height and image_width represent the size of the image.  The image shrinks or stretches if the size specified here does not match the actual size of the original image.  If these two arguments are omitted, the image will be rendered at its original size.

What we are trying to do is to check the Quanaity__c field of the Merchandise__c object.  With careful coding, applying the above business logic I outlined, this is what the formula field will look like:
if(Quantity__c >= 200, 
  image('/img/samples/flag_green.gif', 'Abundant'),
  if(50 <= Quantity__c && Quantity__c < 200,   
    image('/img/samples/flag_yellow.gif', 'Attention!'),
    image('/img/samples/flag_red.gif', 'WARNING!!!')
  )
)

Let's say you have already defined a new list view called "Merchandise with Quantity".  It may look like this:



After you have created this formula field, all you need to do is to include it in your list view definition.  Your list will look like this.

Of course, you don't really need to have an image every line.  You might only want to show the flag when your merchandise has gone down to dangerous level, because that will really make your merchandise with a low inventory count stand out.

Do you know how to change your formula field so you can produce this list?




Lastly, keep in mind that formula fields can not only be used in your list view.  Once you have created it, it can be used in many places, such as in your form (either edit page or detail page) or even reports.  Let's go and explore!

Wednesday, May 1, 2013

BUG REPORT: Dynamic Visualforce Bindings


Before I start, I encourage you to go over Salesforce’s Visualforce Developer’s Guide which you can find here.  There is a section called “Dynamic Visualforce Bindings” that already provides the syntax and more information about the topic that I am discussing today. 

If you don’t have time to read the Developer’s Guide, or if you just want to quickly glance at what I have to say today, then still please let me quickly talk about what exactly Dynamic Visualforce Binding is.  It is an extremely powerful tool to build dynamic pages at run time.

We all know that Visualforce is the “V” (view) part of the MVC paradigm that Salesforce uses.  It indicates what the user interface of a page is like.  A traditional Visualforce page denotes how the page should look like, what information is displayed, and in what order.  In other words, a Visualforce page dictates what information the users see and how they see it.  The person that wrote the Visualforce page is in the driver's seat.
  
However, imagine this use case.  What if you want to display a list of accounts, but you also want to give your users the flexibility to determine what information about the account they want to see.  You may want to present a list of account related fields, and the users can select what fields they want to see and in what order.  Having to program that logic can be a nightmare:  the users may choose one field or ten fields, the users may choose Name first this time and then Name last next time.  There are so many possibilities and combinations that, if not programmed carefully, your code can become nothing but an endless list of if-then-else statements.

Enters Dynamic Visualforce Binding.

Let's just quickly see what a regular Visualforce page looks like.  As an example I want to display the account name, account number, annual revenue and ticker symbol of a list of accounts.  To do that, all you need to do is a very simple Visualforce page like this:
<apex:page standardController="account" recordSetVar="accounts">
    
    <apex:pageBlock >
        <apex:pageBlockTable value="{!accounts}" var="a">
            <apex:column value="{!a.Name}" />
            <apex:column value="{!a.AccountNumber}" />
            <apex:column value="{!a.AnnualRevenue}" />
            <apex:column value="{!a.TickerSymbol}" />
        </apex:pageBlockTable>
    </apex:pageBlock>
    
</apex:page>

Your page will look like this:










In order to use Dynamic Visualforce Binding, you need a little help from a controller.  (I know it can be a turnoff,  but no pain no gain!)

Let's take a look at the controller (again, I don't want to divulge into the syntax.  Please refer to the Developer's Guide for the detailed syntax.  I just want to show you how little code is required to unleash the power of Dynamic Visualforce Binding.)


public class AccountListDynamic
{
    // constructor that simply adds the list of fields 
    // for the account.
    public AccountListDynamic(ApexPages.StandardSetController controller)
    {
        controller.addFields(accountFieldList);
    }

    // accountFieldList is a property.  It is a list of 
    // strings and each element in the list is the API 
    // name of the field that I want to display.  This list
    // is read-only.
    public List<String> accountFieldList
    {
        get
        {
            if (accountFieldList == null)
            {
                accountFieldList.add('Name');
                accountFieldList.add('AccountNumber');
                accountFieldList.add('AnnualRevenue');
                accountFieldList.add('TickerSymbol');
            }
            return accountFieldList;
        }
        private set;
    }

}

I hope the class is quite self-explanatory.  It is an extended controller (hence the ApexPages.standardSetController parameter in the constructor of the class).  All that we are achieving here is to pass an array of account related field names (API names) and expose the list to the Visualforce page.

The Visualforce page now looks like this:
<apex:page standardController="account" recordSetVar="accounts" extensions="AccountListDynamic">
    <apex:pageBlock >
        <apex:pageBlockTable value="{!accounts}" var="a">
            <apex:repeat value="{!accountFieldList}" var="f">
                <apex:column value="{!a[f]}" />
            </apex:repeat>
        </apex:pageBlockTable>
    </apex:pageBlock>
</apex:page>

The hardest part to understand is probably a[f] above.  "a" is a loop variable for each account in the list.  "f" is a loop variable for each field to display.  Therefore to simply put, a[f] refers to the value of a specific field for a specific account.

So, sure now you have the controller that makes things look a little more complicated, but did you notice the controller now handles the list of fields.  All the Visualforce page does is to simply take that list of fields and displays the relevant data; you do not have any field names hardcoded in the Visualforce page at all!

Now, going back to our use case.  Let's say you want to show the user a list of all account related fields, so that the user has the ability to choose which fields they want to display and the order the fields are to display.

You will need a separate Visualforce page for that.  Once you have built this new Visualforce page for that, then all you need to do is to capture the information in your controller.  Then the Visualforce page shown above again can be used to display the information.

This is exactly what the example in the Developer's Guide, in section "Using Dynamic References for a User-Customizable Page", is about.  It is an excellent read, and I urge you to take a look at this topic.

The most unfortunate thing is that this function is not stable.  I have got the code to work in some environments but fail in others.

I followed the example as per the Developer's Guide and this is the error I received:



I have talked to Salesforce and it is now officially under the "Known Issues" list.  If you are interested, you can take a look at this page for more details.  If you can replicate this error too, I strongly encourage you to click the "This Issue Affects Me" button.  Note that the example there is quite different, but it still exposes the defect related to Dynamic Visualforce Binding.




Friday, April 19, 2013

The case of missing Leads information


These days I have been studying my Sales Cloud certification exam so I have dropped Apex and Visualforce for a little bit.  This morning it dawned on me I shouldn't only cover Force.com platform related topics in my blog.  So I'm also going to start putting in some tips and tricks of other parts of Salesforce from now on.

I recently joined the new SFDC Calgary User Group.  I hope by talking to other users of Salesforce, that would give me more topics to cover in my blog.

In our first User Group meeting I was talking to a few other Salesforce users.  Today I thought I would share with you the problems that one of the Salesforce users was encountering.

Say, you have been using Leads for a long time but every time when you convert the Leads, you lose all the information you have saved with the Leads.

This is clearly a case when you have used some custom fields for Leads but have not provided a mechanism to retain the field information when you convert leads.  Salesforce allows you to copy the Leads information into one or more of Account, Contact or Opportunity objects when you convert leads.  Here is how.

Say you have two custom fields, one called Custom Number and one called Custom Text.  Note the fields at the bottom of the page layout here.



After you save and then convert the lead, the information captured is no longer available.  This is because you have not instructed Salesforce where the two pieces of information should go after you convert the lead.  To fix this, it is a two-step process.


  1. You need to decide whether the information should reside in Account, Contact or Opportunity object.  You then go to create new custom fields in these objects.  Make sure you use the same data type, as you cannot copy a field that is of text type of a field that is of numeric type.  Note that some of your custom fields can go to Account, some to Contact and some to Opportunity object.  It is not an all-or-nothing scenario.  The only restriction is that you can only indicate one object for each field you want to map, i.e. you cannot map a Lead field to Account AND Contact at the same time (you can use trigger to circumvent that, but this is out of scope of this blog post because it is not something you can do simply using the Salesforce set-up menu.  Please contact me if you need more information on how to use trigger if you want to map a field from Lead to more than one object.)
  2. After performing step (1), all that is left to do is to set up the mapping.  Go to Setup -> Customize -> Leads -> Fields and scroll to the Lead Custom Fields & Relationships related list.  You will see a button labelled "Map Lead Fields".

In my example, I have created a custom field in Account called "Custom Number (from Lead)" that is of numeric type.  When I click the "Map Lead Fields" button I am brought forward to this screen.  See how the field from Account is populated for the corresponding field from the Lead object:


Once you have set it up, whenever you convert a lead, the information will be propagated automatically to one or more of Account, Contact and Opportunity based on what you have specified in step (2) above.  Try it out!

That still leaves a second problem.  What about the Leads that you have already converted?  Fear not.  Even though you will no longer see converted leads information from Leads, you can run reports to find them.

The easiest way is to go to Reports tab, create a new report using Leads as the report type.  On the left hand side of the report builder, if you drag the left pane all the way to the bottom you will see a "Lead:  Custom Info" section.  Just drag those fields that you want to retrieve from the left pane to the report preview pane.  Your preview pane should look something like this now:



You're almost done.  All you need to do now is click the "Run Report" button, and then after the report displays, click "Export Details".  This way you will be able to retrieve the Leads information that you have lost.

Please let me know if this works!


Friday, March 15, 2013

My experience taking Spring 13 Maintenance Release Exam

First of all, sorry for being away from the blog for so long.  I have been laying very low the last two months.  After spending almost a month in Asia on holiday, I am feeling rested.

I received some emails from Salesforce last week, letting me know it's time I took my Spring 2013 Maintenance Exam for both of my certifications.

I first went to the Release Training site and noticed this time around there were only three tutorials:  Chatter, Sales Cloud and Data.com.  I was a little taken back.  That's it?  Last release there were 6 training tutorials, I thought.  I followed the instructions given in the email for my Administrator Release Exam and studied these topics, using the training provided.


  • Describe the considerations for setting up the beta version of State and Country Picklists
  • Describe the capabilities of Forecasts
  • Describe the capabilities of Chatter Tasks
  • Describe the enhancements to Chatter
  • Describe the enhancements to Salesforce for Outlook

That was not too bad.  I went through the tutorials twice and went for the exam.  The questions were straightforward.  If you go through the training once or twice, you should be ready for the exam.


After completing the Adminstrator Release Exam, I turned to my Force.com Developer Release Exam.  I read the email and read through the topics to be covered in the exam:


  • Describe the considerations for setting up the beta version of State and Country Picklists
  • Describe the use cases for criteria-based sharing
  • Describe the implications of organization-wide defaults
  • Describe object relationships in Salesforce
  • Describe the features of the Salesforce multitenant architecture

Now I was really taken aback. Only the first bullet is new to Spring 2013.  The other four bullets all seem to be old topics.  This email (unlike the old for Admin) also provides a list of topics that it advises us to study in detail before the exam:


  • Overview of Object Relationships
  • Considerations for Relationships
  • Creating Custom Object Sharing Rules
  • Criteria-Based Sharing Rules Overview
  • Securing Data Access
  • Overview of Sharing Settings
  • Setting Your Organization-Wide Sharing Defaults

I decided to go through all these topics from the Help and Training site.  Maybe there were something new to this release in these area that I was not aware of.  Nothing.  Nothing's changed.  I was really starting to wonder if there were printing errors in the email.

I thought, well, OK, I haven't looked at these topics for awhile, so I will just do what is outlined in the exam guide.  I spent a few hours going through all the above Help topics and then went for the exam.

Boy was I glad.  I am sure I would've passed the Release Exam anyway even if I didn't study for it, but by re-familiarizing myself with these old topics, I finished the exam a lot quicker than I think I would have if I didn't study.  I finished the exam in about 25 seconds and submitted, and done!

The moral of this story is simply that, make sure you follow the study guideline, and you will pass the exams with flying colours!!


Thursday, January 24, 2013

BUG REPORT: Map's equals and hashCode methods.

Reading through Apex Developer's Guide (winter 13).  There is a new section for Winter 13 that talks about how you can compare if two custom Apex classes are equal or not.  The bug is not directly related to the equals and hashCode methods, but the bug is introduced here because from Winter 13, you are allowed to use non-primitive values as keys in maps.

You can find the documentation at this page:
http://www.salesforce.com/us/developer/docs/apexcode/Content/langCon_apex_collections_maps_keys_userdefined.htm

The following is the definition of PairNumbers class.

public class PairNumbers 
{
  Integer x,y;
  public PairNumbers(Integer a, Integer b) 
  {
    x=a;
    y=b;
  }

  public Boolean equals(Object obj) 
  {
    if (obj instanceof PairNumbers) 
    {
      PairNumbers p = (PairNumbers)obj;
      return ((x==p.x) && (y==p.y));
    }
    return false;
  }

  public Integer hashCode() 
  {
    return (31 * x) ^ y;
  }
}

The way it is implemented, if you create several instances of the class and add them to a Map collection, duplicate keys should be counted as one.    For example, if you have lines of code like this:

Map<PairNumbers, String> m = new Map<PairNumbers, String>();
PairNumbers p1 = new PairNumbers(1,2);
PairNumbers p2 = new PairNumbers(3,4);
PairNumbers p3 = new PairNumbers(1,2);
m.put(p1, 'first');
m.put(p2, 'second');
m.put(p3, 'third');


You should now have two elements in the collection m, that is because p3 have the same key as p1.  As a result, p3 replaces p1 in the collection m.

However, I noticed that, if I append the code with this line:
System.Debug(m.size());

and I run this code in Developer Console, the debug log will show 3 as the number of elements in the collection.

Strangely, when I run this on Eclipse, the debug log from there shows 2, which is the expected result.

This is a new feature introduced in Winter 13, and let's hope this gets fixed soon!


Tuesday, January 15, 2013

How to show data from Map collection in sorted order inside apex:repeat

I was going through Salesforce's Visualforce Developer's Guide and Apex Developer's Guide the last few weeks over the Christmas holiday.  In the Apex guide, for Map collection, the book warned that the "order of objects returned by maps may change without warning", and therefore we are asked to "not reply on the order in which map results are returned".

Then in the Visualforce guide, there is a section on "Referencing Apex Maps and Lists" section in the "Dynamic Visualforce Bindings" chapter.  It talked about how we can use data from map in combination with the <apex:repeat> to display data in the map.

What good is it if it cannot display the data properly, especially if the data set is large?

I'm going to use the example in the Visualforce guide as a demonstration.  It can be found on page 158 (if you are using Winter 13 of the Visualforce guide).  I am also going to add just a little more records so it's easier to see how data is sorted.

The following is the code for the class:

public class p158_a_Blog_Example
{
    public Map<String, String> directorMap {get; set;}
    
    public p158_a_Blog_Example()
    {
        // set up the data in this constructor
        directorMap = new Map<String, String>
                {
                    'Kieslowski' => 'Poland',
                    'Gondry' => 'France',
                    'del Toro' => 'Mexico',
                    'Lee' => 'Taiwan',
                    'Cameron' => 'Canada'
                };
        
    }
}

This is the Visualforce page that makes use of this controller.  I modified it a little so it displays the data in a table.
<apex:page controller="p158_a_Blog_Example">
    <apex:pageBlock title="Directors List">
        <apex:pageBlockTable value="{!directorMap}" var="dirKey" style='width:50%'>
            <apex:column value="{!dirKey}" />
            <apex:column value="{!directorMap[dirKey]}" />
        </apex:pageBlockTable>
    </apex:pageBlock>
</apex:page>

Using different DE orgs, I seem to get the results in different order, so the order of the data is indeed inconsistent.  This is how the data came out this morning:


I would like the data to show Cameron, del Toro, Gondry, Kieslowski and Lee, in this order.

I need to modify the code, but the first lesson of all, if you need to preserve the sorting order, use LIST in your <apex:repeat> tag, do NOT use the map variable.

Now let's go back to the class and turn the Map into a List, so we can display the data sorted.  It actually is very easy.  All you need to do is to add a new List variable, set it and then sort it (via the sort() method of list collection).

The new class is modified as this:
public class p158_a_Blog_Example
{
    public Map<String, String> directorMap {get; set;}
    // new variable to hold the list of directors.
    public List<String> directorList {get; set;}
    
    public p158_a_Blog_Example()
    {
        // set up the data in this constructor
        directorMap = new Map<String, String>
                {
                    'Kieslowski' => 'Poland',
                    'Gondry' => 'France',
                    'del Toro' => 'Mexico',
                    'Lee' => 'Taiwan',
                    'Cameron' => 'Canada'
                };
        // Set the new List variable to be the set of directors using the addAll() method.  After 
        // that simply all the sort function to sort the directors' names.                
        directorList = new List<String>();
        directorList.addAll(directorMap.keySet());
        directorList.sort();                
        
    }
}

The Visualforce also now needs to be modified so it is not using the map variable as the data set, but the list variable instead (which now contains a list of directors, sorted).  NOTE:  you still need to use the Map variable to access the country from which the director came from.  The bolded, underlined text is the ONLY change you need to make to the Visualforce page:
<apex:page controller="p158_a_Blog_Example">
    <apex:pageBlock title="Directors List">
        <apex:pageBlockTable value="{!directorList}" var="dirKey" style='width:50%'>
            <apex:column value="{!dirKey}" />
            <apex:column value="{!directorMap[dirKey]}" />
        </apex:pageBlockTable>
    </apex:pageBlock>
</apex:page>

Well...  still something is not quite right.  


The list is now almost all sorted, except the Mexican director is displayed at the end.  Turns out that when you call the sort() method on the List, it sorts the data based on the ascii code.  The lower case 'd' (ascii code = 100) comes after 'L' (ascii code = 76).  That is, the sort is case-sensitive.

In order to make the sort case-insensitive, what I found the easiest is to add two new variables.

A new Map variable (directorName) is created that maps between the director's name in upper case and the name intact.  A new List variable (directorListIgnoreCase) is created to hold the director's name in upper case for sorting purposes.  This List variable is used to determine the order of the directors.  However the data stored in this variable is all in upper case.  That's why you need the new Map variable directorName to find the director's name in its original form.  Then you can use the original Map variable directorMap to get the country information.

This is the final class.
public class p158_a_Blog_Example
{
    public Map<String, String> directorMap {get; set;}

    // new variable to map the directors from all uppercase to the original name.
    public Map<String, String> directorName {get; set;}
    public List<String> directorListIgnoreCase {get; set;}
    
    public p158_a_Blog_Example()
    {
        // set up the data in this constructor
        directorMap = new Map<String, String>
                {
                    'Kieslowski' => 'Poland',
                    'Gondry' => 'France',
                    'del Toro' => 'Mexico',
                    'Lee' => 'Taiwan',
                    'Cameron' => 'Canada'
                };
        
        directorName = new Map<String, String>();
        directorListIgnoreCase = new List<String>();
        for (String s : directorMap.keySet())
        {
            directorName.put(s.toUpperCase(), s);
            directorListIgnoreCase.add(s.toUpperCase());
        } 
        directorListIgnoreCase.sort();              
        
    }
}

The Visualforce now also is updated to reflect the changes:
<apex:page controller="p158_a_Blog_Example">
    <apex:pageBlock title="Directors List">
        <apex:pageBlockTable value="{!directorListIgnoreCase}" var="dirKey" style='width:50%'>
            <apex:column value="{!directorName[dirKey]}" />
            <apex:column value="{!directorMap[directorName[dirKey]]}" />
        </apex:pageBlockTable>
    </apex:pageBlock>
</apex:page>

Notice the repeating variable is the new List directorListIgnoreCase.  Do remember this is the director's name in upper case, so you don't want to display that.  To display the original director's name, you'll see to reference the new Map variable directorName, passing dirKey as the key.  That's why the director's name is directorName[dirKey].  Finally, to get the country information, we will need to reference the original Map variable diretorMap, passing directorName[dirKey] as the key.

The resulting page now looks exactly what I'm hoping for:


I felt like I had to jump through a lot of hoops to get to the final desired result.  If I have missed some steps, please let me know!