2

I am new to VisualForce and trying to understand the order of execution and came across this example in the page developer's guide where a sample page uses a custom component-

<apex:component controller="componentController1">
<apex:attribute name="value" type="String" description="Sample component."
assignTo="{!selectedValue}"/>
<p>
Value = {!value}<br/>
selectedValue = {!selectedValue}<br/>
EditMode = {!EditMode}
</p>
</apex:component>

The associated controller -

public class componentController1 {
 public String selectedValue {get;
 set {
     editMode = (value != null);
    // Side effect here - don't do this!
    selectedValue = value;
    }
   }
 public Boolean editMode {get;private set;}
}

It makes sense that the constructors on the associated controller should execute first after the constructors of the main page have been executed. In this case the implicit constructor is called so the initialised values of class variables after constructor is called would be

selectedValue = null editMode = null

Why the documentation says the following while further explaining the execution?

the value of EditMode is not yet known. EditMode is a boolean variable on the componentController. It is set based on the whether value is equal to null: set { selectedValue = value; // Side effect here - don't do this! editMode = (value != null); }

The associated component's implicit controller has already executed and the member variables selectedValue & editMode are set to null.Why the doc says the value of EditMode is not yet known? Also what is making the set accessor of selectedValue property to be called?

4

The code originally quoted is a bad example, because we do actually know what the values of selectedValue and editMode will be; with a private setter, editMode won't have a value until set by the other setter. However, consider this controller:

public class CompCont {
    public String a { get; set { a = (b == null)? 'Hello': value } }
    public String b { get; set; }
}

What will {!a} evaluate to, assuming {!a} and {!b} are both assigned a value using apex:attribute? The answer, of course, is that we don't know, because the compiler could choose to call set(b) first, which will cause 'a' to take its assigned value, while if set(a) is called first, 'a' will take on the value 'Hello' instead of the other value.

You could test this code out, and get the correct output one day, then try it two weeks later, and get the wrong output. It could even have different behavior across orgs on different servers (e.g. production versus sandbox). This is a very difficult and subtle error to try and figure out.

Here's a related question that shows why you should be careful about considering how code executes:

Controller

public class componentController1 {
    public componentController1() {
        counter = 0;
    }
    public integer counter { get; set; }
    public string b { get; set { b = value; counter++; } }
    public string a { get; set { a = value; counter++; } }
}

Component

<apex:component controller="componentController1">
    <apex:attribute assignTo="{!a}" name="valueA" description="First Part" type="String" />
    <apex:attribute assignTo="{!b}" name="valueB" description="Second Part" type="String" />
     {!a} {!b} {!counter}
</apex:component>

What will the value of counter be? Should it not be 2? After all, we perform just one assignment each to a and b, right? As it turns out, the correct answer is 4, not 2 (at least, in my org, today). Each setter is called twice in my example, even with no form elements at the page level. Later optimizations might reduce the count to 2, or increase it to 6 (or really, any value of at least 2).

Any action you perform in a getter or setter should be idempotent, meaning it must have exactly the same effect if the method is called once or a dozen times. This also usually means caching query results if you use lazy loading (e.g. this example would have cost four queries without caching, instead of two).

You should generally leave data manipulation for action methods and constructors, where you have greater control over the order that methods are called in.

  • Brian, I agree with you, they used a wrong example to quote. Naming the custom component as 'EditMode' one of the data members of the associated controller and frequently referring it in explanation. Naming the attribute of the custom component as 'Value' which is a contextual keyword used in set accessors will confuse many first time programmers. – Jarvis Mar 17 '15 at 6:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.