9

EDIT: 25/03/2017 - reworked example to most basic apex class, serialised using JSON and simple string.

We've suddenly (today) started seeing issues in one of our orgs with lightning components that make server side requests that return Apex classes, in that the responses are empty. I've got this down to a really simple test case that shows the difference between returning an apex class that contains a String, a serialised apex class and a simple String.

Apex Controller:

public class KeirTestCtrl {
    @AuraEnabled
    public static KeirResult GetClass()
    {
        KeirResult res=new KeirResult();
        res.message='All good';
        System.debug('Returning ' + res);
        return res;
    }

    @AuraEnabled
    public static String GetSerialisedClass()
    {
        KeirResult res=new KeirResult();
        res.message='All good';
        String resStr=JSON.serialize(res);
        System.debug('Returning ' + resStr);
        return resStr;
    }

    @AuraEnabled
    public static String GetString()
    {
        String res='All Good';
        System.debug('Returning ' + res);
        return res;
    }
}

Apex Class returned by the controller:

public class KeirResult
{
    public KeirResult() {}

    @AuraEnabled
    public String message {get; set;}
}

Lightning Application:

<aura:application controller="KeirTestCtrl">
    <button onclick="{!c.getClass}">Get the Class</button><br/>
    <button onclick="{!c.getSerialisedClass}">Get serialised class</button><br/>
    <button onclick="{!c.getString}">Get the String</button><br/>
</aura:application>

Lightning Controller:

({
    getClass : function(component, event, helper) {
        helper.getClass(component, event);
    },
    getSerialisedClass : function(component, event, helper) {
        helper.getSerialisedClass(component, event);
    },
    getString : function(component, event, helper) {
        helper.getString(component, event);
    }
})

Lightning Helper:

({
    getClass : function(cmp, ev) {
        var action=cmp.get('c.GetClass');
        var self=this;
        action.setCallback(this, function(response) {
                self.actionResponseHandler(response);
        });
        $A.enqueueAction(action);
    },
    getSerialisedClass : function(cmp, ev) {
        var action=cmp.get('c.GetSerialisedClass');
        var self=this;
        action.setCallback(this, function(response) {
                self.actionResponseHandler(response);
        });
        $A.enqueueAction(action);
    },
    getString : function(cmp, ev) {
        var action=cmp.get('c.GetString');
        var self=this;
        action.setCallback(this, function(response) {
                self.actionResponseHandler(response);
        });
        $A.enqueueAction(action);
    },
    actionResponseHandler : function (response) {
        try {
            var state = response.getState();
            console.log('State = ' + state);
            if (state === "SUCCESS") {
                var retVal=response.getReturnValue();
                alert('Result = ' + JSON.stringify(retVal));
            }
            else if (state === "ERROR") {
                var errors = response.getError();
                if (errors) {
                    if (errors[0] && errors[0].message) {
                        alert("Error message: " + errors[0].message);
                    }
                } 
                else {
                    alert("Unknown error");
                }
            }
        }
        catch (e) {
            alert('Exception in actionResponseHandler: ' + e);
        }
    }
})

When I run this on my personal dev org on the EU5 instance and click the 'Get Class' button, I get the following alert in the JavaScript console:

Result = {"message":"All good"}

However, when I run this on our main org on the EU3 instance I get:

Result = {}

Checking the debug log shows that the response has been created correctly:

08:38:09:002 USER_DEBUG [7]|DEBUG|Returning KeirResult:[message=All good]

If I click the button to return the serialised class on my main org, I get the following as expected:

Result = "{\"message\":\"All good\"}"

and when returning a simple string:

Result = "All Good"

As far as I can tell, everything that returns an apex class as a response in the EU3 org is now returning empty values, which means the majority of my lightning components, and thus most of my custom functionality, no longer work. I've raised a case with Salesforce support (16080817) but I'm curious if anyone else has seen this as it seems pretty fundamental.

  • 1
    Could there be a type conflict with the Result type preventing proper serialization? Do you get the same behavior if you change the class name and make the return type an instance of KeirIsAwesome? Does it make any difference if you've got an explicit constructor in the return type class? – Mark Pond Mar 24 '17 at 23:07
  • I'm going to play around with some more today to see if there is any particular aspect that breaks it - I'll try out your suggestions. Thanks. – Bob Buzzard Mar 25 '17 at 7:34
  • Sadly nothing helps - I've moved the result class to a top level, renamed it to KeirResult and added a no-args constructor. Still empty every time, but the exact same code works in other orgs. Looks to me like Salesforce have released some bad code, as we haven't touched the setup on this org for a couple of months and it suddenly started failing. – Bob Buzzard Mar 25 '17 at 8:41
  • 1
    I hit this bug as well. I started case 16074894 which should have some good info on it. I believe support can fix this on a per org basis while a final fix is being worked on. – Mike Tetlow Mar 25 '17 at 20:16
  • The issue should now be resolved and the behavior should be working as expected. success.salesforce.com/issues_view?id=a1p3A0000008gcaQAA – John Brock Apr 7 '17 at 22:15
3

This should be covered by https://success.salesforce.com/issues_view?title=auraenabled-annotation-not-working-correctly-at-runtime-for-json-serialze&Id=a1p3A0000008gca (which links to this post as an example).

The KI talks about JSON.serialize, rather than the implicit serialization of returning an Object from an @AuraEnabled method as you're doing here, but the underlying bug should fix your example here when rolled out.

Also note from the KI: "Please contact Salesforce support if an immediate fix is needed.", if you do this reference the KI so they can fast track the resolution that's internally linked to the bug.

| improve this answer | |
  • 1
    Thank you, Chris. Yes - the fix for the issue should now be rolled out. – John Brock Apr 7 '17 at 22:16
2

We faced the same issue in our package org. Below is what I did to fix it:

1) Serialize the wrapper instance using JSON.serialize() and sent the response as string to LC.

2) Converted the string back to JS Object using JSON.parse()

| improve this answer | |
  • 2
    Yeah, I'd expect this to work as there's no longer an Apex class involved, it's simply a string. I'd have to change around 200 return classes just to work around what feels like a bug that has been introduced into the platform, so I'm leaving this as a last resort. – Bob Buzzard Mar 25 '17 at 7:29
  • @BobBuzzard For sure this is a bug! and I hope salesforce fixes it asap. – Praveen Mar 25 '17 at 8:18
  • has this just started happening for you, or was it in the past? Do you know which instance you were on? I've updated my example to add a serialisation option and sure enough that works fine. – Bob Buzzard Mar 25 '17 at 8:44
  • 1
    It happened two days ago and the instance we are in is NA30. – Praveen Mar 25 '17 at 8:59

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.