8

I've hacked this small example of the unexpected order based on Order of Execution for Visualforce Page Get Requests. From the linked docs (my empahsis):

  1. The constructor methods on the associated custom controller or controller extension classes are called, instantiating the controller objects.
  2. If the page contains any custom components, they are created and the constructor methods on any associated custom controllers or controller extensions are executed. If attributes are set on the custom component using expressions, the expressions are evaluated after the constructors are evaluated.
  3. The page then executes any assignTo attributes on any custom components on the page. After the assignTo methods are executed, expressions are evaluated, the action attribute on the component is evaluated, and all other method calls, such as getting or setting a property value, are made.
  4. ...

This isn't lining up with what I'm seeing in the debug logs.

6   USER_DEBUG  [4]     DEBUG   myController constructor called. Visualforce page controller
9   USER_DEBUG  [8]     DEBUG   myController actionMethod Visualforce page action method called
15  USER_DEBUG  [11]    DEBUG   componentController constructor called.
19  USER_DEBUG  [5]     DEBUG   selectedValue set in componentController
24  USER_DEBUG  [5]     DEBUG   selectedValue set in componentController

Note how the actionMethod on the parent Visualforce page is called before the component constructor and any of the custom component assignTo properties are set.

Basically, why is the page controllers action method being called immediately after the constructor and before the components are ready?

I've got components where I want to call methods on them from the controllers action method. This, of course, requires them to have been constructed first.


These are all using v36.0 from Spring '16.

Component Controller:

public class componentController {
    public String selectedValue {
        get;
        set {
            System.debug(LoggingLevel.Debug, 'selectedValue set in componentController');
            selectedValue = value;
        }
    }

    public componentController() {
        System.debug(LoggingLevel.Debug, 'componentController constructor called.');
    }
}

Component:

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

Controller:

public with sharing class myController {

    public myController() {
        System.debug(LoggingLevel.Debug, 'myController constructor called. Visualforce page controller');
    }

    public void actionMethod() {
        System.debug(LoggingLevel.Debug, 'myController actionMethod Visualforce page action method called');
    }

}

Visualforce page:

<apex:page controller="myController" action="{!actionMethod}">
    <apex:messages />
    <apex:pageBlock title="Component page block">
        <c:editMode value="{!$CurrentPage.parameters.key}"/>
    </apex:pageBlock>
</apex:page>
  • 1
    Perhaps because master page action can redirect to new page causing rendering of custom components moot? – cropredy Apr 11 '16 at 0:40
  • 1
    @cropredy I'm quietly holding out hope that someone will come back with a known issue and that this will all be resolved in a future patch. I suspect however that the problem is in the docs (or my interpretation of them) – Daniel Ballinger Apr 11 '16 at 0:48
  • 1
    @DanielBallinger I could have sworn I've answered this exact question before, but I can't seem to find it now. – sfdcfox Apr 11 '16 at 2:29
  • 1
    @sfdcfox I did see your answer for Order of execution for Visualforce page Get requests which did cover the double property calls (another oddity). But I didn't see much about the order of execution between components and the action method. – Daniel Ballinger Apr 11 '16 at 2:37
  • 1
    @DanielBallinger I can't find it right now, so either I just imagined/dreamed it, or I have too many answers on this site. I'm going to write up a formal answer for you (unless someone beats me to it), but there's two things off the top of my head: (a) when the documentation and behavior differ, the behavior is correct and the documentation is wrong, and (b) the documentation is only updated about every release, but there's usually dozens of hot-patches between releases (the "maintenance windows"), some of which can outdate the documentation. I'll see if I can figure out more. – sfdcfox Apr 11 '16 at 3:02
3

Relaying a response from Michael Alderete - Technical writer for the Salesforce docs team. Slightly modified for context.


While I believe all of the behavior you’ve described [...] is expected, I don’t think you’re misinterpreting the docs. You’ve found an area that could be documented a little more clearly.

  1. This is expected behavior. The page-level action method is called early, as a consequence of accessing the page. This is so that the page can redirect if that's desired.

The description for this attribute explains this (or, rather, tries to):

"The action method invoked when this page is requested by the server. Use expression language to reference an action method. For example, action="{!doAction}" references the doAction() method in the controller. If an action is not specified, the page loads as usual. If the action method returns null, the page simply refreshes. This method will be called before the page is rendered and allows you to optionally redirect the user to another page. This action should not be used for initialization." - Source

However, you're correct that it's not in the diagram and doc you've pointed to in your tweet. I'll create a doc bug to update it.

  1. Regarding "the double property calls (another oddity)", this is also expected. Getters and setters may be called more than once per page request. This is why we document that they should be idempotent, that is, not have side effects.

  2. Regarding timing of the doc updates, it's actually updated every week. Doc is on the same weekly patch release schedule as the app itself. It's just that there's a lot of things to work on, so there aren't changes to the Visualforce docs every week.

  • glad to see you have juice with SFDC doc team and my hypothesis was, for once, not wrong. – cropredy Apr 12 '16 at 1:48
  • @cropredy Yup, you had the right idea. The more I read that doc quote the more questions I have. Why does it refresh if a null PageReference is returned? Seems odd for a GET request. Also, the "This action should not be used for initialization" has me scratching my head, as that is often what I use it for. If I don't do the page init code in the action method, then where should I do it? – Daniel Ballinger Apr 12 '16 at 2:01
  • Daniel - you have two choices - (1) - constructor and/or (2) - make the getters handle their own initialization – cropredy Apr 12 '16 at 2:06
  • The problem with using the constructor and/or properties is that you don't know if everything else is initialized yet. This comes back to my original problem. I wan't to run code in the Page when the Components are all constructed and their properties assigned. I do have something working, but it isn't ideal. – Daniel Ballinger Apr 12 '16 at 2:18

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.