October 30, 2010

How to logout and use multiple Salesforce Orgs with Chatter Desktop !

Chatter Desktop client gives no clear way to logout from a Salesforce Org. This can be because it uses OAuth  internally to authorize with Salesforce. So this post if for you, if you want to

  • Logout yourself or End your Chatter Desktop session.
  • Work with multiple Salesforce orgs with Chatter Desktop.

Logout/End your session on Chatter Desktop

Though this should be rare requirement, as we always keep us logged in to Yahoo/Gtalk Messengers, unless we are working on some temporary office or public machine.

This is pretty easy to do, here are the steps.

  1. Login to your Salesforce org via web browser Smile
  2. Goto Setup > Personal Information page.
  3. On this page, locate a related list / section titled “Remote Access”.
  4. If you have authorized Chatter Desktop Client,  something similar to following screenshot should appear. If you see multiple entries here, please select the one, where “Application” column is having “Chatter Desktop” entry in it (same is shown in big red circle)image
  5. Next, hit the “Revoke” link, in the first column titled “Action”.

imageThat’s it, you are now logged out from the Chatter client. This is not a true logout, we just revoked the oauth authorization. So it leaves so loop holes behind, i.e.

This logout(Revoke) will come to effect on if the Chatter desktop client is closed and restarted. If Desktop client was launched before you revoked the rights, it will keep on working normally.

But on trying to use Chatter desktop on next restart, one will get error screen like the one on left.

 

 

 

 

Work with multiple Salesforce orgs on Chatter Desktop !

Here are the steps to do this.

  1. Click on the Options button, located at the top. And in the popup menu, select “Settings”, to get to the screen shown in next step. image
  2. This screen maintains connections to all of your Salesforce Production/DE/Sandbox orgs.  By default you will see just the default/selected connection and an additional unselected connection to a Sandbox. image
  3. To add a new Org/Connection, enter server name and url in text fields, as highlighted in the screen shot. Server name, can be any good name, that is easy to remember. Server URL can “https://login.salesforce.com” or “https://test.salesforce.com” for Sandbox orgs. Lets say I want to add new production or DE org. So I will use  “https://login.salesforce.com” and will hit the “Add” button.image 
  4. Next, we will see the updated Connection list, as shown below. Make sure the radio before the new org name in the connection list is selected. Selection this radio ensures, that on next run, Chatter desktop will ask user again for authorizing with a new Salesforce Org.image
  5. That’s it, you are all set now. Please restart the Chatter desktop client to see start adding new org. Any time you wish to switch back to some other org, select any other existing connection or create a new one.

Ideas & Comments

I wish, Chatter desktop client makes it simple to add new orgs. For ex. a drop down, right their in the main interface that list all existing connections and ability to add a new one.

What do you say ?

Recommended relevant reading about Chatter !

Salesforce Chatter Desktop client now available for download !

image

I was excited to see this update of Chatter Facebook page. Without any delays, I logged-in to my Salesforce org, to download chatter desktop client.

To install Chatter Desktop, GoTo :(Setup » Desktop Integration » Chatter Desktop).

Expectations set with Chatter Desktop Client

Chatter desktop download page has some interesting facts about the client, like

  • Receive automatic alerts when your feed gets updated
  • Update your status without going into your browser
  • Drag & drop files from your desktop right into Chatter

All features look good for first version of a desktop client. Receive automatic alerts was of prime interest for me, my expectation was something like yahoo messenger / google talk / Tweek Deck will popup on updates in chatter feed.

 

Chatter desktop experience

Chatter desktop’s setup was a small Adobe AIR setup file, it quickly downloaded and installed. On run, I saw this authentication screen, one can login to production or sandbox orgs. Chatter desktop uses Oauth to authorize with Salesforce. So you will see these 4 screens before the Chatter feed.

imageimageimageimage

imageUser interface shown next, is pretty clean >>>

As said by Salesforce, one can easily update status, upload files via drag/drop and comment on existing posts. I liked all of that, it was pretty easy and fast.

Enhancements expected from Chatter Desktop Client

