December 12, 2011

Expecting more Java goodness in Apex?

Apex Runtime Update for Developer Edition Orgs complies Apex code to Java byte code. This change is awesome from performance improvements standpoint, but shall we expect more Java into Apex also ?

Few of the following Java features would be a nice addition to Apex:

December 11, 2011

Easy Visualforce charts with Javascript Remoting & Google Charts API.

We all know native visualforce charting is coming soon to the platform. Still, we have to cater customer requirements and can’t wait for this PILOT feature to become GA. So here is a quick and simplistic example to render charts at blazing fast speeds using Javascript remoting and Google Charts API.

Code for both Apex and Visualforce is kept minimal and simplistic to be self explanatory.

Apex Global Controller

Apex controller is a global class with @RemoteAction. It loads most recent 10 opps in the remote method.

global with sharing class GoogleChartsController {
    
    /**
      Loads most recent 10 Opportunities
    */
    @RemoteAction    
    global static Opportunity[] loadOpps() {
        return [select Id, Name, ExpectedRevenue, Amount from Opportunity order by CreatedDate DESC limit 10];
    }   

}

Visualforce page

Added decent comments in code itself to make it easier to relate and explain.

<apex:page controller="GoogleChartsController" sidebar="false"> 
    <!-- Google API inclusion -->
    <apex:includeScript id="a" value="https://www.google.com/jsapi" />
    
    <apex:sectionHeader title="Google Charts + Javascript Remoting" subtitle="Demoing - Opportunities by Exepected Revenue"/>

    <!-- Google Charts will be drawn in this DIV -->
    <div id="chartBlock" />
    
    <script type="text/javascript">
        // Load the Visualization API and the piechart package.
        google.load('visualization', '1.0', {'packages':['corechart']});
      
        // Set a callback to run when the Google Visualization API is loaded.
        google.setOnLoadCallback(initCharts);
  
        function initCharts() {         
          // Following the usual Remoting syntax
          // [<namespace>.]<controller>.<method>([params...,] <callbackFunction>(result, event) {...}
          // namespace : abhinav
          // controller : GoogleChartsController
          // method : loadOpps
          abhinav.GoogleChartsController.loadOpps( 
                 function(result, event){  
                     // load Column chart
                     var visualization = new google.visualization.ColumnChart(document.getElementById('chartBlock'));
                     // Prepare table model for chart with columns
                     var data = new google.visualization.DataTable();
                     data.addColumn('string', 'Opportunity');
                     data.addColumn('number', 'Expected Revenue');
                     data.addColumn('number', 'Amount');    
                     // add rows from the remoting results
                     for(var i =0; i<result.length;i++){
                        var r = result[i];
                        data.addRow([r.Name, r.ExpectedRevenue, r.Amount]); 
                      }
                    // all done, lets draw the chart with some options to make it look nice.
                    visualization.draw(data, {legend : {position: 'top', textStyle: {color: 'blue', fontSize: 10}}, width:window.innerWidth,vAxis:{textStyle:{fontSize: 10}},hAxis:{textStyle:{fontSize: 10},showTextEvery:1,slantedText:false}});
              }, {escape:true});
          } 
    </script>
</apex:page>

 

Output

Here is how it comes out in visualforce page. Try this demo by directly copy pasting the above code snippets above, you will for sure enjoy the fast rendering speed of page and charts.

image

Using Native Visualforce charting with Javascript remoting

I really liked the way native Visualforce charting is designed, its having variety of ways to accept data source both server and client side i.e. here are the few ways (clicking on hyperlinks below will take you to relevant Visualforce developer guide sections)

Though its important to understand the native visualforce charting limitations also, please check this link for details.

November 19, 2011

XCollections - Use Custom Apex Classes in Map & Set.

Apex currently doesn’t supports User defined Classes/Types(UDT) to be used in Map and Set classes. This is a very hurting limitation in some scenarios.

To overcome this limitation, “XCollections” Apex API project was started few weeks back as an independent project on github. This API as of now has two major classes called XMap and XSet that allows use of UDTs.

