10

I have a lightning component that displays Knowledge Articles based on Topic IDs that it is configured for. This works great so I went to create my test coverage for it and discovered that the inserted test Knowledge Articles can only ever be 'Draft' making my tests fail since the apex class only looks for 'Online'. Instead of rewriting my component I decided to overload the apex method so that when called without the status parameter it passes in 'Online' allowing my tests to pass in 'Draft' instead. However, the first method signature does not get called from the component resulting in null for the status parameter.

Here is the component controller:

({
    "retrieveArticles" : function(component, event, helper) {
        var action = component.get("c.returnArticlesWithTwoTopicIds");
        action.setParams({
            mainTopicId : component.get("v.mainTopicId"),
            secondaryTopicId : component.get("v.secondaryTopicId"),
            limitAmount : component.get("v.limitAmount")
        });

        action.setCallback(this, function(response) {
            var state = response.getState();
            if (component.isValid() && state === "SUCCESS") {
                // handle SUCCESS
            }
            else if (component.isValid() && state === "ERROR") {
                // handle ERROR
            }
        });
        $A.enqueueAction(action);
    }
})

Here is the apex class:

public with sharing class KnowledgeArticleVersionCtrl {
    @AuraEnabled
    public static List<KnowledgeArticleVersion> returnArticlesWithTwoTopicIds(String mainTopicId, String secondaryTopicId, Integer limitAmount) {
        return returnArticlesWithTwoTopicIds(mainTopicId, secondaryTopicId, limitAmount, 'Online');
    }

    @AuraEnabled
    public static List<KnowledgeArticleVersion> returnArticlesWithTwoTopicIds(String mainTopicId, String secondaryTopicId, Integer limitAmount, String status) {
        // build query string
        List<KnowledgeArticleVersion> articles = Database.query(query);
        return articles;
    }
}

Is there something about the component that would cause it to not use the first signature, the one it should match, in place of the second one, which it shouldn't match?

14
+50

I think in general it's asking for trouble to overload a method and make both versions @AuraEnabled. You've seen that it will allow you to fire the method with missing parameters, so I suggest you just keep only the second method and check for a null:

@AuraEnabled
public static List<KnowledgeArticleVersion> returnArticlesWithTwoTopicIds(String mainTopicId, String secondaryTopicId, Integer limitAmount, String status) {
    status = (status == null) ? 'Online' : status;
    // build query string
    List<KnowledgeArticleVersion> articles = Database.query(query);
    return articles;
}

And if you have a scenario where overloads are useful in your Apex code but only one version ever needs to be called from Lightning, then only make that one overload @AuraEnabled.

  • I actually had already used that exact ternary statement in my code to work around this! Great minds I guess. Removing the AuraEnabled is a rather interesting thought. It seems to work but is still disappointing that this would be the issue. Any official word on AuraEnabled and overloaded methods? – Matthew Green Jun 23 '16 at 21:12
  • I'd be interested in hearing official word too. In ASP.NET MVC 5 a similar thing happens but they use annotations to resolve ambiguities. – Charles T Jun 23 '16 at 21:18
  • 5
    Just to add, it might be a best practice that if you have a method that will sometimes be called by Lightning and sometimes from Apex, create a wrapper with @AuraEnabled and a unique name and make that the only version Aura calls. That way even if the underlying implementation changes you can keep one constant name & signature for your Lightning component to talk to. – Charles T Jun 24 '16 at 13:38
3

I would suspect that it uses the most complete signature like Java does.

(i.e. calling myFunction() will execute myFunction(a,b){})

You could get around this by changing the signatures as follows:

public with sharing class KnowledgeArticleVersionCtrl {
    @AuraEnabled
    public static List<KnowledgeArticleVersion> returnArticlesWithTwoTopicIds(String mainTopicId, String secondaryTopicId, Integer limitAmount) {
        return returnArticlesWithTwoTopicIds(mainTopicId, secondaryTopicId, 'Online', limitAmount );
    }

    @AuraEnabled
    public static List<KnowledgeArticleVersion> returnArticlesWithTwoTopicIds(String mainTopicId, String secondaryTopicId, String status, Integer limitAmount ) {
        // build query string
        List<KnowledgeArticleVersion> articles = Database.query(query);
        return articles;
    }
}

Doing this, it should execute the method you expect vs the last one.

  • 1
    This was my first assumption as well. I've tested this however and I'm getting the same results. It's like there is something about AuraEnabled that causes a null status to always be passed in, which then causes the second signature to be used. All very strange. – Matthew Green Jun 27 '16 at 14:15

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.