12

I have an existing class that works with a REST API from a managed package. This class represents the payload that the REST API accepts in implementations, so it has a number of variables that use inline get/set methods. I am now updating this class to work with lightning components and am trying to @AuraEnable the member variables so that they can be used in the components. However, when I try to @AuraEnable a member variable that has an inline set defined, I get an internal server error on compile. For example, the following fails to compile with An unexpected error occurred:

global with sharing class MyApiRequest {

  @AuraEnabled
  global Integer myParam {
    get;
    set {
      myParam = value;
      // Other setup code
    }
  }
}

If anyone from the lightning team ends up reading this, the GACK is 2075044-41594 (1492374082).

Is the @AuraEnabled method just not supported for member variables with inline sets?

3
  • 3
    @DougChasman please look at this post
    – crmprogdev
    May 27, 2016 at 18:14
  • 1
    I have questions as to how you are using this. Is this MyApiRequest class being used as a data representation where you de/serialize JSON into/out of an instance of this class? I think @AuraEnabled is reserved for methods that are to be invoked by $A.enqueueAction and must be static.
    – pchittum
    May 31, 2016 at 11:07
  • @Peter Correct, MyApiRequest represents an Apex object. For an API request, this helps reduce the number of parameters each method needs to accept and for responses (where @AuraEnabled is really crucial to get the response data back to lightning) it is the only way to pass back a full API response including success, messaging, and data. The static method that accepts an instance of MyApiRequest as a parameter is also @AuraEnabled and that compiles just fine.
    – dsharrison
    May 31, 2016 at 15:41

2 Answers 2

5
+50

As per Salesforce document (https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_annotation_AuraEnabled.htm) the AuraEnabled is available for methods and also there is another condition which states that AuraEnabled methods should start with a prefix 'get' (below is the error message).

AuraEnabled methods must be named with a prefix 'get'

I tried couple of things to understand more. To ensure that the setter is visible in Lightning Components, then we should declare the variable with @AuraEnabled and write the getter and setter methods explicitly.

If we have an inline sets with variable declared with @AuraEnabled annotation, this would inherently try to apply the annotation for the setter method. This would violate the above condition of the method with prefix 'get'.

Below is the sample code which works.

global with sharing class MyApiRequest {
@AuraEnabled global Integer myParam;

global Integer getMyParam() {
    return myParam;
}

global void setMyParam(Integer value) {
    myParam = value;
}

@AuraEnabled
global String myString {get;set;}}
4
  • 1
    While I understand that set methods cannot be @AuraEnabled, this is a rule defined by the owners of the framework (Salesforce), so I would think they would be able to apply the annotation to only the get portion of the inline definition, rather than crash.
    – dsharrison
    Jun 1, 2016 at 17:31
  • 1
    @D.S. You have to remember that Lightning is a "work in progress". The Lightning platform isn't yet fully defined and there's much that's yet to be developed or "fleshed out" as they discover what developers need to create the functionality customers want. Right now, they're very focused on fixing security holes they didn't recognize existed in their architecture when they began. You might want to think of Lightning as new technology that's essentially in a "public beta".
    – crmprogdev
    Jun 1, 2016 at 18:39
  • @crmprogdev Yeah, I have been trying to wait for the framework to stabilize to actually get into production lightning development, but the business side could not wait any longer. It sounds like at this point we might need to just duplicate our existing REST API for Lightning and maintain two APIs going forward. We cannot make breaking changes to the existing API as it is in use. It is great that Lightning coerces get methods into properties for Apex object responses and if they added this enhancement to their @RestResource serialization that would be a super win!
    – dsharrison
    Jun 2, 2016 at 15:43
  • @D.S. Sounds like a good one for the Idea exchange.
    – crmprogdev
    Jun 2, 2016 at 18:03
1

Instead of having a return type of MyApiRequest in your @AuraEnabled method, you could have the method return a String, JSON.serialize() the data structure before returning it, and then JSON.parse(response.getReturnValue()) in the client-side controller. At least this way you won't have to add the @AuraEnabled annotations to the data structure that you are returning.

Server Side Controller

@AuraEnabled
public static String getMyApiRequest(){

    MyApiRequest mar = ....

    String s = JSON.serialize(mar);
    map<String,Object> m = (Map<String, Object>) JSON.deserializeUntyped(s);
    m.remove('privateVariable'); 
    return JSON.serialize(m);

}

Client Side Controller

clientsidefunction : function(component,event,helper){
    var action = component.get("c.getMyApiRequest");
    action.setCallback(this,function(response){
        console.log(JSON.parse(response.getReturnValue()));
    }
    );
    $A.enqueueAction(action);
}

Class To Return

global with sharing class MyApiRequest {
// not needed .. @AuraEnabled
global Integer myParam {
    get;
    set {
      myParam = value;
      // Other setup code
    }
  }

private Integer privateVariable{get; set;}
}
2
  • 1
    Good idea, I'll do some testing around the security here. I am not sure if doing that would expose our private variables in the serialized string. This would be an issue since the data would be heading into the client-side javascript and we don't want to expose any sensitive data.
    – dsharrison
    Jun 2, 2016 at 16:34
  • @D.S. In that case, if you wanted to take this idea one step further, you could take that JSON string and turn it into a map where you could specify which variables to exclude, then reserialize it and return it.
    – martin
    Jun 2, 2016 at 16:44

You must log in to answer this question.

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