Regarding XCollections, I had a discussion with two very respected and well known guys in force.com community( brief intros added below, to help my new force.com peers)

  • Richard Vanhook(Force.com MVP & Tech. Sol Architect @ Salesforce.com)
  •  Joel Dietz(Force.com MVP & Tech Architect @T’quilla Ltd) about XCollections.

We decided that better place for this API is in a sub repository named “collections” under very popular apex-commons framework. So going forward XCollections will be available as “collections” in apex-commons.

Today, I wrapped up long time pending tasks like

  • Code clean up
  • Readme.md in github flavored markdown.
  • Test cases
  • And final push and pull requests for apex-commons :) (waiting for the merge)

You can find complete details about this project and how to use the API here : https://github.com/abhinavguptas/collections

References

Your views and feedback !

Always  appreciate & love to discuss your feedback and views, so looking forward to those :)

November 17, 2011

Force.com ESAPI v0.5 & death of Apex-CRUD-FLS-Validator API.

“Apex-CRUD-FLS-Validator” was an open source project I started few days back on github. Motive of this project was to add some handy apis that were missing previously in Force.com ESAPI v0.4. Those missing APIs on a high level were

  • operation to assert() and throw exception if CRUD/FLS is violated. We found it better to crash the page for security error like Salesforce does, so that admin can give the required access. Showing blank values or hiding items was a challenge to handle in complex screens.
  • operation to check if CRUD/FLS is available on a given Sobject/Fields. This information is used later to show/hide a few links/buttons/sections.
  • ability to cache the field describe call and reuse it across. This is important, as we are already caching describe information as part of other requirement, and don’t want to spend more describe calls for security enforcement on same sobject/fields.

 

Apex-CRUD-FLS-Validator APIs merged with Force.com ESAPI

To merge these Apex-CRUD-FLS-Validator APIs with Force.com ESAPI, I had a discussion with Yoel Gluck. Yoel maintains the Google Code project for ESAPI and is Lead Product Security Engineer at Salesforce. In our discussions about adding these new APIs to the Force.com ESAPI project we figured out plan to merge the APIs.

Neal Harris(Associate Product Security Engineer at Salesforce.com) is the man who finally made this API merge happen, he introduced following new APIs to release out  v0.5 of Force.com ESAPI.

  • Added new functions isAuthorizedToView, isAuthorizedToCreate, isAuthorizedToUpdate, and isAuthorizedToDelete.
  • Added new functions getViewableFields, getUpdateableFields, and getCreatableFields accepting an sObjectType as input.
  • Added a describe info cache. Now all the field desc information is cached
  • Apart from caching the desc information, we are giving a pluggable desc info cache support. This will help those who are already caching desc information in their own apex data structures, those same can be easily reused with ESAPI now, with small piece of code change.

 

Apex-CRUD-FLS-Validator is dead now

Apex-CRUD-FLS-Validator project is no more on github now, any related documentation on my blog etc is also deleted to avoid any ambiguity.

Coming up next !

Coming up next is a couple of blog posts and wiki page updates about the new APIs, code samples and tricks to make most out of them.

November 12, 2011

Self Explanatory naming convention for your Apex Classes

I am following an apex class naming convention in a couple of projects for a while and its turning up well and big timesaver for me, so thought of sharing with you all.

Why a special naming convention ?

You must be thinking, “why a special naming convention ?“ This is required because apex classes doesn’t support nested namespaces or packages(java) to organize code in a clean way. So mostly the “classes” area for an org with reasonable code ends up in a mess. Its hard to tell which class is of what use most of the times. A good example with few classes would be

  • ContactDuplicateCheck < Used in contact dedupe trigger
  • OpportunityAmountValidator < Used to validate opportunity amount in a trigger on opporunity
  • OppLoadController < Visualforce controller
  • AccountLoader < Visualforce extension used to load accounts
  • ContactMergeExtension < Contact merge based on custom logic, an extension class for a VF page.
  • ContactService < WebService based on Apex
  • BulkRecordCleaner < Batch job that cleans the records.
  • NightlyAccountSync < Nightly scheduled job that syncs the system accounts.