I must say, it’s a good first version of Chatter desktop client. But for sure there is a lot of scope for improvements. Like :

  • A way to locate SObjects, I am following or I can follow. So we can have another tab like “SObjects”, that offers clean layout to give next level of filtering based on Account, Opportunities and Custom Objects names.
  • As of now, Chatter desktop throws user on web browser for almost everything expect comments and file upload. We can have some brief details about User(self/other) Profile & Sobject right in the client itself.
  • Any redirection to web browser, shouldn’t require login. As of now Chatter desktop URLs are not taking care of that.
  • I can’t see notifications working. Would love to see Tweet Deck style notifications with Chatter Desktop client too.
  • There should be clean way to logout, as of now their no clean way to logout and login to other org in Chatter desktop. I will explain, how to do so in other blog post.
  • Ability to login to multiple Salesforce org/accounts. Again I am Tweek deck fan, so having ability to login to multiple Salesforce Orgs at the same time will  help for sure.

What do you say ?

Do you feel enhancements mentioned in this post makes sense. If YES, please comment, we will groom them to SFDC IdeaExchange.

Recommended relevant reading about Chatter !

October 27, 2010

Tolerado WSC APIs upgraded to support SFDC Winter’11 Web Service API changes !

Since SFDC winter’11 release, I was updating the Tolerado WSC APIs. This update to Tolerado APIs was important because Winter’11 brought too many cool enhancements to the Web service API.

List of changes done.

Following are the changes done to Tolerado WSC APIs

1. Upgraded to latest WSC-API

SFDC WSC got a new release(wsc-20.jar) few weeks back, Tolerado was upgraded to use that.

2. Upgrade to latest SFDC API v20.0 WSDLs

All WSDL2Java stuff for each partner, enterprise, metadata and apex WSDL, was regenerated to latest API version i.e. 20.0. This is important so that one can take benefit of cool new features of Web Services API like

  • Multiple Object Type Support: Ability to process records for multiple objecttypes, including custom objects, in one create() or update() call. For example, you can create a contact and an account in one call. Previously, you could only process records for one object type in a call.
  • Better Transactional Control : The New AllOrNoneHeader SOAP Header, allows the create(), delete(), undelete(), update(), and upsert() calls to roll back all changes unless all records are processed successfully. The default behavior is to allow partial success of a call.
  • Increased Number of Relationships Allowed in a SOQL Query : With Winter '11, you can include 25 relationships in a SOQL query in all API versions. Previously, there was a limit
    of 20 relationships.
  • Chatter Photos in User object:  The User object includes new fields if Chatter is enabled:
    • FullPhotoUrl—The URL for a user's profile photo.
    • SmallPhotoUrl—The URL for a thumbnail of a user's profile photo.
    • DigestFrequency—The frequency at which Salesforce.com sends the user’s Chatter personal email digest.
  • More details in Winter’11 release notes for other new and changed objects etc.

3. New Tolerado API’s for AllOrNoneHeader support

ToleradoEnterpriseStub & ToleradoPartnerStub classes are enhanced, to have a direct call to set new AllOrNone header. So one no more needs to get into native SOAP bindings to add this header. Also added Junit tests to make sure the AllOrNone SOAP header changes are working correctly.

Here is a code sample that shows how to turn on “AllOrNone” setting.

 public void testRollBackOnContacts() throws Exception {
         ToleradoPartnerStub stub = new ToleradoPartnerStub(credential);
         //
         // Create a new Contact
         //
         SObject c1 = new SObject();
         c1.setType("Contact");
         String firstName = "Abhinav";
         String lastName = "Gupta-";
         c1.setField("FirstName", firstName);
         c1.setField("LastName", lastName);

         //
         // Create a new Contact, created without last name intentionally to fail
         //
         SObject c2 = new SObject();
         c2.setType("Contact");
         c2.setField("FirstName", "Abhinav1");

         // Using AllOrNoneHeader = true, to make the rollback happen
         stub.setAllOrNoneHeader(true);

         SaveResult[] saveResults = stub.create(new SObject[] { c1, c2 });
         Assert.assertNotNull(saveResults);
         Assert.assertEquals(2, saveResults.length);
         Assert.assertEquals(false, saveResults[0].getSuccess());
         Assert.assertNull(saveResults[0].getId());
         Assert.assertEquals(false, saveResults[1].getSuccess());
         Assert.assertNull(saveResults[1].getId());
   }

