0

I have a vf page displaying several Multi select custom buttons. And I am calling a apex method every time one of the button is clicked from VF page using actionfunction. But if I click 2 buttons in quick succession, the apex method being executed for the second time for the second button happens before the apex method for the first button finishes leading to unexpected result. if I wait for a little bit inbetween, the results come correct.

I tried using a Boolean 'methodExecuted' which will only execute the Javascript method after the Apex method gets executed. Didn't work.

Below similar Code

VisualForce

    <apex:page standardcontroller="Opportunity" extensions="extensionclass">
      <apex:slds/>

     <script type="text/javascript">

       function ButtonSelected(BtnValue) {
          ButtonSelected(BtnValue);

         if({methodExecuted}){
            // Code to change the CSS style of button onclick
         }
        }
      </script>

     <apex:actionFunction action="{!ButtonAction}" name="ButtonSelected" reRender="dummy">
        <apex:param name="param" value=""/>
     </apex:actionFunction>

     <apex:pageBlock>
        <apex:repeat value="{!allButnValues}" var="Btn" id="dummy">
          <button  onclick="ButtonSelected('{!Btn.value');" id="{!btnId}">
             {!Btn}  
          </button>
        </apex:repeat>
     </apex:pageBlock>
   </apex:page>

Class

 public class extensionclass{

  public Boolean methodExecuted {get;set;}

      public PageReference ButtonAction(){
          methodExecuted = false;
          selectedOption = Apexpages.currentPage().getParameters().get('param');
         // Some logic to get data from the clicked button.But before this method finishes the first time, the method gets executed again
           methodExecuted  = true;
      return null;
  }

2 Answers 2

2

When a Visualforce action goes off, the "view state" - which encapsulates the state of the controller and its instance variables - gets sent to the server from its storage (in encrypted, serialized form) in the client-side page.

On the server, that view state is deserialized to produce the current state of the controller, the code is executed, and the view state is returned to the client, ready for further actions to be taken that would start from that state.

Here, you're firing two asynchronous actions in very close proximity to one another. Assuming neither completes prior to the other starting, they have two independent copies of the view state, both starting from the same position (where methodExecuted is false or null). Setting methodExecuted in one of these invocations won't have any effect on the other, because it's already running, and the controller instance for each of the running actions is not shared across those threads of execution.

Fundamentally, what you have here is a species of race condition or synchronization problem. It's hard to design a cure for the issue because we don't see the actual logic involved. As a general principle, you'll want to make sure your server actions are resilient to this kind of ordering or synchronization issue via tactics like

  • ensuring that the actions are idempotent and mutually independent.
  • ensuring that a user cannot initiate Action B (which depends on the result of Action A) until Action A has successfully completed and returned by, for example, not rendering Action B's button until the page is in the correct state.
  • rerendering the right elements of the page to ensure that all changes are properly reflected regardless of action ordering.
2
  • option 2 elaboration - use actionStatus to block page UI (i.e the spinner technique)
    – cropredy
    Commented Jan 18, 2019 at 19:37
  • @David Reed.. Thanks for the insightful answer.. I ended up doing what was in essence Option 2..
    – Brav
    Commented Jan 21, 2019 at 13:03
-1

All Apex programs runs entirely ON-Demand on Force.com Platform.First the platform application server compiles the code into abstract set of instructions that can be understood by Apex runtime interpreter.The compile code is stored to metadata.

When the end users triggers the execution of Apex by clicking button or visualforce page the application servers retrieves the compiled instructions from the metadata and send them to runtime interpreter before returning the result.

1
  • 1
    This does not answer the question.
    – David Reed
    Commented Jan 18, 2019 at 14:31

You must log in to answer this question.

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