5

I'm working on a VF Page + Apex Controller where I leverage the action attribute on <apex:page> to handle some logic. What I've noticed is that when my user is set to Japanese, the VF Page tries to load data into Visualforce tags prior to evaluating the action method. I took a look in the Debug Log and confirmed this. However, when the user is set to English, this works as expected.

What I'm curious about is which behavior should be expected. Based on the Visualforce Page order of execution and controller lifecycle, I thought the action on the <apex:page> attribute should fire prior to evaluating anything else on the page?

Below is some sample code to explain the concept of what I am seeing. Unfortunately, this snippet of code does not fail, but the actual code I am leveraging is far too complex to include at the moment.

Visualforce Page

<apex:page controller="myController" action="{!init}">
  <apex:form>
    ...
    <input type="hidden" id="stringsSize" value="{!stringsSize}"/>
    ...
  </apex:form>
</apex:page>

Apex Controller

public class myController {
  public List<String> strings;

  public PageReference init() {
    strings = new List<String>();
    return null;
  }

  public Integer getStringsSize() {
    return strings.size();
  }
}

In this example, because init is being called after getStringsSize, there is a null pointer exception because strings hasn't been instantiated yet (but only if the user is Japanese).

1 Answer 1

1

The documentation does not specify any specific order between the action method and the various page expressions, so you should expect no particular order. Use lazy-loading/initialization in these scenarios to coerce your desired order-of-execution.

The solution:

// define your initialization logic in here:
private void initStrings() {
    // init only if not previously init'd:
    if (strings == null)
        strings = new String[]{};
}

// for everywhere but initStrings, use this getter rather than
// a direct reference to "strings":
public String[] getStrings() {
    initStrings();
    return strings;
}

public Integer getStringsSize() {
    return getStrings().size();
}

Or a a slightly more compact solution using an attribute:

public String[] strings {
    get {
        if (strings == null) {
            // initialization logic:
            strings = new String[]{};
        }
        return strings;
    }

    private set;
}

public Integer getStringsSize() {
    return strings.size();
}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .