Tuesday, December 24, 2013

Delivering package for you HO HO HO

I got package for you!! Whenever I want to retrieve the code from Salesforce I seldom use Force IDE UI.I mean the one that we need to right click at Force.com -> Add/Remove Metadata Components. It slow and for unknown reason sometimes it hang my system. Other work around that I use is directly write the class,trigger or anything that I want in package file and then click Force.com ->Refresh from Server.
So here the sample of package file
<package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>MyApexClass</members>
        <name>ApexClass</name>
    </types>
    <types>
        <members>MyApexTrigger</members>
        <name>ApexTrigger</name>
    </types>
    <types>
        <members>MyCustomApplication</members>
        <name>CustomApplication</name>
    </types>
    <types>
        <members>MyCustomObject</members>
        <members>MyCustomSetting</members><!--Custom Setting inside CustomObject tag-->
        <name>CustomObject</name>
    </types>
        <types>
        <members>MyCustomObject.MyButtonName</members>
        <name>Weblink</name><!--To handle custom button -->
    </types>
    <types>
        <members>MyCustomTab</members> <!--Note -profile setting not able to be setup here-->
         <name>CustomTab</name>
    </types>
    <types>
        <members>MyStaticResource</members>
        <name>StaticResource</name>
    </types>
    <types>
        <members>Admin</members>
        <name>Profile</name>
    </types>
    <version>27.0</version>
</package>
        
Well the stuff that always give me headache previously is when I want to upload CustomSetting, it give me an error until I notice there no metadata for CustomSetting, but we can include it inside CustomObject type.


Have a nice holiday... HOHOHO...

Friday, December 20, 2013

Action function causing Object doesn't support this property or method in IE8

Anyone love IE? Ha ha ha... I don't like it because IE love to catch my code...uppss :) I have this web application that fusion of Salesforce and JQuery.It quite happy to run in Chrome and Firefox but not in Internet Explorer.It give this:
Message: Object doesn't support this property or method Line: 1934 Char: 1 Code: 0
I spend the whole day staring at my screen.The code is doing rating by change the  color  and save to database.It run in another two browsers but somehow it show error in IE bar.There two code snippets that run with same function however the first one is not hitting the error, but the second one yes.
 First code

<apex:outputpanel id="Price">
 <div id ="Price1" class="{!IF(Rating['Price Detail'].Rating_Color__c=='Yellow','light light-yellow',
     IF(Rating['Price Detail'].Rating_Color__c=='Red','light light-red',
     IF(Rating['Price Detail'].Rating_Color__c=='Green','light light-green','light light-grey')))}"  title="{!IF(Rating['Price Detail'].Rating_Color__c=='Yellow','Yellow',
     IF(Rating['Price Detail'].Rating_Color__c=='Red','Red',
     IF(Rating['Price Detail'].Rating_Color__c=='Green','Green','Grey')))}">
</div>
</apex:outputpanel>
<apex:actionfunction action="{!RatingValue}" name="Price" rerender="Price">       
 <apex:param assignto="{!ColorValue}" name="x" value=""/>
 <apex:param assignto="{!Category}" name="z" value=""/>
 <apex:param assignto="{!ChangeValue}" name="y" value="Price"/>
</apex:actionfunction>
Second code

<apex:outputpanel id="Quality1">
<div id="Quality" class="{!IF(Rating['Quality Detail'].Rating_Color__c=='Yellow','light light-yellow',
     IF(Rating['Quality Detail'].Rating_Color__c=='Red','light light-red',
     IF(Rating['Quality Detail'].Rating_Color__c=='Green','light light-green','light light-grey')))}"  title="{!IF(Rating['Quality Detail'].Rating_Color__c=='Yellow','Yellow',
     IF(Rating['Quality Detail'].Rating_Color__c=='Red','Red',
     IF(Rating['Quality Detail'].Rating_Color__c=='Green','Green','Grey')))}">
