Apr 30, 2013

How Can I Become A MVP (Force.com)

Recently my MVP title is renewed (Extra! Announcing our newest and renewed Force.com MVPs) and this question bothered many from time to time "How can I become a MVP"? 

Don't focus on how to become a MVP, focus only on the motive behind the program. It is stated that "Force.com MVP program recognizes outstanding contributors and technological leaders in the Force.com cloud platform ecosystems. Force.com MVPs are being called out for willingly sharing their expertise with others, demonstrating stewardship of the community in which they play an integral part, advancing the community body of knowledge and strengthening the developer network." 

Now there are multiple ways to do this, let's talk about some of them: 

1) Contribution via discussion boards, which is the heart of community. We've multiple discussion boards where you can share your knowledge with other community members.


2) Evangelism of the technology through independent publication such as blogs/whitepapers/FB Page 

3) Contribution to open sources. If you've ever thought about sharing some code samples or some big projects so don't let it be restricted to only your personal blogs. Make them live here:


4) Get Social and stay connected with other peers on social sites like

  • Twitter : Follow official accounts @forcedotcom @salesforce and use #askforce if you need any help or you want to help the community
  • Facebook : Like the official page and stay connected with the latest news and events
  • LinkedIn etc.

5) Participate as much as you can via attending live webinars (you can get the information from social sites or here), online events (where you get chance to win some cool stuff), online challenges like this 

6) Participate in local developer user group meetings. You can get the list of all developer user groups here.

7) Participate in big events like Dreamforce, Cloudstock etc.

List never ends and it's benefits too, like by doing all this

  • Your knowledge will be increased.
  • Your networking will be strong
  • Will be acknowledged globally
  • Significant increase in offers from companies
  • Domain will not be restricted any more
  • After actively participating in events your wardrobe will be full of some cool stuff like Jackets, T-Shirts, Caps, Bags, Trophies, Books, Hoodies


Above benefits are for sure, and if you are entitled as MVP then there are some additional benefits to above:

  • You'll get sponsored trips to SF for events like MVP Summit
  • You'll get free passes to Dreamforce
  • Highlighted community profile, (here is mine)
  • Early access to feature previews and releases, with direct feedback to the PMs on these products
  • Access to chatter groups where all MVPs jam together



I don't know where to stop...so now you have the links and I hope you know what to do. GOOD LUCK!

Make our community rock!!


Mar 16, 2013

Jaipur DUG Cloud Trivia Winners

Yes! It's true, winners list of Jaipur DUG Cloud Trivia is out.
Thank you all who participated. After getting such an awesome response, I hope I'll be able to arrange some more contest like this. It is just to motivate you guys to stay updated with the latest release, and I must say you guys did a great job.

Here is the winners list :-



Amit Jain
Deepali Jain
Pankaj Kabra
Er Deepak Sheoran
Kumawat Deshraj
Jinesh Goyal
Ranu Jain
Mohit Chawla
Ashish Agarwal






Please drop me an email on "ankit.salesforce@gmail.com" so we can co-ordinate how you can collect your prize (T-Shirt/Workbook/CheatSheets/Salesforce Touch Platform Book).

Stay connected with us to know info about more contest like this :-
3) Meetup

Dec 27, 2012

Streaming APIs - Easy Code


Streaming API is useful when you want notifications to be pushed from the server to the client based on criteria that you define.

The sequence of events when using Streaming API is as follows: (explained in detail later)
1. Create a PushTopic based on a SOQL query. This defines the channel.
2. Clients subscribe to the channel.
3. A record is created or updated (an event occurs). The changes to that record are evaluated.
4. If the record changes match the criteria of the PushTopic query, a notification is generated by the server and received by the subscribed clients.

Before we get started, I recommend you to go through these topics:

1) Push Technology
2) Bayeux Protocol, CometD, and Long Polling


We will achieve this once we are done with all steps (given below):





Now follow these steps:

Prerequisites:
1) The “Streaming API” permission must be enabled -> "Your Name > Setup > Customize > User Interface"
2) The logged-in user must have “Read” permission on the PushTopic standard object to receive notifications.
3) The logged-in user must have “Create” permission on the PushTopic standard object to create and manage PushTopic records.
4) The logged-in user must have “Author Apex” permissions to create a PushTopic by using the Developer Console.


Step 1: Create an Object - In our case we will use Account

