Visual force Order of Execution:
Order of Execution for Visualforce Page Get Requests
A get request is an initial request for a page either made when a user enters an URL or when a link or button is clicked that takes the user to a new page. The following diagram shows how a Visualforce page interacts with a controller extension or a custom controller class during a get request:
In the diagram above the user initially requests a page, either by entering a URL or clicking a link or button. This initial page request is called the get request.
- The constructor methods on the associated custom controller or controller extension classes are called, instantiating the controller objects.
- 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.
- 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 <apex:page> component is evaluated, and all other method calls, such as getting or setting a property value, are made.
- If the page contains an <apex:form> component, all of the information necessary to maintain the state of the database between page requests is saved as an encrypted view state. The view state is updated whenever the page is updated.
- The resulting HTML is sent to the browser. If there are any client-side technologies on the page, such as JavaScript, the browser executes them.
As the user interacts with the page, the page contacts the controller objects as required to execute action, getter, and setter methods.
Once a new get request is made by the user, the view state and controller objects are deleted.
If the user interaction requires a page update, such as when the user clicks a Save button that triggers a save action, a postback request is made. For more information on postback requests, see Order of Execution for Visualforce Page Postback Requests.
Order of Execution for Visualforce Page Postback Requests
A postback request is made when user interaction requires a page update, such as when a user clicks on a Save button and triggers a save action. The following diagram shows how a Visualforce page interacts with a controller extension or a custom controller class during a postback request:
- During a postback request, the view state is decoded and used as the basis for updating the values on the page.
- After the view state is decoded, expressions are evaluated and set methods on the controller and any controller extensions, including set methods in controllers defined for custom components, are executed.These method calls do not update the data unless all methods are executed successfully. For example, if one of the methods updates a property and the update is not valid due to validation rules or an incorrect data type, the data is not updated and the page redisplays with the appropriate error messages.
- The action that triggered the postback request is executed. If that action completes successfully, the data is updated. If the postback request returns the user to the same page, the view state is updated.
- The resulting HTML is sent to the browser.
If the postback request indicates a page redirect and the redirect is to a page that uses the same controller and a proper subset of controller extensions of the originating page, a postback request is executed for that page. Otherwise, a get request is executed for the page. If the postback request contains an <apex:form> component, only the ID query parameter on a postback request is returned.
Once the user is redirected to another page, the view state and controller objects are deleted.
Examples of Visualforce Page Execution Order
The following examples illustrate the lifecycle of a Visualforce page as a user interacts with it. The page used in the examples is designed to show information about an account, the value of the variables on the page, and allows the user to edit details of the account if the key value is set to anything except false.
To set up the Visualforce page for the examples:
- Create a controller for a custom component called componentController:
01
public
class
componentController {
02
public
String
selectedValue {
03
get
;
04
set {
05
editMode = (value !=
null
);
06
// Side effect here - don't do this!
07
selectedValue = value;
08
}
09
}
10
public
Boolean editMode {
get
;
private
set;}
11
}
- Create a custom component called editMode:
1
<apex:component
controller=
"componentController"
>
2
<apex:attribute
name=
"value"
type=
"String"
description=
"Sample component."
3
assignTo=
"{!selectedValue}"
/
>
4
<p>
5
Value
=
{!value}<br/
>
6
selectedValue
=
{!selectedValue}<br/
>
7
EditMode
=
{!EditMode}
8
</p>
9
</apex:component
>
- Create a custom controller called myController:
01
public
with sharing
class
myController {
02
03
private
final
Account account;
04
05
public
myController() {
06
account = [
select
id, name, site, NumberOfEmployees, Industry
from
Account
07
where
id = :ApexPages.currentPage().getParameters().
get
(
'id'
)];
08
}
09
10
public
Account getAccount() {
11
return
account;
12
}
13
14
public
PageReference save() {
15
update
account;
16
return
null
;
17
}
18
19
public
PageReference cancel() {
20
return
null
;
21
}
22
}
- Create a controller extension called lifecycle:
01
public
with sharing
class
lifecycle {
02
03
private
final
Account acct;
04
Integer EmpAdd;
05
06
public
lifecycle(myController controller) {
07
this
.acct = (Account)controller.getAccount();
08
}
09
10
public
String
getGreeting() {
11
return
acct.name +
' Current Information'
;
12
}
13
14
public
void
resetEmp() {
15
acct.numberofemployees =
10
;
16
update
acct;
17
}
18
}
- Create a page called setEmps:
01
<apex:page
controller=
"myController"
tabStyle=
"Account"
extensions=
"lifecycle"
action=
"{!resetEmp}"
>
02
<apex:messages
/
>
03
<apex:pageBlock
title=
"{!greeting}"
>
04
<apex:outputLabel
value=
"{!$ObjectType.account.fields.Name.label}: "
05
for=
"acctName"
/
>
06
<apex:outputField
value=
"{!account.name}"
id=
"acctName"
/
>
07
<br/
>
08
<apex:outputLabel
09
value=
"{!$ObjectType.account.fields.NumberOfEmployees.label}: "
10
for=
"emps"
/
>
11
<apex:outputField
value=
"{!account.NumberOfEmployees}"
id=
"emps"
/
>
12
<br/
>
13
</apex:pageBlock
>
14
<apex:pageBlock
title=
"Variable values"
>
15
<
c:editMode
value=
"{!$CurrentPage.parameters.key}"
/
>
16
</apex:pageBlock
>
17
<apex:form
rendered=
"{!$CurrentPage.parameters.key = 'true'}"
>
18
<apex:pageBlock
title=
"Update the Account"
id=
"thePageBlock"
>
19
<apex:pageBlockSection
columns=
"1"
>
20
<apex:inputField
id=
"aName"
value=
"{!account.name}"
/
>
21
<apex:inputField
value=
"{!account.NumberOfEmployees}"
/
>
22
<apex:pageBlockSectionItem
>
23
<apex:outputLabel
value=
"{!$ObjectType.account.fields.Industry.label}"
24
for=
"acctIndustry"
/
>
25
<apex:actionRegion
>
26
<apex:inputField
value=
"{!account.Industry}"
id=
"acctIndustry"
>
27
<apex:actionSupport
event=
"onchange"
rerender=
"thePageBlock"
28
status=
"status"
/
>
29
</apex:inputField
>
30
</apex:actionRegion
>
31
</apex:pageBlockSectionItem
>
32
</apex:pageBlockSection
>
33
<apex:pageBlockButtons
location=
"bottom"
>
34
<apex:commandButton
action=
"{!save}"
value=
"Save"
/
>
35
<apex:commandButton
action=
"{!cancel}"
value=
"Cancel"
immediate=
"true"
/
>
36
</apex:pageBlockButtons
>
37
</apex:pageBlock
>
38
</apex:form
>
39
</apex:page
>
Get Request Example One
For the first example, visit the setEmps page using a URL of the form https://Salesforce_instance/apex/setEmps?id=recordId, where Salesforce_instance is the name of your instance (for example, na1) and recordID is the ID of an account record in your organization (for example, 001D000000IRt53). You'll see a page with content similar to the following:
Let's trace the lifecycle to see why the page displays what it does. Since you've requested the page directly by entering a URL, this page is the result of a get request, not a postback request.
- The first thing that happens in a get request is that constructor methods on the custom controller and controller extension are called. The myController method is the constructor on the controller and the lifecycle method is the constructor on the extension. Those are executed and the two objects now exist. The controller now has a variable, called account, that is the result of a query that uses the id parameter from the URL, to identify which account object to query. The extension now has a variable, called acct, that is created by calling the getAccount method on the controller. The getAccount method has no side-effects.
- The next step in a get request is to create the custom components and execute constructor methods on associated controllers or controller extensions. The page includes one custom component:
1
<
c:editMode
value=
"{!$CurrentPage.parameters.key}"
/
>
This custom component has an associated controller, but the controller has no explicit constructor. As with all Apex objects without explicit constructors, the object is created using an implicit, no-argument, public constructor. As part of creating the custom component, the value attribute on the custom component is set. In this case, it is equal to the result of the expression {!$CurrentPage.parameters.key}. Since we did not specify the key attribute in the URL, value is set to null. - After custom components are created, all assignTo attributes on those custom components are executed. An assignToattribute is a setter method that assigns the value of this attribute to a class variable in the associated custom component controller. The editMode custom component does have an assignTo method, so it is executed. The assignTomethod sets selectedValue on the attribute to the value attribute. The value attribute is set to null, so selectedValue is set to null.
- The next step in a get request is evaluation of the action attribute on the <apex:page> component , expressions, and the required getter and setter methods. Although we'll step through these below, remember that the order of these evaluations is indeterminate and may be different than the following:
- The <apex:page> component has an action attribute which calls the resetEmp method on the extension. That method sets the numberofemployees field on the acct object to 10.
- There are several expressions that evaluate on the page. Let's focus on three:
- <apex:pageBlock title="{!greeting}">The title attribute on <apex:pageblock> calls the getter method on the lifecycle extension getGreeting. This is rendered on the page as “Global Media Current Information.”
- <apex:form rendered="{!$CurrentPage.parameters.key = 'true'}">The rendered attribute on <apex:form> is set based on the value of the key parameter. We did not set key when calling the page, so the form is not rendered.
- Value = {!value}<br/> selectedValue = {!selectedValue}<br/> EditMode = {!EditMode}This expression occurs in the custom component. We've already discussed that value and selectedValue are set to null, however, 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:
1
set {
2
selectedValue = value;
3
// Side effect here - don't do this!
4
editMode = (value !=
null
);
5
}
Since value is null, EditMode is set to false. Note, however, that there is a side-effect in the setter method for EditMode. As part of setting editMode, we also setselectedValue to value. Since value is null, this doesn't change anything, but this behavior has an impact in a later example.
- <apex:pageBlock title="{!greeting}">
- The other expressions and methods are evaluated in a similar manner.
- Since the <apex:form> component isn't rendered, the view state isn't created.
- The last step in the get request is to send the HTML to the browser, which renders the HTML.
Get Request Example Two
For the second example, visit the setEmps page using a URL of the form https://Salesforce_instance/apex/setEmps?id=recordId&key=false, where Salesforce_instance is the name of your instance (for example, na1) and recordID is the ID of an account record in your organization (for example, 001D000000IRt53). Unlike the first example, this example includes a second parameter, key=false. You'll see a page with content similar to the following:
Let's trace the lifecycle again. This page is also the result of a get request:
- The first thing that happens in a get request is that constructor methods on the custom controller and controller extension are called. The myController method is the constructor on the controller and the lifecycle method is the constructor on the extension. These are executed and the two objects now exist. The controller now has a variable, called account, that is the result of a query that uses the id parameter from the URL to identify which account record to query. The extension now has a variable, called acct, that is created by calling the getAccount method on the controller.
- The next step in a get request is to create the custom components and execute constructor methods on associated controllers or controller extensions. The page includes one custom component:
1
<
c:editMode
value=
"{!$CurrentPage.parameters.key}"
/
>
This custom component has an associated controller without a constructor, so the controller object is created using an implicit, no-argument, public constructor. As part of creating the custom component, the value attribute on the custom component is set. In this case, it is equal to the result of the expression {!$CurrentPage.parameters.key}. We specified the key attribute as false, so value is set to false. - After custom components are created, all assignTo attributes on those custom components are executed. The assignTo method sets selectedValue on the attribute to the value attribute. The value attribute is set to false, so selectedValue is set to false.
- The next step in a get request is evaluation of the action attribute on the <apex:page> component , expressions, and the required getter and setter methods. Although we'll step through these below, remember that the order of these evaluations is indeterminate and may be different than the following:
- The <apex:page> component has an action attribute which calls the resetEmp method on the extension. That method sets the numberofemployees field on the acct object to 10.
- Of the expressions on the page, let's see how our chosen three are evaluated:
- <apex:pageBlock title="{!greeting}">
- The title attribute on <apex:pageblock> calls the getter method on the lifecycle extension getGreeting. It is rendered on the page as “Global Media Current Information.”
- <apex:form rendered="{!$CurrentPage.parameters.key = 'true'}">
- The rendered attribute on <apex:form> is set based on the value of the key parameter. We set key to false when calling the page, so the form is not rendered.
- Value = {!value}<br/> selectedValue = {!selectedValue}<br/> EditMode = {!EditMode}
- This expression occurs in the custom component. Since value is not null, EditMode is set to true. At this point, selectedValue is set to null. Remember, however, that the setter method for EditMode has a side-effect. In this case, the side-effect sets selectedValue to the value attribute on the custom component. Since value is set to false, selectedValue is set to false. This illustrates why you should not use side-effects in your methods. If the evaluation order were different, and the value for selectedValue were determined before the setter for EditModewas evaluated, selectedValue would still be null. Execution order is not guaranteed, and the result for selectedValue could change the next time this page is visited.
- Since the <apex:form> component isn't rendered, the view state isn't created
- The last step in the get request is to send the HTML to the browser, which renders the HTML.
Get Request Example Three
For the third example, visit the setEmps page using a URL of the form https://Salesforce_instance/apex/setEmps?id=recordId&key=true, where Salesforce_instance is the name of your instance (for example, na1) and recordID is the ID of an account record in your organization (for example, 001D000000IRt53). Unlike the second example, this example sets key=true. You'll see a page with content similar to the following:
Let's trace the get request lifecycle one more time:
- The first thing that happens in a get request is that constructor methods on the custom controller and controller extension are called. The myController method is the constructor on the controller and the lifecycle method is the constructor on the extension. These are executed and the two objects now exist. The controller now has a variable, called account, that is the result of a query that uses the id parameter from the URL to identify which account record to query. The extension now has a variable, called acct, that is created by calling the getAccount method on the controller.
- The next step in a get request is to create the custom components and execute constructor methods on associated controllers or controller extensions. The page includes one custom component:
1
<
c:editMode
value=
"{!$CurrentPage.parameters.key}"
/
>
This custom component has an associated controller without a constructor, so the controller object is created using an implicit, no-argument, public constructor. As part of creating the custom component, the value attribute on the custom component is set. In this case, it is equal to the result of the expression {!$CurrentPage.parameters.key}. We specified the key attribute as true, so value is set to true. - After custom components are created, all assignTo attributes on those custom components are executed. The assignTo method sets selectedValue on the attribute to the value attribute. The value attribute is set to true, so selectedValue is set to true.
- The next step in a get request is evaluation of the action attribute on the <apex:page> component, expressions, and the required getter and setter methods. Although we'll step through these below, remember that the order of these evaluations is indeterminate and may be different than the following:
- The <apex:page> component has an action attribute which calls the resetEmp method on the extension. That method sets the numberofemployees field on the acct object to 10.
- Of the expressions on the page, let's see how our chosen three are evaluated:
- <apex:pageBlock title="{!greeting}">
- The title attribute on <apex:pageblock> calls the getter method on the lifecycle extension getGreeting. It is rendered on the page as “Global Media Current Information.”
- <apex:form rendered="{!$CurrentPage.parameters.key = 'true'}">
- The rendered attribute on <apex:form> is set based on the value of the key parameter. We set key to true when calling the page, so the form is rendered.
- Value = {!value}<br/> selectedValue = {!selectedValue}<br/> EditMode = {!EditMode}
- This expression occurs in the custom component. Since value is not null, EditMode is set to true. As in the previous example, selectedValue is set to null. The side-effect in the setter method for EditMode sets selectedValue to true.
- Since the <apex:form> component is rendered, the view state is created.
- The last step in the get request is to send the HTML to the browser, which renders the HTML.
Postback Request Example
Unlike the first two examples, the third example rendered a final page with editable fields clickable buttons. To understand how a postback request works, use the final page in Example 3 to change the account name to “Pan Galactic Media,” the employee count to 42,” and the industry to “Other.” Then click Save. This initiates a postback request:
- The first thing that happens in a postback request is that the view state is decoded. The view state contains all the information required to render the page. If, during the postback request, an operation fails, the view state is used to display the page to the user.
- Next, all expressions are evaluated and methods on controllers and controller extensions are executed.Of the expressions on the page, let's see how our chosen three are evaluated:
- <apex:pageBlock title="{!greeting}">
- The title attribute on <apex:pageblock> calls the getter method on the lifecycle extension getGreeting. In our edit, we changed the value of the Account name. Thus, the value of greeting changes to “Pan Galactic Media Current Information.”
- <apex:form rendered="{!$CurrentPage.parameters.key = 'true'}">
- The rendered attribute on <apex:form> is set based on the value of the key parameter. We have not changed the keyparameter, so the value in the view state is used. Since the value was true when the view state was created, it is still true and the form is rendered.
- Value = {!value}<br/> selectedValue = {!selectedValue}<br/> EditMode = {!EditMode}
- We have not changed any of these values, so, for each expression, the value in the view state is used.
- Lastly, the save action, the action that triggered the postback request, is evaluated. The save action is the following method on the controller:
1
public
PageReference save() {
2
update
account;
3
return
null
;
4
}
This method updates the record with the new data. If this method fails, which it might do if the user does not have permission to update the record, or if there are validation rules that are triggered by the change, the page is displayed along with error messages describing the error. The values the user entered are not lost. They remain as they were when the user clicked the Save button. Assuming there are no errors, the data on the object is updated, the view state is updated, and, since the action that triggered the postback did not include a page redirect, the view state is updated. The resulting HTML is sent to the browser:
No comments:
Post a Comment