</div>
</apex:outputpanel>   
<apex:actionfunction action="{!RatingValue}" name="Quality" rerender="Quality1">       
<apex:param assignto="{!ColorValue}" name="x" value=""/>
<apex:param assignto="{!Category}" name="z" value=""/>
<apex:param assignto="{!ChangeValue}" name="y" value="Quality"/>  
</apex:actionfunction>
By glancing, you won't notice the differences.I checked all the element one by one but could not figure it out until I got hunch on the code below.Note that actionFunction name= "Quality" and  div id="Quality".I change it to different name, and the error is gone.html will generate actionFunction to javascript function, could it be the name is conflict and cause the error?So far I think that way.

<apex:actionfunction action="{!RatingValue}" name="Quality" rerender="Quality1"> <!--code detail inside--> </apex:actionfunction>

 <div id="Quality">
<!--code detail inside--> </div>
Note:Please don't hate IE, they just try to make the code clean and provide peaceful in the code.

Friday, December 13, 2013

Run Execute Anonymous in Java Script for Custom List View Button

The application is required to run in schedule.I have Schedule class and Batch class.I call Batch class inside Scheduler like this

global class MySchedulerClass implements Schedulable{
    global void execute(SchedulableContext sc) {
       MyBatchClass c = new MyBatchClass ();
       Database.executeBatch(c, 5);
      
    }
}
But during development, I didn't schedule the job.I directly run in Apex Execute Anonymous like this:

MyBatchClass c = new MyBatchClass ();
       Database.executeBatch(c, 5);
So I can see the result quicker instead of waiting the job to be run on specific time. However there some request from the user to be able to run the Batch on the 'real' time using button.So I got an idea to just apply it as the same way I run in Apex Execute Anonymous.

Requirement
Steps:
1) Go to Setup -> Create -> Object . Choose the object you want to modify.Go to Buttons,Links and Action section.Click at New Button or Link.
2)Here you see the configuration for the button.Fill in necessary data as example below.
3)At the script field put the javascript code as below.

{!REQUIRESCRIPT("/soap/ajax/29.0/connection.js")}
{!REQUIRESCRIPT("/soap/ajax/29.0/apex.js")}
 

  var scr="MyBatchClass c = new MyBatchClass (); " +
         " Database.executeBatch(c, 5); ";
  var result = sforce.apex.executeAnonymous(scr);
   alert("The Batch is Running");
Please note sforce.apex.executeAnonymous(scr); . src is variable that contain string of the Apex code that I run in Apex Execute Anonymous.

4) You're almost done.Now go to Search Layouts section.Click on Edit at Search Result.You will see Custom Buttons section, just move the button that you created to Selected Button.Then Save.

That's all you need.  Now it's done.The button should be display as requirement stated above.Dream come true, yay!!


References :  ExecuteAnonymous()

Wednesday, December 04, 2013

Wondering about @future

What a hectic day:

18:04:53.589 (1589740000)|FATAL_ERROR|System.CalloutException: Callout from triggers are currently not supported.

Actually I try to call a class (contain Http that retrieve data from external server) from trigger and retrieve the error above.

Based on googling, it said something like this : to prevent exception above we need to add @future annotation at the top of our method like below.


@future
public static void executeSearch(string criteria)  {  
        String returnStr='';
        String baseUrl =URL + '/2.0/search?format=xml&amp;';
        String[] searchArgs = new List&lt;string&gt;();
        searchArgs.add(criteria);
        String relativeUrl = String.format('criteria={0}', searchArgs);
             
        HTTPRequest request = new HTTPRequest();              
        request.setEndpoint(baseUrl + relativeUrl);
        request.setHeader('Authorization', authorizationHeader);
        request.setHeader('Content-Type', 'application/xml');
        request.setMethod('GET');
        request.setTimeout(120000);
       
        HTTP http = new HTTP();
        HTTPResponse response =  http.send(request);

         if(response.getStatusCode()!=200){
           returnStr=response.getStatusCode() +' : '+ response.getStatus();
           errorCode=response.getStatusCode();
           errorMessage=returnStr;
         }
        
        else {
          returnStr=response.getBody();
         }
        system.debug( returnStr);
    }

