Friday 22 August 2014

Streaming API Salesforce

The Force.com Streaming API lets you expose a near real-time stream of data from the Force.com platform. Administrators can create topics, to which applications can subscribe, receiving asynchronous notifications of changes to data in Force.com, via the Bayeux Protocol. Streaming data made simple, secure  and scalable.

Before Digging Deep into the Logic First Download the Following Zip Files and Upload them in Static Resources
There are 3 steps in creating Real Time Notifications Using Streaming API

1) Upload files in static Resources
2) Build a query of fields you want to access and create your pushtopic.
3) Write Your logic for handling the notifications received.

1) Upload files in static Resources : -

Download Below rar file, extract and Upload each file. Remember What you are naming while uploading as you need to access this files in your vf page.

Click To Download

2) Build a query of fields you want to access and create your pushtopic : -

Query

The first step in using the Streaming API is to define a SOQL query that will return the records you are interested in. For example, your application may require a notification whenever a new Account is created. A suitable query might be:
1SELECT Id, Name FROM Account
Alternatively, you might only be interested in Accounts with more than 1,000 employees:
1SELECT Id, Name FROM Account WHERE SomeField> 1000
As a special case, you can specify a record id in the WHERE clause and receive notifications whenever any change occurs on that record:
1SELECT Id, Name FROM Account WHERE Id = '001x0000002JSofAAG'
These are just some simple examples - see the Streaming API documentation for a full discussion of Streaming API queries.

PushTopic

Once you have decided on your query, it's time to create a PushTopic that binds a topic name to the query. You can set the following fields on the PushTopic record:
Field NameTypeExampleDescription
ApiVersiondouble23.0Required. API version to use for executing the query specified in Query.
DescriptionstringAll records for the Account object.Optional. Description of what kinds of records are returned by the query.
NamestringNewAccountsRequired. Descriptive name of the PushTopic. The maximum length is 25 characters.
QueryStringSELECT Id, Name FROM AccountRequired. The SOQL query statement that determines which record changes trigger events to be sent to the channel. Maximum length is 400 characters.
There are also several system fields on PushTopic such as CreatedById and SystemModstamp.
As soon as you create a PushTopic record, applications can subscribe to the topic.
Go ahead and create a topic now. Login to your Developer Edition environment, Go to Developer console and navigate to Execute Anonymous Block and copy paste below code.
 PushTopic pushTopic = new PushTopic();  
 pushTopic.Name = 'new account'; // you can specify name of your choice  
 pushTopic.Query = 'SELECT Id, Name FROM account';  
 pushTopic.ApiVersion = 31.0;  
 pushTopic.NotifyForOperationCreate = true;  
 pushTopic.NotifyForOperationUpdate = true;  
 pushTopic.NotifyForOperationUndelete = true;  
 pushTopic.NotifyForOperationDelete = true;  
 pushTopic.NotifyForFields = 'Referenced';  
 insert pushTopic;  
3) Write Your logic for handling the notifications received: -

Visual Force page Code :-
 <apex:page showHeader="false" standardController="Account" extensions="streamingcontroller" id="page" >  
 <!-- the static resource files uploaded-->  
   <apex:includeScript value="{!$Resource.cometd}"/>  
   <apex:includeScript value="{!$Resource.jquery}"/>  
   <apex:includeScript value="{!$Resource.json2}"/>  
   <apex:includeScript value="{!$Resource.jquery_cometd}"/>  
   <apex:includeScript value="/support/console/25.0/integration.js"/>  
   <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/newaccount', function(message)  
         {  
           //You can use message as it will return you many attributes  
           //I am just using to track that event is generated  
           RefreshedAccounts();  
         });  
       });  
     })(jQuery)  
   </script>  
  <apex:form id="form" style="padding:0px;margin:0px;">  
  <apex:actionFunction name="RefreshedAccounts" action="{!newaccountlist}" reRender="block">  
  </apex:actionFunction>  
   <apex:pageBlock mode="maindetail" id="block">  
    <apex:pageblockTable value="{!myaccounts}" var="a">   
    <apex:column width="50%" >  
    <apex:outputField value="{!a.name}" id="name" />  
    </apex:column>  
   </apex:pageblockTable>  
   </apex:pageBlock>  
  </apex:form>  
 </apex:page>  