One can see Junit tests for each enterprise and partner wsdl as detailed code samples.

4. Latest Tolerado-WSC available in downloads

All code changes are in SVN and latest version of all tolerado and salesforce wsdl jar files etc is available in download area.

What about Tolerado for Apache Axis ?

I have left “Tolerado for ApacheAxis” upgrade intentionally(+to save my time Winking smile) because, I personally feel we should move to SFDC-WSC APIs for all better performance. Still if anyone is blocking/depending on Tolerado for Apache Axis and wants Winter’11 coolness, please let me know. I will do that upgrade to Tolerado-Axis stubs too.

October 20, 2010

Force.com IDE for Eclipse 3.6 Helios, now available !

I was pleased to see that Force.com IDE plugin for Eclipse 3.6(Helios) is now available. You can find the download/installation instructions here. Though there is nothing different to the installation process, you just need to add the same Eclipse-Galileo update site to Eclipse-Helios.

image

I am happy about this release, as I no more need to maintain two versions of Eclipse i.e.

  • Eclipse 3.5 (Galileo) for Force.com projects.
  • Eclipse 3.6 (Helios) for J2EE projects.

Great job force.com tools team. I know its hard to match and release with latest Eclipse versions.

References

October 12, 2010

Debugging Sites Authorization Required Error !

Force.com sites redirects to “Authorization Required” page in case something goes wrong behind the scenes, for ex.
  • The Site’s public access settings or user profile doesn’t have access to a Page, Object, field etc used in the visualforce page / controller.
  • In case of Apex Exceptions like, LimitException.
  • Etc
“Unauthorized” page makes sense in case of missing access problem. But in case of Exceptions ideally the redirect should be the “Exception” page.
End user obviously can’t figure out anything by seeing the page. So how should developers debug this problem ?

Debugging the cause of Authorization required error.

Test  Fixture

To reproduce this problem, easily for all. I just created a super simple VF page. This VF page fails for Authorization required error, because it tried to do “DML” inside the Controller’s constructor. Details of both page and controller are available in code snippets below.
VF Page
<apex:page controller="MyPageController">
    <apex:outputLabel for="contactName" value="Created Contact :"></apex:outputLabel>
    <apex:outputField id="contactName" value="{!contact.Name}"/>                    
</apex:page>
Controller
public class MyPageController {
    public  Contact contact {get;set;}
  
    public MyPageController () {        
     // We are not allowed to do DML in constructor.
  // So this should reproduce the Autorization error on sites
  // pretty easily
        contact = new Contact(FirstName='Failing', LastName ='Contact'); 
        insert contact;
    }
           
}
On executing this page with sites, you will get “Authorization Required” error, as shown:
image
Next we will see approaches to debug the cause of this issue.

Debug Approach 1

The first approach to debug this problem would be to 
  • Enable debugging for “Sites User”, under Setup > Monitoring > Debug Logs.
  • Refresh the page failing for “Authorization” error.
  • Check what comes in debug logs.
The above approach will work most of the time and will let developers know, why “Authorization Required” page is shown. In our case, debug logs clearly say “DML currently not allowed”, as shown in screen shot below.
image
But sometimes on “Authorization” error no debug logs are generated, even if you have enabled debug logging for the user. In that case jump to Approach 2, described below.

Debug Approach 2

Login in your Salesforce org. Make sure you have turned on “Development Mode” under “Setup > Personal Information > Development Mode”.  Try running the same Visualforce page, without the sites domain i.e. execute the page just like any other visualforce page for ex.
"https://<Node>.visual.force.com/apex/<Sites Page Name>”
As development mode is on, one should see the error cause on the page itself. As shown in screen shot below
image
Still, if you can’t see any error on the visualforce page, jump to Approach 3 described  below:

Debug Approach 3

In this approach we will create another sites page, that calls the failing sites page via Apex API, i.e.
“Page.mypage.getContent().toString()”
Lets call that sites visualforce page “Error Finder”. Following is the visualforce + apex code for this new page.
Visualforce Page – ErrorFinder
<apex:page controller="ErrorFinderController"  action="{!fetchFailingPage}" showHeader="false" sidebar="false" >
    <apex:outputText id="failingPageResponse" escape="false" value="{!failingPageResponse}" />