Or if we want it to execute callout use @future(callout=true) ,if want to prevent callout use @future(callout=false)

Why @future?
To identify methods that are executed asynchronously. When we specify future, the method executes when Salesforce has available resources.

But @future will have some limitation.It only works for static void method, it won't work if our method got return value example if I want to retrieve response string .Other work around on this is to store the return value in somewhere else that we can refer it later.

Because it depends on resource availability, I have no idea when it run.If our process contains several method that doing call out and depend on each other , we might not able to control it.In other word,the method won't get executed in the same order it is called.


More explanation from Salesforce site.Below I copy some note from the Force IDE Help for my own note.
Methods with the future annotation have the following limits:
  • No more than 10 method calls per Apex invocation
  • Salesforce also imposes a limit on the number of future method invocations: 200 method calls per full Salesforce user license, Salesforce Platform user license, or Force.com - One App user license, per 24 hours. This is an organization-wide limit. Chatter Only, Chatter customer users, Customer Portal User, and partner portal User licenses aren’t included in this limit calculation. For example, suppose your organization has three full Salesforce licenses, two Salesforce Platform licenses, and 100 Customer Portal User licenses. Your entire organization is limited to only 1,000 method calls every 24 hours, calculated as 200 * (3+2), not 200 * (3+2+100).
  • The specified parameters must be primitive data types, arrays of primitive data types, or collections of primitive data types.
  • Methods with the future annotation cannot take sObjects or objects as arguments.
  • Methods with the future annotation cannot be used in Visualforce controllers in either getMethodName or setMethodName methods, nor in the constructor.


Other references link that I've read.
http://salesforce.stackexchange.com/questions/5602/http-callout-from-triggers
http://www.sundoginteractive.com/sunblog/posts/four-gotchas-when-using-future-calls-in-apex-in-salesforce
http://boards.developerforce.com/t5/Apex-Code-Development/Synchronous-callout-in-trigger/td-p/271947

Well,maybe instead of using trigger, I will  use Scheduler and Batch.

Thursday, November 21, 2013

Screaming for XMLStreamReader!!

I am studying on how to extract data from xml file.Actually I need to learn it for my project requirement.So I googling around and found these nice links.

http://salesforceapexcodecorner.blogspot.com

http://blogs.developerforce.com

http://it.toolbox.com/

Some of it using XMLStreamReader and some using XMLNode.But I choose to use XMLStreamReader.Why? I think it enough for my project requirement and for this time being I am
able to understand XMLStreamReader better.

If you refer to links above, most of it giving simple XML which only contain one element.During my self study, I am trying to read XML file whereby the element contains sub elements such as below


<user xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<id>2262</id>
  <displayname>Unidha</displayname>
<email>unidha@yahoo.com</email>
<usergroups>
 <usergroup><id>301</id><name>Administrators</name></usergroup> <usergroup><id>302</id><name>Sales</name></usergroup>
</usergroups>
<city>Cybercity</city></user>
Notice that beside <Id>2262</Id> ,there Id for UserGroups which are 301 and 302.Now I am going to read the Id without get confuse which one is User id and which one is Group Id.The code below is wrote based on article in link I mentioned above.
public class MyXmlStreamReader {

   //object that hold information on transaction,user etc.
     class Employee{
        
        private List&lt;String&gt; GroupId{get;set;} //one user might have multiple group being assigned
        private Boolean autoProvision{get;set;}
        private Id userId{get;set;}
        private String email{get;set;}
        private String displayName{get;set;}
        private String city{get;set;}
      
   
    }
  
