+ Start a Discussion
NaishadhNaishadh 

Strange behavior of apex:attribute : calling setter twice

Hi,

 

I have found some strange behavior of apex attribute component.  Whenever I load the page it calls component setter method twice. I don't know why. Please suggest.

 

Component

 

<apex:component controller="sampleCon1"> <apex:attribute id="compKey" name="componentKey" description="component key" assignTo="{!componentKey}" type="String"/> </apex:component>

 Page

 

<apex:page > <c:reloadtestcomponent componentKey="CC-006"></c:reloadtestcomponent> </apex:page>

 class

 

 

public with sharing class sampleCon1 { private String componentKey; public String getComponentKey() { System.debug('Inside Component Key : -' + componentKey); return componentKey; } public void setComponentKey(String key) { componentKey = key; System.debug('Inside Set Component Key : -' + componentKey); } public sampleCon1() { System.debug('Inside Contructor'); } }

 

 

 output

15:46:30 DEBUG - ***Begining Page Log for /apex/reloadTestComponentPage 20100118101630.551:Class.sampleCon1.<init>: line 16, column 3: Inside Contructor 20100118101630.551:External entry point: returning from end of method public sampleCon1<Constructor>() in 0 ms 20100118101630.551:Class.sampleCon1.setComponentKey: line 12, column 3: Inside Set Component Key : -CC-006 20100118101630.551:External entry point: returning from end of method public void setComponentKey(String) in 0 ms 20100118101630.551:Class.sampleCon1.setComponentKey: line 12, column 3: Inside Set Component Key : -CC-006 20100118101630.551:External entry point: returning from end of method public void setComponentKey(String) in 0 ms Cumulative profiling information: No profiling information for SOQL operations. No profiling information for SOSL operations. No profiling information for DML operations. 2 most expensive method invocations: Class.sampleCon1: line 10, column 14: public void setComponentKey(String): executed 2 times in 0 ms Class.sampleCon1: line 15, column 9: public sampleCon1<Constructor>(): executed 1 time in 0 ms ***Ending Page Log for /apex/reloadTestComponentPage

 

 

Best Answer chosen by Admin (Salesforce Developers) 
bob_buzzardbob_buzzard

I usually have another property in the controller that I use to determine if I have already done the work for the getter/setter.

 

Here's an example from one of my projects:

 

 

private boolean eventIdSet=false;

public void setEventId(String theId)
{
// only do this once
if (!eventIdSet)
{
if ( (theId!=null) && (theId.length()>0) )
{
List<DiaryEvent> events=[select id, Start_Date_Time__c, End_Date_Time__c
from Diary_Event__c where id=:theId];

if (events.size()>0)
{
// do more stuff
}
}
eventIdSet=true;
}
}

 

 

 

Message Edited by bob_buzzard on 01-18-2010 03:45 AM

All Answers

bob_buzzardbob_buzzard

Yep.  This is documented on Page 161 of the Winter 10 VisualForce Developer's Guide, reproduced below:

 

Methods may evaluate more than once — do not use side-effects

Methods, including methods in a controller, action attributes, and expressions, may be called more than once. Do not

depend on evaluation order or side-effects when creating custom methods in a controller or controller extension. 

 

Is this giving you a particular problem?

NaishadhNaishadh

Actually, I want to store user preference on the basis of user choice. So that when next time user visit that component he will find the same preference.  

 

Now due to this code is calling soql query twice and also creating problem while storing the user preference. Is there any other way to store user preference please suggest! 

bob_buzzardbob_buzzard

I usually have another property in the controller that I use to determine if I have already done the work for the getter/setter.

 

Here's an example from one of my projects:

 

 

private boolean eventIdSet=false;

public void setEventId(String theId)
{
// only do this once
if (!eventIdSet)
{
if ( (theId!=null) && (theId.length()>0) )
{
List<DiaryEvent> events=[select id, Start_Date_Time__c, End_Date_Time__c
from Diary_Event__c where id=:theId];

if (events.size()>0)
{
// do more stuff
}
}
eventIdSet=true;
}
}

 

 

 

Message Edited by bob_buzzard on 01-18-2010 03:45 AM
This was selected as the best answer
NaishadhNaishadh
thanks! It works!
ShambolicRuseShambolicRuse

Can someone explain why a method may be evaluated twice? How does that happen?