</apex:page>
Apex Controller – ErrorFinderController
public class ErrorFinderController {
    public String failingPageResponse { get; set; }
    
    public void fetchFailingPage() {
       try {
           // Make a call to failing sites page here
           failingPageResponse = Page.mypage.getContent().toString();
       } catch (Exception e) {
           failingPageResponse = e.getTypeName() + ' : ' + e.getMessage() ;
       }       
    }   
}
On executing this page after connecting with sites, you will see why sites page “mypage” was showing Authorization required error. Here is the screenshot of the errorfinder sites page:
image
More over you can also try “Debug Approach 2” described above, i.e. looking into debug logs at “Setup > Monitoring > Debug Logs” for the sites user. You will get better details of error, if debug logs are available for the failing “mypage”.

More ideas/ways you know ?

Please share any thoughts or better ideas to know the cause of such sites page errors.


October 8, 2010

Apex Test data isolation from Org/User’s data.. !

The key to write a good apex test case is isolate test-data from actual org/user data. If your test case in anyway depends on org data, then it will fail for sure in deployments across different Salesforce orgs.

Unfortunately Apex tests run in SYSTEM mode (The permissions and record sharing of the current user are not taken into account), so their is no isolation from the org/user’s data.

How to Isolate test-data from org’s real data ?

  • All your apex code should declare classes as “with sharing”, unless you really want to access all of the org data. This is really important to ensure sharing rules work correct. In case you need to access all org data i.e. by pass sharing rules, then I suggest creating a new top level or nested class with “without sharing” keywords before class name. This without sharing class should be used to fire all such SOQLs, that need to by pass sharing.
  • Using System.runAs(User) one can create some isolation, this is explained in detail here . But, System.runAs() is effective only if :
    • All Sobjects used in Test case are having “Private” sharing access. But that is not possible and real scenario.
    • Test User profile has no profile overrides on sharing rules, like “Modify All Data” or “Modify/View All” permissions for Sobjects used in Test cases.

So, its pretty hard to ensure that test cases will go good all the times. They will certainly fail for bad combination of sharing rules, profile permissions and org data.

So, how to write stable Apex code + Apex Tests ?

The only good way I found is

“you non-test apex code(trigger/controller) should handle test execution smartly”

This means, one has to write the trigger/controller code to filter records more specifically for current user, (if possible) when running in test mode. One can do this by just doing things

  1. All test code should use System.runAs(<Mock User>) for creating quality test data. Note, here creating a mock user, who doesn’t already exists in system is important for isolation. As if you use some existing user, you might be able to see records owned by him/her. How to do so is explained in this post.
  2. Adding this criteria to all SOQL calls “WHERE OwnerId =:UserInfo.getUserId()” when Controller/Trigger is executed from Test Context. When this criteria is in place, only the test data will be visible to trigger/controller code.

Next, in code samples below, we will try to show how one can implement these above two points in Apex.

Code Sample

This the sample code fixture consists of:

  • A simple custom SObject named “TestObj__c” with “Private” Org wide sharing access. This Sobject is just having a Text field named “SomeTextField”.
  • An apex class named “MyClass”, it can be related to any thing i.e. trigger or a visualforce controller. This class
    • tries to query custom object TestObj__c for a criteria.
    • has configuration attributes to tell, if the class is executing in test context.
  • An apex test class that is written for MyClass. It
    • uses System.runAs etc to ensure tests run correctly in all orgs.
    • creates some TestObj__c records, for testing the MyClass’s query.

MyClass Code

Please note this class’s attributes like isRunningTest, this attribute is required until Salesforce winter’11 release is GA, as winter’11 will give System.isRunningTest() method, that can be used anywhere in test code to know if the code is running in test context. 