  public void test() {
     String str = '<user xmlns:i="http://www.w3.org/2001/XMLSchema-instance">'
                   +'<id>2262</id>'
                   +'<displayname>Unidha</displayname>'
                   +'<email>unidha@yahoo.com</email>'
                   +'<usergroups>'
                   +'<usergroup><id>301</id><name>Administrators</name></usergroup>'
                   +'<usergroup><id>302</id><name>Sales</name></usergroup>'
                   +'</usergroups>'
                   +'<city>Cybercity</city></user>';
                   

     
     XmlStreamReader xsr = new XmlStreamReader(str);
      
     readResponse(xsr);
        
        }


   public void readResponse(XmlStreamReader reader) {
   
   
    boolean isFlag=false;
    Employee   empRecord= new Employee ();
    empRecord.GroupId=new List&lt;String&gt;();
   
   while (reader.hasNext()) { 
       
        if (reader.getEventType() == XmlTag.START_ELEMENT) { 
           if ('Id' == reader.getLocalName()) {
              String strId= getValueFromTag(reader);
                          
              if(isFlag){
                 empRecord.GroupId.add(strId);
              }
             
            }
            else if ('DisplayName' == reader.getLocalName()) {
                empRecord.displayName= getValueFromTag(reader);
          
            }
             else if ('Email' == reader.getLocalName()) {
                empRecord.email= getValueFromTag(reader);
                
            }
           else if('UserGroups' == reader.getLocalName()) {
                isFlag=true;
            }      
            else if('City' == reader.getLocalName()) {
                empRecord.city= getValueFromTag(reader);
            }       
                
           }
          else if (reader.getEventType() == XmlTag.END_ELEMENT){
             if('UserGroups' == reader.getLocalName()){
                 isFlag=false;
             }
            }
      reader.next();
            
            
            }//end of while
     
      }
      
      }//end of class
Now, watch closely at isFlag variable.I use this boolean to indicate when the Id is UserId and when it is become the GroupId.

That's it.My problem is solved for this time being.Let's drink some coffeee with cinnamon roll.Yum yum!

Monday, November 18, 2013

Getting value from Custom Setting

I figured out how to getting value from custom setting. I know, I am too slow! :) .

The purpose of custom setting can be read here.But my purpose is to store the Application configuration such as Key.In java , maybe I will store


I create Custom Setting with details value:

Label : Application Config
Object Name: Application_Config__c 
Setting Type : List  [Please go to here for more knowledge on List/Hierarchy differences]
Visibility:Protected [I choose it by default]

Once created, you will able to create custom fields.Last time I tried to create Name field without realize Name is default field.

For this , I create one field named Value with API name Value__c .

I inserted the data with Name : App_Name and Value__c : Health Monitoring .

I just test in Apex Execute :

String str1=Application_Config__c.getValues('App_Name').Value__c;
system.debug('unid -'+str1);

So that is how we can call custom setting value.

Thanks.


Tuesday, October 29, 2013

Looping Map in Apex Salesforce

How to loop map?Use values().It is quite useful if the map contain object where we need to get the object property.



Map<String,String> mapStr = new Map<String,String>();

mapStr.put('A','angsa');
mapStr.put('B','beruk');
mapStr.put('C','cicak');
system.debug('@mapStr ======'+mapStr);
for(String s:mapStr.values()){
    system.debug('@'+ s);
}
The output :
DEBUG|@mapStr ======{A=angsa, B=beruk, C=cicak}
DEBUG|@angsa
DEBUG|@beruk
DEBUG|@cicak

Thursday, October 03, 2013

Escape from Single Quote

Everytime I need to do soql statement I have to googling around.I keep forgeting.

Okay, I copy this from salesforce link here.
SequenceMeaning
\n or \NNew line
\r or \RCarriage return
\t or \TTab
\b or \BBell
\f or \FForm feed
\"One double-quote character
\'One single-quote character
\\Backslash
LIKE expression only: \_Matches a single underscore character ( _ )
LIKE expression only:\%Matches a single percent sign character ( % )


This is how I run query using escape for single in Force Explorer.
select Id,Name from Country where Name in('COTE D\'IVOIRE','CURACAO','KAZAKHSTAN',
'LAO PEOPLE\'S DEMOCRATIC REPUBLIC','LIBYAN ARAB JAMAHIRIYA','MACAO')
order by Name
Done.:)