Controller Code :-
 public class streamingcontroller{  
   public streamingcontroller(ApexPages.StandardController controller) {  
    storinglist = new list<account>();  
   }  
 //variables declaration  
 public list<account> storinglist{set;get;}  
   //get method of list  
   public list<account> getmyaccounts(){  
      storinglist= [select id,name from account order by id desc];  
   return storinglist;  
   }  
   public void newaccountlist(){  
   getmyaccounts();  
   }  
 }  

Hope this Helps..

Wednesday 20 August 2014

Look up field for Multiple Sobjects in VisualForce page

Hi,Have you gone through task fields ? There we will have a Single lookup field "WhoId" which works for both Contact as well as Leads. Thought of Implementing this Logic in VisualForce.Here we need two vf pages  and controllers to do so.MultipleLookup is page 1 and controller :- Parent Page lookuppage is page 2 and controller :- Child Page So lets start with parent page, In this page we will have 3 fields 1)Hidden field:- To store the Id of the record(As relationship fields need ID to save) 2)Pick List :- To store Sobjects you wish to provide 3) Input text :- To display label of record selected. Below is the Page 1 Code : -
 <apex:page controller="multiplelookup" showHeader="false">  
 <script> var newWin=null;  
 function openLookupPopupipd(name, id,val){  
 if(val.value != ''){  
         var url="/apex/lookuppage?namefield=" + name + "&idfield=" + id+"&sobject="+val.value;  
  newWin=window.open(url, 'Popup','height=700,width=1200,left=100,top=100,resizable=no,scrollbars=yes,toolbar=no,status=no');  
         if (window.focus){  
           newWin.focus();  
         }  
         return false;  
         }  
         else{  
         }  
       }   
       function closeLookupPopup(){  
         if (null!=newWin){            
         newWin.close(); }   
       }   
     </script>  
  <apex:form >  
  <apex:pageBlock >  
   <apex:pageBlockSection >  
   <apex:outputPanel >  
    <apex:inputhidden value="{!hiddenval}" id="hiddenid"/><br/>  
    <apex:outputLabel >Field</apex:outputLabel>   
    <apex:selectList size="1" value="{!selectedsobject}" label="Select Sobject"   
    onchange="openLookupPopupipd('{!$Component.labeltoshow}','{!$Component.hiddenid}',this); return false">  
    <apex:selectOptions value="{!allsobjects}"></apex:selectOptions>  
   </apex:selectList><apex:inputText value="{!showinglabel}" id="labeltoshow"></apex:inputtext>  
   </apex:outputPanel>  
   </apex:pageBlockSection>  
  </apex:pageBlock>  
  </apex:form>  
 </apex:page>  
Controller 1 Code : -
 public class multiplelookup {  
 //variable declaration  
 public string hiddenval{set;get;}  
 public string showinglabel{set;get;}  
 public string selectedsobject{set;get;}  
   //constructor  
   public multiplelookup (){  
   }  
    //method which gets list of sobjects  
   public list<SelectOption> getallsobjects(){  
   Map<String, Schema.SObjectType> demomap= Schema.getGlobalDescribe();  
   Schema.DescribeSObjectResult[] descResult =Schema.describeSObjects(new String[]{'Account','Contact','Lead','Opportunity'});  
   List<SelectOption> options = new List<SelectOption>();  
     options.add(new SelectOption('','--None--'));  
   for(integer i=0;i<=descResult.size()-1;i++){  
   DescribeSObjectResult sobjectRes = descResult[i].sObjectType.getDescribe();  
   system.debug('sobjects:::::'+sobjectRes );  
   options.add(new SelectOption(sobjectRes.getName(),sobjectRes.getName()));  
   }  
     return options;  
   }  
 }  