It would be hard to tell the use/purpose of above classes, without the desc I added. But this situation is more panic, when many developers are working on the same code base.

Better Naming convention !

 

Approach 1 : Prefixing class names

Apex class names can be prefixed based on the functionality, feature etc

“{prefix}_classname.cls”

Approach 2 : Suffixing class names

UPDATE : 16/Nov/2011 : Based on discussion in post comments with @jpseabury & @RalphCallaway, another approach was highlighted to do the suffixing in similar way. The plus of doing this is “Classes would be correctly sortable in “Apex Classes” section in setup area.” For more details on this, please check the respective comments in this post.

“classname_{suffix}.cls”

Suggested prefixes/suffixes based on scenario

  • page : For all controller and extension classes connected to visualforce pages. Ex. names would be page_OppLoadController, page_AccountLoader.
  • trgr : Any class used by triggers. Example class names would trgr_AccountTriggerHandler, trgr_ContactDuplicateCheck, trgr_OpportunityAmountValidator
  • hlpr : For all the classes, that are having reusable code for helper or utility functions. For ex. any code that is common and reused between triggers and page controllers.
  • btch : Classes for batch jobs.
  • schd : Classes for scheduled jobs.
  • glbl : All global classes.
  • ws : All classes declaring web services in them.
  • test : For all test classes.

You can easily imagine, how easy would be the life on a reasonably big project with many apex classes.

This is how the above class list will look after prefixing.

  • trgr_ContactDuplicateCheck
  • trgr_OpportunityAmountValidator
  • page_OppLoadController
  • page_AccountLoader
  • page_ContactMergeExtension
  • ws_ContactService
  • btch_BulkRecordCleaner
  • schd_NightlyAccountSync

Isn’t it cleaner and self explanatory.

Your thoughts and views ?

Looking forward to those …

November 8, 2011

Rich Visualforce Editor, major feature update live !

 

IMPORTANT: Author of this plugin might not get alerted for any comments made here on this blog’s comments section. I request you all to directly raise issue on the github repository for this product here : https://github.com/ajayhada/Rich-VisualForce-Editor/issues

For those who don’t know about Rich Visualforce Editor, its discussed in my previous blog post. On a high level it gives content assist support in visualforce.

New updates !!!

@AjayHada added a couple of new features to Rich Visualforce Editor, like :

  • Context sensitive help for visualforce tags, i.e. select the tag name and press “CTRL + 1”
  • Toolbar icons to quickly launch visualforce and apex developer guide right inside eclipse.
  • Contextual icons in content assist box for tags and attributes.
  • Update site support. Now updating the plugin is super easy.

Further details below about each update :

Context sensitive help for Visualforce tags !

Now if you need to know more about a visualforce tag you are currently coding around. Just select the tag name after “apex:”, as show below

rich visualforce editor context sensitive help by keyboard shortkey

rich visualforce editor help page opened

TODO : Please note, we are working on an enhancement that will open context sensitive help on a tag without selecting the tag name. It will be out soon in a week time.

Toolbar icons for Visualforce & apex developer guide

Two new toolbar icons are added to quickly launch Apex and Visualforce developer guide right inside eclipse.

toolbar icons to launch apex & visualforce developer guides in eclipse

Contextual icons in content assist box for tags and attributes.

Content assist box is beautified now to support different icons for tags and attributes as shown below.

tag icon in content assistattribute icon in content assist

Update site support

Now less of manual intervention is required in updating the rich visualforce editor. It supports Update site from this version. To update, please follow these steps

  1. Goto “About Eclipse” dialog.  To get this dialog, Mac users “Eclipse > About Eclipse”, Windows/Linux users, “help > about eclipse”.About eclipse dialog
  2. Hit the “Installation details” button.
  3. Hit Update button in next dialog as indicated below. Please agree and complete the next screens on the update flow  : Dialog after hitting the update button

 