Step 2: Create a PushTopic
Use the Developer Console to create the PushTopic record. You can use either Developer Console or Workbench. If needed these records can be updated.

"Your Name > Developer Console"


PushTopic pushTopic = new PushTopic();
pushTopic.Name = 'RefreshAccounts';
pushTopic.Query = 'SELECT Id, Name FROM Account';
pushTopic.ApiVersion = 26.0;
pushTopic.NotifyForOperations = 'All';
pushTopic.NotifyForFields = 'Referenced';
insert pushTopic;


Step 3: Create Static resource

1. Download the CometD compressed archive (.tgz) file from http://download.cometd.org/cometd-2.2.0-distribution.tar.gz
2. Extract the following JavaScript files from cometd-2.2.0-distribution.tar.gz:
• cometd-2.2.0/cometd-javascript/common/target/org/cometd.js
• cometd-2.2.0/cometd-javascript/jquery/src/main/webapp/jquery/jquery-1.5.1.js
• cometd-2.2.0/cometd-javascript/jquery/src/main/webapp/jquery/json2.js
• cometd-2.2.0/cometd-javascript/jquery/src/main/webapp/jquery/jquery.cometd.js


File Name
Static Resource Name
cometd.js
Cometd
jquery-1.5.1.js
Jquery
json2.js
json2
jquery.cometd.js
jquery_cometd




Step 4: Test the PushTopic Channel

Here is the code sample

Visualforce Page


<apex:page id="PG" controller="StreamingAPIController">
<apex:form id="FRM">

    <apex:includeScript value="{!$Resource.cometd}"/>
    <apex:includeScript value="{!$Resource.jquery}"/>
    <apex:includeScript value="{!$Resource.json2}"/>
    <apex:includeScript value="{!$Resource.jquery_cometd}"/>

    <apex:actionFunction name="GetRefreshedAccounts" reRender="PB,PBT"/>

    <script type="text/javascript">
        (function($)
        {
            $(document).ready(function() {
                
                // Connect to the CometD endpoint
                $.cometd.init({
                    url: window.location.protocol+'//'+window.location.hostname+'/cometd/24.0/',
                    requestHeaders: { Authorization: 'OAuth {!$Api.Session_ID}'}
                });
                
                // Subscribe to a topic. JSON-encoded update will be returned in the callback
                // In this example we are using this only to track the generated event
                $.cometd.subscribe('/topic/RefreshAccounts', function(message)
                {
                    //You can use message as it will return you many attributes
                    //I am just using to track that event is generated
                    GetRefreshedAccounts();
                });

            });
        })(jQuery)
    </script>

    <apex:pageBlock id="PB">
        <apex:variable var="count" value="{!0}" />
        <apex:pageBlockTable id="PBT" value="{!getRefreshedAccount}" var="AllAcc">
            
            <apex:column headerValue="S.No.">
                <apex:variable var="count" value="{!count+1}" />
                {!count}
            </apex:column>
            <apex:column value="{!AllAcc.Name}" headerValue="Name"/>
            
        </apex:pageBlockTable>
    </apex:pageBlock>

</apex:form>
</apex:page>

Apex Class


public class StreamingAPIController
{
    //Everytime page is reRendered it will get refreshed values of account
    public List<Account> getRefreshedAccount
    {
        get
        {
            return [select Id, Name from Account LIMIT 50000] ;
        }
        set;
    }
    
    public StreamingAPIController()
    {
    }
}


This is very small and simple sample code, you can do a lot more with streaming APIs. Please refer these documents to learn more:

1) http://www.salesforce.com/us/developer/docs/api_streaming/api_streaming.pdf
2) http://www.salesforce.com/us/developer/docs/api_streaming/index.htm
3)http://wiki.developerforce.com/page/Getting_Started_with_the_Force.com_Streaming_API

Dec 22, 2012

Uploading Multiple Attachments into Salesforce - Simple Code

Okay, so here is the simple code to upload multiple attachments into Salesforce. Please note that I've used standard controller ("Account" in the code) so you need to pass the record Id in parameter. You can also change this according to your need as code is dynamic.

So first option allow you to select how many files you want to upload. Say, you have selected "5", then it will give you 5 options to select files and once you click on "Upload" it will upload the files as attachments to the associated record.



Visualforce Page Code:


