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
    @DougChasman please look at this post – crmprogdev May 27 '16 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 '16 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 '16 at 15:41
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;}}
| improve this answer | |
  • 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 '16 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 '16 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 '16 at 15:43
  • @D.S. Sounds like a good one for the Idea exchange. – crmprogdev Jun 2 '16 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;}
}
| improve this answer | |
  • 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 '16 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 '16 at 16:44

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.