Roadmap

We are working in couple of more features as mentioned in TODO section of my previous post.

Feedback & Views

Looking forward to those !

November 2, 2011

Rich Visualforce Editor that finally supports Content Assist !

IMPORTANT: Author of this plugin might not get alerted for any comments made here on this blog’s comments section. I request you all to directly raise issue on the github repository for this product here : https://github.com/ajayhada/Rich-VisualForce-Editor/issues

We all miss content assist support in Force.com IDE Visualforce editor. My previous attempt of using eclipse code templates was a patch to fill this gap. Good news now is, my colleague @AjayHada is creating a Visualforce editor, that will give decent code assistance support on typical “CTRL + SPACE” hit.

Meet @AjayHada !

Before we go any further, let me introduce you all with @AjayHada. He is a J2EE champ with a decade of experience in developing applications ranging from Supply chain management, ERP and Social Event management.

AjayHada’s experiences with Force.com IDE :-/

Ajay recently started learning and developing on Force.com platform. After a few days of flying in clouds, his major point of frustration was Force.com IDE, because of its well known limited capabilities. Being a Java guy by heart, he decided to write an Eclipse plugin to fill this long void, and he started an open source project for visualforce editor. After a few hours of research and RnD he was able to come up with an alpha version of this editor.

This editor is available on github here : https://github.com/ajayhada/Rich-VisualForce-Editor

Rich Visualforce Editor Plugin for Force.com IDE

This editor in its infant stage is supporting content assist for most commonly used visualforce tags.

How to launch ?

launching rich visualforce editor

  • Right click on any Visualforce page, to launch the popup menu.
  • Select “Open With” menu item.
  • In the sub menu select “Rich Visualforce Editor”.

 

 

Content assist in action !

control space with visualforce editor tags

CTRL + SPACE in action for tags

tag specific attributes in visualforce editor

CTRL + SPACE assistance for tag specific attributes

 

Liked it, How to install ?

You can download this zip “rich.visual.force.editor.plugin.zip” from here. After download extract the zip and copy “VFEdit_xxxxx.jar” to “eclipse install folder/plugins”. Restart eclipse to reflect the changes.

Rich Visualforce Editor Roadmap & TODOs

Following are the features planned in next release. You are more than welcome, to fork and contribute to any of these.

  • HTML5 tag support will be added to future versions
  • Only applicable tags will be visible inside tags like apex:param will only be visible for applicable parent tags
  • Display validation errors for apex and html tags
  • Used attributes will be removed from the suggestion box.
  • Suggestion box will also show some mark to show that tag is related to APEX, or HTML4, or HTML5
  • Proper Tag, Attribute, Text, Comment color scheme
  • Context sensitive help within IDE on pressing a hot key for visualforce tags.
  • Support for “plugin update site” for all known pros.
  • Support for dynamic update of tags and attributes, as per new Salesforce releases.

 

Help required from Force.com IDE team !

This plugin can be more awesome, if they can give us XSD/DTD for visualforce tags. This will help a lot in developing this editor in lesser time.

Your views and feedback !

Looking forward to those

October 31, 2011

Easy upgrade Eclipse(Helios) Force.com IDE to Winter’12 release.

After long wait, Force.com IDE team finally released an update for Winter’12 release. To see what’s new and supported platforms, please go here : http://wiki.developerforce.com/index.php/Force.com_IDE_Release_Notes
 
If you are doing clean install or using older version of Eclipse before 3.6 (Helios), you can check the install/update instructions in this wiki page. Though I don’t like those mentioned in this wiki update guide, as it requires you to open “Force.com start page”, that is smart enough to crash the eclipse or would take ages to open on faster internet connections. If you are on Eclipse Helios, my preferred way to update in a simpler way is as follows :
 

1. Goto “help > check for updates” in eclipse menu :  

eclipse check of updates menu