Friday, August 23, 2013

About sharing that I misunderstood

Sharing means caring literally.In salesforces, with sharing means I want to share based on the rules.

By default, Apex class does not effected by  current user's permissions, field-level security, and sharing rules.Because it run in system context.Oh,please note this is not include Apex code that run in Execute Anonymous.Code in Execute Anonymous still effected by permission of the current user.

So this is the reason why with sharing and without sharing keywords come for.But only to control sharing rules.

Use with sharing to enforce the sharing rules that apply to the current user.

Use without sharing  to ensure that the sharing rules for the current user are not enforced.

How about if the class use neither with sharing or without sharing? Still the current sharing rules remain in effect.

All the details can be check at Using the with sharing or without sharing Keywords .

Actually why suddenly I babbling about sharing?Because it cause me headache  for almost whole day.

I got this one line of code in one Apex class

 
for (AggregateResult ar : [Select Name, max(Employee) Emp, Account__r.Name AccName  
      from Location__c  Where Account__c != null and Status__c = 'Approved' 
       group by Name,Account__r.Name order by Name])
{
  system.debug('@MYTEST Name=' +(String)ar.get('Name')+' , Account Name ='+(String)ar.get('AccName'));
}


The issue that I face, when ever I run my application the Account Name returning null value while actually I knew it should return some value.

I run the query in Workbench , it 's returning the data.I run in Developer console, it also returning data.But when I try to execute it from UI,the value not coming out in Monitoring Debug log.

I never thought the issue is caused by this sharing stuff.After struggling whole day, I discussed with my colleague and she suggesting to remove with sharing  keyword from the class.

After I have done that, my problem puff away.The value printing as usual.Now I can see that with sharing is not mean sharing is caring or you can share the data to everyone.It means, the sharing will be restricted or  can say that actually I can put it if I want to share certain data only.

Use with sharing when you only want to share certain thing.If you want to share it to all,do not use with sharing.

Tuesday, July 23, 2013

Salesforce Actionstatus with JQuery Dialog box


I have a page which contains apex:component, custom (dynamic) tab in apex:page.The design is like this,each tab represent the category and each category have 3 text area.The tab is created in page level while the text areas is inside component level.Once the user navigate into different tab, the component will re render the text area for the related category.

The user reported that whenever they update the textarea and quickly move to the different textarea or navigate into other tab, the data won't update correctly.I am thinking maybe because I use  actionSupport for every text area that calling the same method in Apex Controller which will update all the three text areas together.

The quick workaround that I can think is to disable user to move or enter  new data before system complete processing the previous data.So I need to have something like indicator or progress bar like the one that I used to see in other applications.I need to use ActionStatus but it will be cooler if I combine it with jQuery.

After I bumped into here and here.I come out with this.

1) The style to hide the dialog box's close button ,because it ugly to show the progressing icon with the Close 'X',and I don't want user to close it manually.
<!--This will remove the Close button inProgress dialog-->
 <style>
.ui-dialog-titlebar-close{
    display: none;
}
</style>
2)Define jquery dialog box
$(document).ready(function () {
$( "#dialog-modal" ).dialog({
        autoOpen: false,
        height: 150,
        width: 400,
        modal: true,
        resizable: false,
        draggable: false
        });
});

3)Create html div , put the image that I created from the
<div id="dialog_modal">
<div align="center">
<img src="{!$Resource.ProgressCircular}" />
            </div>
</div>

4)Create java script function to show and hide the dialog
function statusShow() {
$( "#dialog-modal" ).dialog( "open" );
}
function statusHide() {
$( "#dialog-modal" ).dialog( "close" );
}
5)ActionStatus
<apex:actionstatus id="inProgress" onstart="statusShow();" onstop="statusHide();">
</apex:actionstatus>