public with sharing class MyClass {
    public TestObj__c [] objs {get;set;}
   // Should be set to true, by Apex test cases only
   public boolean isRunningTest = false;    
    private Id contextUserId = Userinfo.getUserId();
       
    public void init() {
       String soql = 'select Id, SomeTextField__c from TestObj__c where SomeTextField__c like \'Gupta\'';
        objs = Database.query(prepareTestSOQL (soql));
    }    
    
    private String prepareTestSOQL (String soql) {
       // after winter'11 we can use System.isRunningTest here
       if (isRunningTest)
         return soql.replaceAll('where', 'where OwnerId =:contextUserId and ');
      else
         return soql;       
    }
}

TestMyClass Code

@isTest
private class TestMyClass{
    public static testMethod void testInit() {
       // Query Standard User or what ever profile best for Test Case
        Profile p = [SELECT Id FROM profile WHERE name='Standard User'];
        // Create a in-memory mock user for running tests in limited data access
        // context
        User mockUser = new User(alias = 'newUser', email='newuser@testorg.com',
        emailencodingkey='UTF-8', lastname='Testing', 
        languagelocalekey='en_US', localesidkey='en_US', profileid = p.Id,
        timezonesidkey='America/Los_Angeles', username='newuser@testorg.com');
      
        System.runAs(mockUser) {    
          // Create 2 test records
          TestObj__c c1 = new TestObj__c (SomeTextField__c='Gupta');
          TestObj__c c2 = new TestObj__c (SomeTextField__c='Gupta');
          insert new TestObj__c[]{c1, c2};
          
          MyClass mycls = new MyClass();
          mycls.isRunningTest = true;
          mycls.init();
        // Now this assertion, should never fail
        // as we are restricting the access in main
        // apex code using Owner Id
          System.assertEquals(2, mycls.objs.size());
        }        
    }
}

Do we have a better way to write Apex Tests ?

I know the above approach and code sample is messy and looks wierd, but this is what I can figure out to make sure that test cases run without crashing across the orgs and multiple deployments. I am sure its not possible to do such owner id replacements always, this can be because of many reasons like

  • Project is too big and has many complex SOQLs.
  • For some reasons we can’t add the ownerid filter in SOQL where clause.

So, if you have any better ideas and ways to crack this problem. Please share with me.

New Idea - Apex tests shouldn’t get access to any org’s data !

So is their a way, really to isolate test cases from Salesforce Org data ? I think no body needs to access org’s user data in apex test cases. Test cases should always run in isolation and their should be no way for them to access what’s the user data. This is because, a single force.com app can be installed in many salesforce orgs, if the test cases rely on org data then they will for sure fail any where because of too much or too less data.

I have posted new idea on Idea Exchange, so that this isolation can be given by salesforce to us in coming releases. If you feel, I am correct and this makes some sense. Then please promote this idea.

October 5, 2010

Winter’11 Setup/Logout in dropdown, inspired from Facebook ?

Winter’11 gave an interesting new location to popular links like “Setup” and “Logout”. They are no longer one click available, you have to click your login name in new interface header to see these links. In first appearance I thought its fine. But over the time when I was working in my winter’11 pre-release org and sandbox orgs. I found it little annoying to make 2 clicks to access “Setup” & “Logout”. 

Dropdown inspiration from Facebook !

We are habitual on one click logout, even the same stands true for links like “Settings” which can be related to “Setup” link of Salesforce. Most of the popular sites like twitter, gmail etc give one click access to logout and settings link. Only exception to this is FACEBOOK, which hides logout and settings link under a dropdown. Following pic tries to relate Salesforce dropdown to the Facebook one.

image

Why this dropdown is sensible on Facebook ?

This looks sensible with Facebook, as we rarely click on any “Settings” link, we are too busy to even read the complete news feed ;-) For me “logout” link is the same story, Chrome(browser) remembers me on Facebook forever. If I ever logout or need to re-login on facebook, I have to do “forget password” get recover my Facebook password :-D. So for Facebook perspective, having these links in a drop-down seems good UI decision and saves some real state too.

Why this dropdown is NOT sensible on Salesforce ?

In Salesforce, story is very very different from Facebook. Here is how :

  • We need to click “Setup” too often. This is specially true for developers and admins. So its not like Facebook, where many users doesn’t even understand how much they can do with Settings.
  • We need to “Logout” many times, I usually work on 5-6 different Salesforce orgs in a day, across many projects. Again, its not like Facebook, where you can remember your self forever in a browser.