2. Let eclipse search for updates, until it comes with a dialog like this. Select “Force.com IDE” and hit “Next” button, as shown below:

Force.com IDE update dialog

3. Hit “Next” on the next screen :

force.com ide installation details dialog

4 : Accept the license terms and finish as usual :)

force.com ide upgrade license terms dialog

5. Let eclipse download the updates, once done you will get a notification to restart Eclipse. Restart it and you are all set to use Winter’12 IDE.

 

After restart you will notice this classic popup asking for Force.com project upgrades.

force.com upgrade project to winter'12 dialog
I usually do a clean checkout of project again, as I work on very small and selective metadata required at point of time. Why selective metadata, checkout this blog post for more details : http://www.tgerm.com/2010/03/fast-save-refresh-force-ide-eclipse.html

October 16, 2011

Winter’12–Social approving of records using ‘Chatter Approvals’ !

Everyone talking about Social Enterprise, Winter’12 release introduced “Chatter Approvals”. Approvals in Chatter are really fun and new social way of approving items, right inside and from Chatter feeds.

For more details about Chatter approvals, please check this Salesforce documentation.

Next, we will see how its social and fun to have Approvals in Chatter.

Exploring - Leave approvals in Chatter !

Manager approving leaves is common scenario in most of organizations. I tried exploring the same here with new Chatter approvals.

Leave management done using Salesforce

This great team uses Chatter for managing CRM and HRM operations like Leave management.

Leave Sobject

A simple custom Sobject called Leave is created to apply & approve leaves. Here are 4 key fields in it

  • Type(PickList) : EL, ML, etc (Earned Leave, Medical Leave)
  • Reason : Why this leave is required.
  • From Date & To Date.

Approval Process

We created standard approval process via Setup > App Setup > Create > Workflow & Approvals > Approval Process.

This approval process sends the record to approval to User’s manager. No more complexity for sake of fun.

Setting up Chatter Approvals

Here are the steps to make sure your org is ready for Chatter approvals.

  1. Enable approvals in chatter here, Setup > Customize > Chatter > Settings : Enable Chatter Approvals in Salesforce Setup Screens
  2. Enable Feed Tracking for Leave sobject here, Setup > Customize > Chatter > Feed Tracking.
  3. Chatter Approvals lets you create “Post Templates” for Chatter feed post. In a Chatter Post Template, one can pick upto 5 fields from Sobject, those fields will be shown in chatter feed post. Create a Post Tempalte for “Leave” sobject here :
    • Chatter Post Template in Salesforce Setup Menu
  4. In Chatter “Post Template” I selected 4 most relevant fields to a leave i.e. From Date, To Date, Leave Type and Reason. As shown here : Chatter Post Template

All set now to play with Chatter Approvals in leave. Next, we will see all this in action.

Leave approval fun via Chatter Approvals :)

Guys, next story is going to revolve around 3 characters in an enterprise. So, lets meet them :

Meet the cast – employees !

badboss scared employee depressed

Mr. Bad Ass, aka Boss/Manager

Mr. Depressoo, reports to Mr. BadAss

Mrs. Frustoo, also reporting to Mr. BadAss

 

Mr. Depresso wants Leave next week :-?

Mr. Depresso is a star performer working at least 60 hours a week to keep customers & more importantly Mr. Bad Ass happy. On the festive occasion of Diwali, he wants a break to meet family and friends. so applied for Leave of few days using “Leave” sobject in Salesforce CRM.

He creates a leave record and submits it for Approval :

Leave Sobject submitted for approval

Mr. Bad Ass Boss feels such leave plan is imaginary, it’s a Joke :)

As we have chatter approvals enabled Mr. Bad Ass get an update in his chatter feed about Mr. Depresso looking forward for a leave. So he adds a chatter comment, and laughs out on this leave request.

chatter approval post in salesforce chatter

Mr. Depressoo tries convincing boss about seriousness of Matter !

He writes back a chatter comment..

both approver and the one who applied commenting in chatter