Now Page 1 is ready.. Now lets see What is happening on selection of Sobject from Picklist. Onselection a Javascript function named "openLookupPopupipd"  is invoked along with 3 parameters.  1)Hidden Field ID 2)InputText Field ID 3) Sobject we select from picklist. Page 2 :- Page 2 Contains list of records of sobjects we have selected from page 1. It is a Dynamic list, and gets loaded based on sobject  selected Page 2 Code: -
 <apex:page controller="lookuppage" showHeader="false">  
 <script language="javascript">  
   window.onload = new function()   
   {  // bring popup window to front  
    window.focus();   
  var ele=document.getElementById('{!$Component.form.block.section.query}');  
    if (ele)   { ele.focus();   }  }  
   function fillIn(name, id)  {    
    var winMain=window.opener;if (null==winMain)  {      
     winMain=window.parent.opener;    
     }    
      var ele=winMain.document.getElementById('{!$CurrentPage.parameters.namefield}');  
     ele.value=name;  
     ele=winMain.document.getElementById('{!$CurrentPage.parameters.idfield}');  
    ele.value=id;   
    ele.focus();  
    winMain.closeLookupPopup();  
    }  
   </script>  
 <apex:form >  
  <apex:pageBlock mode="maindetail" id="show">  
  <apex:pageMessage severity="error" summary="No Matcing Data Found" rendered="{!showerror}"></apex:pageMessage>  
   <apex:pageblocksection >  
   <apex:pageBlockTable value="{!listofrecords}" var="rec">  
    <apex:column value="{!rec.id}" rendered="{!IF(Fields.size == 0 , true, false)}"/>  
    <!--<apex:column value="{!rec.name}" /> -->  
    <apex:repeat value="{!Fields}" var="FieldLable">   
      <apex:column rendered="{!IF(FieldLable != ' ' , true, false)}" >  
       <apex:outputLink value="#" onclick="fillIn('{!rec[FieldLable]}', '{!rec.id}')" >{!rec[FieldLable]}</apex:outputLink>   
      </apex:column>   
         </apex:repeat>       
   </apex:pageBlockTable>  
   </apex:pageblocksection>   
  </apex:pageBlock>  
 </apex:form>  
 </apex:page>  
Controller 2  Code :-
 public class lookuppage {  
 public list<sobject> records{set;get;}  
 public boolean showerror{set;get;}  
 public List<string> fields{private set;get;}  
 public string selectedsobject{get;set;}   
   public lookuppage(){  
   selectedsobject = System.currentPageReference().getParameters().get('sobject');  
   if(selectedsobject == '' || selectedsobject ==null) {  
   showerror = true;  
   }  
   else{  
   showerror = false;  
   }  
   records = new list<sobject>();  
   fields = new List<string>();  
   }  
   public list<sobject> getlistofrecords(){  
    try{  
   fields = new list<string>();  
    Map<String, Schema.SObjectType> gd = Schema.getGlobalDescribe();   
    Schema.SObjectType systemObjectType = gd.get(selectedsobject);  
    Schema.DescribeSObjectResult r = systemObjectType.getDescribe();   
    Map<String, Schema.SObjectField> M = r.fields.getMap();   
      for(Schema.SObjectField s: M.values()){  
      Schema.DescribeFieldResult fieldResult = s.getDescribe();   
     if( fieldResult.getName()=='Name'){  
     fields.add(fieldResult.getName());  
     }  
      }  
      system.debug('fields::::::::::'+fields);  
      String query='select Id' ;  
      for(string field : fields){  
      if(field.toLowerCase() != 'id' )   
       query+= ','+ field + ' ' ;   
      }  
    query+= ' from ' + selectedsobject+ ' LIMIT 100' ;  
    system.debug('Query:::::::::'+query);  
    records = Database.query(query);  
     system.debug('queried records::::::::::'+records);  
     return records;  
    }  
    catch(exception e){  
    return null;  
    }  
   }  
 }