<apex:page standardController="Account" extensions="MultipleUploadController">
    <apex:form>
        <apex:pageBlock title="Upload Multiple Attachment to Object">
            
            <apex:pageBlockButtons>
                <apex:commandButton value="Upload"  action="{!SaveAttachments}"/>
            </apex:pageBlockButtons>
            
            <apex:pageMessages id="MSG"/>
            <apex:actionFunction name="ChangeCount" action="{!ChangeCount}"/>
            
            <apex:pageblocksection>
                            
                <apex:pageBlockSectionItem>
                    <apex:outputLabel value="How many files you want to upload?"/>
                    <apex:selectList onchange="ChangeCount() ;" multiselect="false" size="1" value="{!FileCount}">
                        <apex:selectOption itemLabel="--None--" itemValue=""/>
                        <apex:selectOptions value="{!filesCountList}"/>
                    </apex:selectList>
                </apex:pageBlockSectionItem>
            
            </apex:pageblocksection>
            
            <apex:pageBlockSection title="Select Files" rendered="{!IF(FileCount != null && FileCount != '', true , false)}">
                <apex:repeat value="{!allFileList}" var="AFL">
                    <apex:inputfile value="{!AFL.body}" filename="{!AFL.Name}" />
                    <br/>
                </apex:repeat>
            </apex:pageBlockSection>
            
        </apex:pageBlock>
    </apex:form>
</apex:page>


Apex Code:


public class MultipleUploadController
{   
    //Picklist of tnteger values to hold file count
    public List<SelectOption> filesCountList {get; set;}
    //Selected count
    public String FileCount {get; set;}
    
    public List<Attachment> allFileList {get; set;}
    
    public MultipleUploadController(ApexPages.StandardController controller)
    {
        //Initialize  
        filesCountList = new List<SelectOption>() ;
        FileCount = '' ;
        allFileList = new List<Attachment>() ;
        
        //Adding values count list - you can change this according to your need
        for(Integer i = 1 ; i < 11 ; i++)
            filesCountList.add(new SelectOption(''+i , ''+i)) ;
    }
    
    public Pagereference SaveAttachments()
    {
        String accId = System.currentPagereference().getParameters().get('id');
        if(accId == null || accId == '')
            ApexPages.addmessage(new ApexPages.message(ApexPages.Severity.ERROR,'No record is associated. Please pass record Id in parameter.'));
        if(FileCount == null || FileCount == '')
            ApexPages.addmessage(new ApexPages.message(ApexPages.Severity.ERROR,'Please select how many files you want to upload.'));

        List<Attachment> listToInsert = new List<Attachment>() ;
        
        //Attachment a = new Attachment(parentId = accid, name=myfile.name, body = myfile.body);
        for(Attachment a: allFileList)
        {
            if(a.name != '' && a.name != '' && a.body != null)
                listToInsert.add(new Attachment(parentId = accId, name = a.name, body = a.body)) ;
        }
        
        //Inserting attachments
        if(listToInsert.size() > 0)
        {
            insert listToInsert ;
            ApexPages.addmessage(new ApexPages.message(ApexPages.Severity.INFO, listToInsert.size() + ' file(s) are uploaded successfully'));
            FileCount = '' ;
        }
        else
            ApexPages.addmessage(new ApexPages.message(ApexPages.Severity.ERROR,'Please select at-least one file'));
            
        return null;
    }
    
    public PageReference ChangeCount()
    {
        allFileList.clear() ;
        //Adding multiple attachments instance
        for(Integer i = 1 ; i <= Integer.valueOf(FileCount) ; i++)
            allFileList.add(new Attachment()) ;
        return null ;
    }
}


You can enhance the code if you like, as I've provided the basic code which is re-usable. Also you can change the object passed in standard controller and code will handle the rest. URL should have ID else you will get error on UI :-)

Say, I've saved my VFP code as "MultipleUpload", so my URL will be https://...../apex/MultipleUpload?id=XXXXXXXXXXXXXXX (account id in this code).

Happy Coding.

Dec 19, 2012

Reading Visualforce Page Code In Apex