6)The fields and actionSupport that call the ActionStatus
 <apex:repeat value="{!myFields}" var="c">
       <div class="col">
<apex:inputtextarea value="{!c.Name}">
        <apex:actionsupport action="{!updateData}" event="onchange" rerender="dummy" status="inProgress">
       </apex:actionsupport></apex:inputtextarea>
       </div>
<div class="col">
<apex:inputtextarea value="{!c.Age}"> 
          <apex:actionsupport action="{!updateData}" event="onchange" rerender="dummy" status="inProgress">
          </apex:actionsupport></apex:inputtextarea>
          </div>
<div class="col">
<apex:inputtextarea value="{!c.Position}"> 
         <apex:actionsupport action="{!updateData}" event="onchange" rerender="dummy" status="inProgress">
         </apex:actionsupport></apex:inputtextarea>
        </div>
</apex:repeat>


Congratulations to me it works but after testing, I figured out something weird.When I first time load the page, update the text area ,the dialog box able to close automatically.But after I click into different tab, update the text area,the dialog box popup and it never close forever.It keep hanging there.I am not sure why at the first load it works, but after I navigate through the tabs it wont work.
I was running out of idea, I moved the code here and there, put at page level ,move back to the component level.I put alert inside statusHide() and the alert come out but I noticed it could not read this
$( "#dialog-modal" ).dialog( "close" );

I don't get any solid rules why,because it works initially after the page loading but suddenly not working if I navigate into different tab and update the field from there.I googling here and there but still zero result.At last maybe because of too much reading, I see various kind of code posted in internet and come out with something like this. Instead of calling using id, I declare and call it as variable.
var dialog_modal= $( '#dialog_modal' ).dialog({
        autoOpen: false,
        height: 150,
        width: 400,
        modal: true,
        resizable: false,
        draggable: false
});


function statusShow() {
$(dialog_modal).dialog('open');
}

function statusHide() {
 $(dialog_modal).dialog('close');
}
It WORKS and I have no idea why it works??? Happy and confuse with the solution.I am using jquery 1.7.1 ... is it related?No idea :)

EDITED:For better code put style="display: none;" in dialog_modal div.

Saturday, June 29, 2013

Generate JSON in Salesforce

I explore about JSON for generating pie chart in the site.I try this simple one, with hardcoded data.

Requirement:
1)Apex Controller to prepare the data
2)Visual force page to display the data in JSON

1) Apex controller
public class PieController {

     public String jsonString {get;set;}
    
    //Constructor
    public PieController ()
    {
      jsonString = prepareData();

    } 
  
    //Temp Method to prepare the Data
     private String prepareData()
    {
       List&lt;CompanyDetail &gt; dtlObj = new List&lt;CompanyDetail &gt;();
       CompanyDetail c1 =new CompanyDetail('1','Samson',30);
       CompanyDetail c2=new CompanyDetail('2','Targus',35);
       CompanyDetail c3=new CompanyDetail('3','Swan',60);
       CompanyDetail c4=new CompanyDetail('4', 'Filla',30);
       
        dtlObj.add(c1);
        dtlObj.add(c2);
        dtlObj.add(c3);
        dtlObj.add(c4);
            
        return JSON.serialize(dtlObj);
    }
     public class CompanyDetail {
     
       public String Name {get;set;}
       public Decimal share {get;set;}
       public String Id {get;set;}
       
       public CompanyDetail(String id,String Name,Decimal share){
           this.Name=name;
           this.Id=id;
           this.share=share;
       }
     
     }
 }

2) Visual force page
<apex:page contenttype="application/x-JavaScript; charset=utf-8" controller="PieController" showheader="false" sidebar="false" standardstylesheets="false">

  {!jsonString}

</apex:page>
Finally the output,this is how the JSON page will look like

[{"share":30,"Name":"Samson","Id":"1"},{"share":35,"Name":"Targus","Id":"2"},{"share":60,"Name":"Swan","Id":"3"},{"share":30,"Name":"Filla","Id":"4"}]