Mr. Bad Ass boss is not in mood to understand, so he rejects from Chatter itself !

This is how a rejected leave would look in chatter. Mr. Bad Ass boss also added condolence chatter comment :

rejecting approval request from Chatter

Mrs. Frustoo a silent watcher of all this drama, finally speaks up !

Mrs. Frustoo is a kind hearted lady, suffering from same tortures of Mr. Bad ass. So, she decided to cheer up Mr. Depresoo..

somebody else commneting on the chatter approval feedpost

 

Moral of the Chatter Approvals – Story !

Doing Approvals via chatter is really social and fun. It really adds nice context to discuss the approval in chatter feeds. But but but, one needs to be careful about what’s going to be discussed in Approval’s chatter comments, if wrong information is shared to wrong guys, it might be sarcastic fun.

Looking forward for your views and comments !

October 12, 2011

Parse JSON by one line of code using Winter’12 JSON API !

Salesforce Winter’12 release came with a great new API addition to Apex stack i.e. JSONParser. This parser solves all the classic problems using open source Apex based JSONObject.cls, to know more about these problems read my previous post.

This post is an attempt to discuss how one can simplify both JSON operations like JSON serialization and deserialization(parsing) using the new System.JSON API.

Parsing JSON using Winter’12 API

The new JSON API is having decent documentation and most helpful post to start with is from Mr. Pat (aka MetaDaddy), you can read his post here.