Recently faced a strange requirement to change the Visualforce page code dynamically (apologies can't disclose the complete scenario)

So would like to share the small POC with code. Code will take Visualforce Page name as parameter and will return you the code written for that VFP as text. For example, this is my Visualforce Page saved with name "VisualforceCode"


<apex:page id="PG" controller="VisualforceCodeController">
<apex:form id="FRM">
    <apex:pageMessages id="PM"/>
    <apex:pageBlock id="PB">
        
        <apex:commandLink value="See Magic" action="{!DisplayCode}" >
            <apex:param assignTo="{!CurrentPageName}" value="{!$CurrentPage.Name}"/>
        </apex:commandLink>
        
        <br/> <br/>

        <apex:outputPanel id="OPT" rendered="{!showCodeSection}">
            <apex:outputLabel value="{!PageText}"/>
        </apex:outputPanel>
    
    </apex:pageBlock>
</apex:form>
</apex:page>


Now I want to read the code written in this page, so here is the working code which send page name as parameter in "UtilClass" to get the code as text:


public class VisualforceCodeController
{
    //To display section which hold code as text of VF page
    public boolean showCodeSection {get; set;}
    
    //To hold VF Code as text
    public String PageText {get; set;}
    
    //Hold current page name
    public String CurrentPageName {get; set;}
    
    public VisualforceCodeController()
    {
        CurrentPageName = '' ;
        showCodeSection = false ;
    }
    
    public PageReference DisplayCode()
    {
        if(CurrentPageName != '')
        {
            //Fetching VF code
            PageText = UtilClass.VFPageCode(CurrentPageName) ;
            showCodeSection = true ;
        }
        return null ;
    }
}


To get the visualforce page name I've used "{!$CurrentPage.Name}" which is a global variable

Here Util Class code:


//General Class with static methods
public class UtilClass
{
    //Method will take visualforce page name as parameter and returns the code written in it
    public static String VFPageCode(String PageName)
    {
        ApexPage testPage = new ApexPage();
        String PageText = '' ;
        
        if(PageName != '')
        {
            //Fetching visualforce page code
            testPage = [Select Id, Markup from ApexPage where name =: PageName];
            PageText = testPage.markup ;
        }
        return PageText ;
    }
}

There are many other methods you can use with "ApexPage" mentioned here. So if you want to update the VFP code from apex dynamically you can use "ApexPage"

Nov 23, 2012

Page Block Table With Dynamic Columns In Salesforce

This is something extensively used, but every time I need to look for some easy code.

So here is the solution (apologies as I've not covered the negative cases in code, and I hope you all are smart enough to take care of that). Requirement is to build the dynamic page block table with dynamic columns, but this is not it. It should be so dynamic that user can select the object and it's fields by himself and nothing should be hard-coded. So first of all I've provided a picklist with all objects (not all objects... why? Take a look at it Please Remove The System Objects From My sObject List)

Visualforce Page Code:

<apex:page controller="DynamicTableController">
<apex:pageBlock >
    <apex:form >
        <apex:actionFunction name="ObjectFileds" action="{!ObjectFields}"/>
        
        <apex:commandButton  value="Show Table" action="{!ShowTable}"/>
        
        <apex:pageBlockSection >
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Select Object"/>
                <apex:selectList multiselect="false" size="1" value="{!SelectedObject}" onchange="ObjectFileds();">
                    <apex:selectOption itemLabel="--None--" itemValue="--None--"/>
                    <apex:selectoptions value="{!supportedObject}" />
                </apex:selectlist>
            </apex:pageBlockSectionItem>
            
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Select Field"/>
                <apex:selectList multiselect="true" size="5" value="{!SelectedFields}">
                    <apex:selectOption itemLabel="--None--" itemValue="--None--"/>
                    <apex:selectoptions value="{!fieldLableAPI}" />
                </apex:selectlist>
            </apex:pageBlockSectionItem>
            
            <apex:pageBlockTable rendered="{!IF(ObjectList.size > 0 , true , false)}" value="{!ObjectList}" var="rec">
                <apex:column value="{!rec.Id}" rendered="{!IF(SelectedFields.size == 0 , true, false)}"/>
                <apex:repeat value="{!SelectedFields}" var="FieldLable">
                    <apex:column value="{!rec[FieldLable]}" rendered="{!IF(FieldLable != '--None--' , true, false)}"/>
                </apex:repeat>
            </apex:pageBlockTable>
            
            <apex:outputPanel rendered="{!IF(ObjectList.size < 1 , true , false)}">
                <apex:pageMessage severity="ERROR" summary="No records to display"/>
            </apex:outputPanel>
            
        </apex:pageBlockSection>
        
    </apex:form>
</apex:pageBlock>
</apex:page>


Apex Code (Class):

public class DynamicTableController
{
    //List displayed on UI
    public List<selectoption> supportedObject {get; set;}
    
    //Selected Object
    public String SelectedObject {get; set;}
    
    //Global describe
    Map<String, Schema.SObjectType> gd = Schema.getGlobalDescribe();
    Set<String> objectKeys = gd.keySet();
    
    //Field Select List
    public List<SelectOption> fieldLableAPI {get; set;}
    
    //Selected fields to be displayed in table
    public List<String> SelectedFields {get; set;}
    
    //List to maintain dynamic query result
    public List<sObject> ObjectList {get; set;}
    
    
    //Constructor
    public DynamicTableController()
    {
        //Initialize
        supportedObject = new List<selectoption>() ;
        SelectedObject = '' ;
        fieldLableAPI = new List<SelectOption>() ;
        SelectedFields = new List<String>() ;
        ObjectList = new List<sObject>() ;
        
        //Get only reference to objects
        for(Schema.SObjectType item : ProcessInstance.TargetObjectId.getDescribe().getReferenceTo())
        {
            //Excluding custom setting objects
            if(!item.getDescribe().CustomSetting)
            {
                //Adding to list
                supportedObject.add(new SelectOption(item.getDescribe().getLocalName().toLowerCase() , item.getDescribe().getLabel() ));
            }
        }
        
    }
    
    //Get fields of selected object
    public void ObjectFields()
    {
        if(SelectedObject != '--None--')
        {
            //Creating sObject for dynamic selected object
            Schema.SObjectType systemObjectType = gd.get(SelectedObject);
            //Fetching field results
            Schema.DescribeSObjectResult r = systemObjectType.getDescribe();
                
            Map<String, Schema.SObjectField> M = r.fields.getMap();
            //Creating picklist of fields
            for(Schema.SObjectField fieldAPI : M.values())
            {
                fieldLableAPI.add(new SelectOption(fieldAPI.getDescribe().getName() , fieldAPI.getDescribe().getLabel())) ;
            }
        }
    }
    
    public void ShowTable()
    {
        //Creating dynamic query with selected field
        String myQuery = 'Select Id ' ;
        
        for(String field : SelectedFields)
        {
            if(field.toLowerCase() != 'id' && field.toLowerCase() != '--none--')
            myQuery += ','+ field + ' ' ;
        }
        
        //Limit is 100 for now you can change it according to need
        myQuery += ' from ' + SelectedObject + ' LIMIT 100' ;
        
        //Executing the query and fetching results
        ObjectList = Database.query(myQuery) ;
    }
}

Once user selects any object from the first picklist, filed picklist will be populated with all the field labels related to that object. Note, it's a multi-select picklist so user can select multiple fields. Once fields are selected and "Show Table" is clicked, page block table will display the field values (selected in field picklist) of all records (limit is 100 right now, you can change it according to your need).

There are some extra checks that needs to be implemented in code like "isQueryable" etc..

Sep 25, 2012

Creating Public Web-Service in Salesforce

We all are familiar with web services and we often use them. Now let's talk about other side of using web services by making them public so I don't need any authentication/passwords/SessionIds etc.

Recently I need to create a web service so it can used in a mobile app. Most of us know about Mobile SDK, REST, oAuth etc.. but in all I need to intake the credentials of salesforce organization to get access token or if am using web services then to get the session Id. But think about it, why end user will be concerned with the back-end/database? So all we need is a public web service which can be called to process our request.

So follow these simple steps:

1) Create a web service like this

global class DemoClass
{
    webService static string Method()
    {
        return 'DoSomething' ;
    }
}

2) Go to Site > Setup > App Setup > Develop > Sites > Select your Site > Give access of class "DemoClass" to site profile

3) Extract WSDL of your class, go to your class and then click "Generate WSDL". Now all we need to change the SOAP address.

Lets say, this is a snippet of my WSDL



Now we need to change the highlighted code like this:

This is the location:
https://ap1-api.salesforce.com/services/Soap/class/ankit/DemoClass

And our site URL is:

So our final location will be:
http://ankitarorasite-developer-edition.ap1.force.com/services/Soap/class/ankit/DemoClass

Now you can use this location in your WSDL and there will be no need of getting any access tokens or session Ids. Happy Coding.