+ Start a Discussion
isalewisalew 

Debugging client and server controller actions with the same name

The Lightning Components Developer Guide warns about using the same name for client and server controller actions:
Use unique names for client-side and server-side actions in a component. A JavaScript function (client-side action) with the same name as a server-side action (Apex method) can lead to hard-to-debug issues.
I was unlucky enough to miss this tip before I debugged one of those hard-to-debug issues. To prevent others from making the same mistake, I wanted to share my debug path in case you miss the memo about naming conventions and run into similar symptoms:

PricingTool.cmp
My component contains a button that runs a client controller action named "c.getPricing"

<pre>
<aura:component controller="ServerController">
  <aura:attribute name="products" type="ServerController.ProductPrice[]"></aura:attribute>
  <ui:button aura:id="buttonGetPricing" label="Get Pricing" press="{!c.getPricing}"></ui:button>
</aura:component>
</pre>

PricingToolController.js
The controller action calls a helper action with the same name: "hlp.getPricing"

<pre>
({
    getPricing: function(cmp,evt,hlp){
        console.log('in c.getPricing');
        hlp.getPricing(cmp,hlp);
    }
})
</pre>

PricingToolHelper.js
My helper attempts to call a server-side action "c.getPricing", which is the same name as the client-side action "c.getPricing"

<pre>
({
    getPricing : function(cmp,hlp)
    {
        console.log('in hlp.getPricing');
        var action = cmp.get('c.getPricing');
        var products = cmp.get('v.products');
        action.setParams({productList : products});
        action.setCallback(this,function(res){
            console.log('in hlp.getPricing callback');
            var state = res.getState();
            console.log('hlp.getPricing ' + state);
            if (state === "SUCCESS") {
                var pricing = JSON.parse(res.getReturnValue().body);
                console.log(pricing);
            }
        });
        $A.enqueueAction(action);
    },
})
</pre>

ServerController.cls
The server code successfully passes unit testing, but when launched from my Lightning Component helper class, no "/aura" logs are created on the server, indicating the server code is never touched.

<pre>
public class ServerController{

    @AuraEnabled
    public static Response getPricing(List<ProductPrice> productList) {...}
}
</pre>

Back To The Client...
So the server action is never run, and my javascript console is growing a fearsome loop of the following log lines:
 
in c.getPricing             # client controller action triggered
in hlp.getPricing           # helper action triggered
in hlp.getPricing callback  # callout to "c.getPricing" triggered
hlp.getPricing SUCCESS      # callout successfully returned
undefined                   # the results of res.getReturnValue() are empty
in c.getPricing
in hlp.getPricing
in hlp.getPricing callback
hlp.getPricing SUCCESS
undefined

The Moral of this Story
When the helper attempts to "get" a server action from the component, it receives the client action instead, because they use the same name. This causes an endless loop on the client, where the controller executes itself again and again via the helper's action call. The callback won't throw any errors and happly continues with a "SUCCESS" state.

The fix to this all, of course, is quite simple.

ServerController.cls
First change the name of the server controller action:

<pre>
// public static Response getPricing(...) {...}
public static Response getServerPricing(...){...}
</pre>

PricingToolHelper.js
Then update the helper reference to the server controller:

<pre>
// var action = cmp.get('c.getPricing');
var action = cmp.get('c.getServerPricing');
</pre>

Happy Lightning Development!
Ryan FrankRyan Frank
Wow - isalew - Thank you!  I've been banging my head against the wall for the past 2 hours wondering what I was doing wrong.  Finally did a google search, and you saved the day.  You get a gold star for the day - thank you!
Pawan Kumar 407Pawan Kumar 407
For better understanding this concept just focus on the $A.enqueueAction function.

$A.enqueueAction(action) adds the server call that we’ve just configured to the Aura component framework request queue. It, along with other pending server requests, will be sent to the server in the next request cycle.

The important thing about $A.enqueueAction(action) is that we can invoke other Javascript function which are in the same controller using this method. for example.

({
    getName: function(cmp){
        console.log("call *getPhone* Javascript function");
        var action = cmp.get("c.getPhone");
         $A.enqueueAction(action);
    },
    
    getPhone: function(cmp){
        console.log("called phone");
    }
})

$A.enqueueAction(action), first find the calling function into Javascript controller rather than Apex Controller and if Javascript controller have this function then 
Javascript function invoke first.

----------------------------------------------------------------------------------------------------
Now the main issue(Hard to Debug) issue.

Suppose you have a method with the same name into Javascript controller and Apex Controller and you tried to invoke Apex function into the Javascript controller then below code first call the Javascript function and this way Apex method never invoke.

getName: function(cmp){
        console.log("call *getPhone* Javascript function");
        var action = cmp.get("c.getName");
         $A.enqueueAction(action);
    }

And if the function will call itself then this creates the Recursive situation as such *getName* function get call 1000 times(it is the maximum calling limit) and after that the process will be terminated and you will get following error.


This page has an error. You might just need to refresh it. AuraClientService.postProcess: error in processing [Maximum call stack size exceeded] Failing descriptor: {aura:html}

User-added image
Ankit Gupta 305Ankit Gupta 305
Thank you so much  -  Isalew & Pawan Kumar 407 , for helping me in understanding it in an easy way,