4

I have a VF page with a handful of apex:repeat tags - each of which references a getter, which runs a soql query to retrieve data. I also have an actionpoller in the page to refresh it every 15 seconds.

I started getting the 101 SOQL Query error - even though I was well short of 101 queries. The error only occurs on the actionpoller refresh - so if I load the page manually, it loads without incident. I did some debugging, and I see that when the page re-loads as part of the actionpoller, all of the getters are called twice.

Debugging further, I see that if i put the getters in an outputText tag, the getters are only called once. Odd.

Is this expected behavior as per the post below? Setter executes twice when attributes are defined on components - and specifically per this documentation:

It’s a best practice for getter methods to be idempotent, that is, to not have side effects. For example, don’t increment a variable, write a log message, or add a new record to the database. Visualforce doesn’t define the order in which getter methods are called, or how many times they might be called in the course of processing a request. Design your getter methods to produce the same outcome, whether they are called once or multiple times for a single page request.

Or is there something else happening here which is causing the getters to be called twice? I've stripped the code to a pretty minimal version and I'm clearly seeing the behavior in the debug logs. (I just did a bit more debugging, and it seems that the controller behavior is dramatically different between calling via outputText and repeat...)

thanks so much for your help. chris

5

Getters and setters may be called more than once. This is determined by the compiler and can't explicitly be forced. Generally, if you're doing anything in a getter, you should be caching the results, and returning that cached value when possible. Typical example:

transient SelectOption[] myPicklistCache;
public SelectOption[] getPicklistOptions() {
  if(myPicklistCache == null) {
    // build a new list of items
  }
  return myPicklistCache;
}

This is especially important when the operation is "expensive" (e.g. it performs a query, complex calculations, etc). You should avoid performing the calculation more than once. The transient keyword keeps the data out of the view state, reducing its size.

Edit: This is not technically a bug, because the documentation basically tells us that the quantity and order of getter calls is indeterminate, so you should always guard against that possibility. Only action methods will be called once, and you can guarantee they'll be called is predictable within the Visualforce Lifecyle.

  • sfdcfox - Thanks so much for your response - I have marked it as the answer to this post. I implemented something similar to what you suggested above shortly after posting my question - and it worked as expected. And agreed - not a bug - peculiar behavior though (although I'm sure there's a reason for it on the backend)... – chris markiewicz Feb 1 '17 at 22:54
1

I think you are using the actionpoller to get the latest data on the page after each interval. I would suggest you to use Streaming API as its a simple way to push relevant data to your users in realtime, instead of having to refresh the screen to get new information. This allows a user to get information without having to perform any action to retrieve it, essentially pushing new data to the screen.

Example - https://developer.salesforce.com/docs/atlas.en-us.api_streaming.meta/api_streaming/code_sample_vfp_intro.htm

  • Yeah, good call. This code was actually already written and I was just doing some debugging, but I'll look into refactoring it. Streaming API might make a lot of sense here. Thanks for your response! chris – chris markiewicz Feb 5 '17 at 0:50

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.