Views & Ideas of Salesforce community on Winter’11 Dropdown.

Following are some tweets, that strengthen my feeling about issues with new winter’11 UI.

@TehNrd created a GreaseMonkey script to open the drop-down on hover, so saves the extra click. This can be a good idea for Salesforce to make it default behavior. For more details click here.

So its clear that people really loved the original “Setup” & “Logout” links, no body wants a drop-down. Their is even an idea posted on IdeaExchange, to “Bring the Setup link back out of the name dropdown”.  Please promote it, you know we want the links out of the drop-down !

October 4, 2010

Playing with Visualforce $Action Global Variable

Recently, I stumbled upon Visualforce $Action tag. My requirement was :

  • To open the standard “List” page of an Sobject from Visualforce page.
  • To open “New” Contact page from Visualforce page.

Seems too simple :)

I know $Action tag was the way, so I jumped to the “Visualforce docs for Global Variables”. But can’t find any good code sample at this page, only one sample that’s available is for opening new Account page ($Action.Account.New). So I started searching for some sample with Visualforce documentation, found a couple of good links like :

Still I was struggling to open “New” Contact page, based on what I understood from Account code sample in “Visualforce docs for Global Variables”.  I was trying following code snippet to open it in similar fashion.

<apex:outputLink value="{!URLFOR($Action.Contact.New)}">
    Create New Contact
</apex:outputLink>

This didn’t worked, so have to jump on force.com forums for any solution. Luckily I found this link/solution, it clearly states

“This is the syntax you want: {!URLFOR($Action.Contact.NewContact)}

If you're having problems figuring out the name of an action go to Setup -> Customize -> Contacts -> Buttons and Links and look in the "Name" column for the action you want.

I wish the above solution in green is available in original “Visualforce docs for Global Variables”. It was so confusing to have different Action names for even standard objects like Account and Contact.

We need more code samples on $Action

Even after the above solution, I found that every $Action has some dependencies on params etc. For ex.

  • You need to pass in ObjectType with “List” Action : URLFOR($Action.CustomSobject__c.List,  $ObjectType.CustomSobject__c)
  • You need to pass in Object Id to “View” Action : URLFOR($Action.CustomObject__c.View, 'a00900000016iUl')
  • Action to open new Contact is “$Action.Contact.NewContact”, whereas the same for Account is “$Action.Account.New”
  • Similarly, their can be many such examples and special cases.

Lets collect $Action code snippets.. !

Because of many such options with $Action, I thought of creating a centralized collection of all such $Action possibilities & code snippets. This can for sure help other Visualforce developers. For that I started creating some code samples at snipplr.com under tag “visualforce-action-var”.

If you have any more cool samples around $Action, please share on snipplr.com with tag: “visualforce-action-var”.

References

October 2, 2010

Editing Custom Labels in Force.com IDE !

Custom Labels are key to create multilingual Salesforce apps. Developers usually move their page/class to Custom Labels in two steps

  1. The first cut of the page/class is developed using hard coded English labels & messages. This helps in speeding up development time, as switching between IDE & “Custom Label” UI, for each label and message for sure slows development speed.
  2. In second cut, developers usually scan all the pages and classes for any hardcoded English labels/messages. Custom Label is created for each such hardcoded label/message and replacements are done with the Custom Label full api name.

Though this approach speeds the development time, still I feel creating custom labels from UI is time consuming. So to save time, I suggest use Force.com IDE(Eclipse) to directly update/create new labels, and replace the hard coded English text.

How to get Custom Labels in Force.com IDE ?

By default Custom Labels are not downloaded into Force.com project. How to get custom labels into your project depends, if

  • You are creating a new force.com project, or
  • You’re working on existing force.com project

Getting Labels in New Force.com Projects !

In new Force.com project wizard, after entering login/pass you will land up on following screen. Select second option “Selected metadata components:” and hit “Choose” button, this will open a dialog to select metadata components.

 image

In the next dialog, together with classes, pages, resources & triggers etc, make sure “CustomLabels” is selected as shown below. Selecting “CustomLabels” will download them to your force.com project.

image

After completing the above wizard, you will see new source folder named “labels” in your force.com project, as shown below (in red circle). Notice, their is new XML resource named “CustomLabels.labels” in  your force.com project. This is the one, we will use for editing/creating custom labels.