Approach 1 - Parse JSON via Streaming Scary Tokens :((

Pat did a great job in describing how to parse JSON using the streaming token based approach. The streaming token is good from time/space complexity point of view, but if you have to parse a huge JSON structure, it become pain to write a parser using this, at least for me it was like $#$#%$^$. I was like understanding now what, is it START OBJECT, START ARRAY or FIELD… :((

Approach 2 – Using JSON.deserialize(…) method

Luckily, I found a very simple approach that can fit to “MOST” of the JSON parsing scenarios. I said most, because this approach will not work well, if your JSON structure is not naming the fields correctly.

This approach requires you to have well defined Apex classes mapped to each of the structure/entity represented in the JSON string. If your apex class exactly resembles the JSON structure you can parse the whole JSON in just one line of code. How ? we will see next.

Lets take the classical example of Departments, Employees and Addresses i.e. Department has many employees and employee can have multiple addresses.

Example JSON structure for one department :

{
   "name":"Engineering",
   "code":"ENGR",
   "employees":[
      {
         "name":"James Bond",
         "mobile":"123-456-7892",
         "isMale":true,
         "age":29,
         "addresses":[
            {
               "street":"900 Concar Drive",
               "state":"CA",
               "postalCode":94402,
               "isPrimary":true,
               "country":"USA",
               "city":"San mateo"
            },
            {
               "street":"800 Bridgepointe",
               "state":"CA",
               "postalCode":29230,
               "isPrimary":false,
               "country":"USA",
               "city":"Foster City"
            }
         ]
      },
      {
         "name":"Brad Pitt",
         "mobile":"987-456-7892",
         "isMale":true,
         "age":35,
         "addresses":[
            {
               "street":"900 Rough Drive",
               "state":"CA",
               "postalCode":13245,
               "isPrimary":true,
               "country":"USA",
               "city":"SFO"
            }
         ]
      }
   ]
}

Object model required for this JSON :

I have created following classes nested under a top level class called “JsonParserTests”.

public with sharing class JsonParserTests {
    
    class Department {
        public String name;
        public String code;
        public Employee[] employees;        
        
        public Department(String n, String c) {
            this.name = n;
            this.code = c;
            this.employees = new List<Employee>();
        }        
    } 
    
    class Employee {
        public String name;
        public Integer age;
        public String mobile;
        public boolean isMale;
        public Address[] addresses;
        
        public Employee(String n, Integer a, String m, boolean im) {
            this.name = n;
            this.age = a;
            this.mobile = m;
            this.isMale = im;
            this.addresses = new List<Address>();
        }
    }
    
    class Address {
        public String street;
        public String city;
        public String state;
        public Integer postalCode;
        public String country;
        public boolean isPrimary;
        
        public Address( String street, String city, String state, Integer postalCode, String country, boolean isPrimary) {
            this.street = street;
            this.city = city;
            this.state = state;
            this.postalCode = postalCode;
            this.country = country;
            this.isPrimary = isPrimary;
        }
    }
} 

 

Parsing the full JSON in one line of code.

Here is the method from System.JSON to do so :

// This department instance is having the full hierarchy
// of employees and addresses in it
Department d = (Department)JSON.deserialize(jsonToParse, JsonParserTests.Department.class);

The beauty of this JSON serialization is you get the full nested object hierarchy in JSON created in one go. Also, it just needs one script statement for the full parsing operation.

One might argue that the above nested classes more than one line of code. I would say its always good to visualize and work on Entities mapped to Classes/Types. Even if one is using streaming parser, they would have required similar nested classes by the end of parsing.

Approach 3 – Hybrid of Streaming Tokens and deserialize !

As I mentioned above in Approach 2 also, that all JSON strings can’t be deserialzed directly using “JSON.deserialize()” call. The JSON structure needs to be well formed with proper field names etc. The good news is one can use both streaming token parser and deserialization together i.e.

  • Parse partial JSON structure using streaming tokens
  • Parse part of JSON structure that can be mapped to an Apex class using “JSONParser.readValueAs()” API.

JSONParser.readValueAs() is almost similar to JSON.deserialize() call, only difference is it works on current token value, instead of taking the JSON string explicitly as param.

Here is an example of “JSONParser.readValueAs()” for the same department JSON structure, but using hybrid mode. Here we will only parse first employee object via JSONParser.readValueAs(..)

System.JSONParser parser = JSON.createParser(jsonToParse);
parser.nextToken(); // START OBJECT
parser.nextToken(); // name
parser.nextToken(); // engineering
parser.nextToken(); // employees
parser.nextToken(); // start array
parser.nextToken(); // start object
// only first employee object parsed.
Employee employee = (Employee)parser.readValueAs(JsonParserTests.Employee.class);  

 

Serializing JSON from Apex in one line of code !

Similar to the easy deserialization approach discussed above, one can serialize complete object graph too. For ex. the same above JSON structure for department can be created like this

Department engineering = new Department('Engineering', 'ENGR');

Employee e1 = new Employee('James Bond', 29,  '123-456-7892', true );
engineering.employees.add(e1);

e1.addresses.add(new Address('900 Concar Drive', 'San mateo', 'CA', 94402, 'USA', true));
e1.addresses.add(new Address('800 Bridgepointe', 'Foster City', 'CA', 29230, 'USA', false));

Employee e2 = new Employee('Brad Pitt', 35,  '987-456-7892', true );
engineering.employees.add(e2);
e2.addresses.add(new Address('900 Rough Drive', 'SFO', 'CA', 13245, 'USA', true));
// JSON string created and printed in debug logs
System.debug(JSON.serialize(engineering));

 

References

Your views and thoughts ?

Looking forward for your comments !!

Visualforce Code Templates/Snippets for Force.com IDE !

I recently saw a lot of action around Mac’s favorite editor TextMate. Force.com community has done a great job to create a full fledged IDE and various code templates for ease in working.

I like TextMate, but I am more inclined towards Force.com IDE, because of its platform neutral nature. Most of my force.com pals are either on Windows machines and few of the geeks are using Ubuntu too. So I am always more motivated towards doing something using Force.com IDE.

Force.com IDE is already doing a decent job on top of Eclipse. It gives a nice Visualforce editor, that gives syntax highlighting and code indentation based on standard Eclipse HTML Editor. I recently tried to create a couple of Visualforce code templates/snippets to quickly assist in creating the pages, and was successful in that attempt. Rest of the post describes how.

How to setup Visualforce code templates for Eclipse ?

Here are the steps

  1. Goto Eclipse > Preferences.
  2. Search for “Template” in the left pane preference filter box, as shown belowEclipse Preferences Pane with Template Search Text 
  3. Hit the “New” button on extreme right side to start creating a new Template, as shown :Create New template for visualforce tag
  4. In the dialog next, enter tag name in the text field labeled “Name” and code snippet in text area labeled “Pattern”. Also select context as “HTML Tag”, as shown below : Defining template name and pattern for visualforce
  5. Now, in any visualforce page in Force.com IDE, press CTRL + SPACE and start typing the tag name, like apex:p… In the content assist box, you will see the newly created template as shown below. Hit enter to get the template inserted in current code location.  Visualforce template based content assist box in Eclipse

Using the same steps as above, I have created a few templates for visualforce like

Field Label Template

Visualforce Field Label template

CRUD FLS Permission

Visualforce CRUD FLS check template

Creating a useful template library for Visualforce !

The good part about Eclipse templates is those can be exported and imported back via XML. I started creating a few code snippets/templates and the export for them is available in gist here.

One can easily import this GIST on the same template page using the “Import” button near the New one. Similarly exporting yours is easy too, just select templates to export and hit “Export” button.

Please join me to add more and better code templates for making Visualforce development easier in Eclipse.

October 11, 2011

Visualforce RelatedList CRUD FLS Security Tip !

Visualforce makes it very easy to create Salesforce look and feel pages. It also helps developers to get most of the Salesforce security guidelines implemented transparently, though developers need to take care of few items on their own. All these items are discussed in great details on DeveloperForce WIKI here. Motive of this post is to highlight a common mistake done by most of the developers from both security and quality point of view.

Code below is a very basic example of a visualforce page, to show some account details with a Contact related list only.

<apex:page standardController="Account">
    <apex:detail relatedList="false"/>
    <apex:relatedList list="Contacts"/>
</apex:page>

This page will work very well with all user’s, whose profiles are having at least read permission on “Contact” standard object. But but but, the same page will crash completely if user’s profile is not having at least READ permission on Contact, like this

Visualforce error on missing related list permission

So, its clear that Salesforce doesn’t transparently hides the related list on missing permissions, thus highly recommended to all Salesforce developers to add a security CRUD/FLS check on related lists too like this

<apex:page standardController="Account">
    <apex:detail relatedList="false"/>
     <!--
          Control rendering of related list by checking the relevant
          child sobject, via $ObjectType.Contact.accessible
     -->
    <apex:relatedList list="Contacts" rendered="{!$ObjectType.Contact.accessible}"/>
</apex:page>

Now, the page will atleast show the record details except the Contacts related list on Account and this is what should happen as per profile permissions.

I hope above fix will make life easy post go-live, no fear of facing a panic customer whose page is messed for a given profile :)

References

 

Want to explore more about Salesforce security ?

These articles will be a good read

September 29, 2011

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

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

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

“JSON response vs JSONObject Parser” the bloody war !

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

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

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

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


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

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

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

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

Is Game over ?

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

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

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

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

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

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

$ dscacheutil –flushcache

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

More thoughts ?

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

September 24, 2011

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

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

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

@isTest
private class Test_System_RunAs {

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

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

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

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

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

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

Your views and comments

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

Posted the same as a question on Apex development boards here

Dependency Injection for ease in Testing Apex WebService Callouts !

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

 

Fixing the problem with Dependency Injection

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

1. IHttpResponse

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

2. IHttpCallout

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

 

Implementing contract for both Real World & Test Simulation !

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

Real World Implementation.

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


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

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

}

Testing Simulation for Amazon Sample above

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

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

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

 

Did you noticed ?

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

Source Code as GIST

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

Feedback & Views

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

September 11, 2011

Seesmic CRM for Salesforce (Android Version) reviewed !

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

Playing with Seesmic CRM for Android !

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

What I liked about Seemic CRM for Android !

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

Issues and Challenges for Seesmic CRM

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

 

Feedback

Looking forward for your thoughts on this post.