image 

Getting Labels in Existing Force.com Projects !

In case you already working on a force.com project, you can still get “Custom Labels” resource in your project. Here are the steps

  1. Go to Navigator or Project/Package Explorer and right click the force.com project to which you want to add Custom Labels.
  2. In the popup menu, select Force.com and in the next sub-popup menu select “Add/remove metadata components”, as shown below: image
  3. In the next dialog, hit “Add/Remove” button to open the Metadata Selection Dialog image 
  4. Again, as with new force.com project, ensure that “labels”>”CustomLabels” is selected. As shown below:image
  5. On completing this and next dialogs, you will be prompted for project refresh(as shown below). Hit “Yes” button image
  6. After completing the above wizard, you will see new source folder named “labels” in your force.com project, as shown below (in red circle). Notice, their is new XML resource named “CustomLabels.labels” in  your force.com project. This is the one, we will use for editing/creating custom labels.

    image 

Manipulating Labels from Force.com IDE !

To start open the resource “CustomLabels.labels” in Force.com IDE. You will see XML editor with all your custom labels. For demoing in this post, I previously created one custom label from UI, so my XML looks like this :

<?xml version="1.0" encoding="UTF-8"?>
<CustomLabels xmlns="http://soap.sforce.com/2006/04/metadata">
    <labels>
        <fullName>foo_screen_title</fullName>
        <categories>titles</categories>
        <language>en_US</language>
        <protected>true</protected>
        <shortDescription>foo screen title</shortDescription>
        <value>My FOO Screen Title</value>
    </labels>
</CustomLabels>

As you can see this XML structure is pretty simple, you will get a <labels> tag per Custom Label. The key attributes here are

  • Full Name : This is used in API like Visualforce($Label.foo_screen_title) and Apex(System.Label.foo_screen_title) for referring the custom label. You can change this value, by editing text inside the <fullName>…</fullName> tag.
  • Value  : This is the default value displayed for custom label. You can change this value, by editing text inside <value>…</value> tag

Edit custom labels via Force.com IDE

To edit you can change any value inside of the <labels> tag. Once you are done, save CustomLabels.labels file to replicate the changes in your org.

Note : Changing <fullName> of existing label, will create a new label for that name.

Create new custom labels via Force.com IDE

For ex. if I need a new custom label named “bar_screen_title” with value “My BAR Screen Title”, I can just copy the “foo_screen_title” <labels> XML tag from above example and create a new one with attributes required, as shown below :

<?xml version="1.0" encoding="UTF-8"?>
<CustomLabels xmlns="http://soap.sforce.com/2006/04/metadata">
    <labels>
        <fullName>foo_screen_title</fullName>
        <categories>titles</categories>
        <language>en_US</language>
        <protected>true</protected>
        <shortDescription>foo screen title</shortDescription>
        <value>My FOO Screen Title</value>
    </labels>
    <labels>
        <fullName>bar_screen_title</fullName>
        <categories>titles</categories>
        <language>en_US</language>
        <protected>true</protected>
        <shortDescription>bar screen title</shortDescription>
        <value>My BAR Screen Title</value>
    </labels>
</CustomLabels>

Just save this XML file to replicate the new labels in your Salesforce org.

Note

  • Refresh the CustomLabels.labels resource, before making any change and after saving this file. Salesforce re-organizes the xml some times, so its good to always work on latest from Salesforce.
  • If you haven’t created any Custom Labels, you will get no <labels> tag to use as template in “CustomLabels.labels” resource. So I recommend creating at least one via salesforce web interface.

Benefits of having Custom Labels in Force.com IDE !

  • You can text search the “CustomLabels.labels” xml with IDE. Searching for required labels and peeking into details is time consuming on web interface.
  • You can edit/create labels and copy the full api names quickly to your Visualforce and Apex code.
  • Easy to copy multiple labels quickly from one Org to other. You can just open the labels xml file for both org and do a cross org copy/paste of labels easily.
  • Its much faster the web interface to work on labels, specially changing and creating multiple labels at once.

 

Have more thoughts and tips/tricks on this topic, please comment !!