[SalesForce] Lightning Component : INVALID_SESSION_ID when retrieving picklist values by recordtype using Metadata API

Am using FinancialForce's MetadataService Class to retrieve picklist values by record type ,which works properly in a Remotingmethod.

When i try to do the same in lightning component's AuraEnabled method i get below error in the debug log.

Web service callout failed: WebService returned a SOAP Fault: INVALID_SESSION_ID: This session is not valid for use with the API faultcode=sf:INVALID_SESSION_ID faultactor

Here's the code:

Controller:

public class PickListController{  

@AuraEnabled
public static String getPickListByRecordTypes(String recTypeStr,String fieldStr,String objectName){

    List<String> recType = recTypeStr.split(',');
    List<String> fieldList = fieldStr.split(',');
    Map<String, Map<String, List<SelectOptionWrapper>>> returnRecordTypeAndFieldNameAndPickValSetMapMap = new Map<String, Map<String, List<SelectOptionWrapper>>>();
    Set<String> fieldSet =  new Set<String>(fieldList);

    if(recType != Null && recType.size() > 0) {
        MetadataService.MetadataPort service = createService();
        System.debug(':::recType:::' + recType + '   ' + recType.size());

        for(String rt : recType) {
            Map<String, List<SelectOptionWrapper>> fieldNameAndPickValMap = new Map<String, List<SelectOptionWrapper >>();
            System.debug(':::rt:::' + rt);

            MetadataService.RecordType recordType = (MetadataService.RecordType) service.readMetadata(
                'RecordType', new String[] { objectName +'.'+ rt }
            ).getRecords()[0];
            System.debug(':::recordType:::' + recordType);

            if(recordType.picklistValues != NULL) {
                for ( MetadataService.RecordTypePicklistValue rpk : recordType.picklistValues ) {
                    System.debug(':::rpk:::' + rpk );
                    if(rpk.picklist != NULL) {

                        if ( fieldSet.contains(rpk.picklist) ) {
                            for (MetadataService.PicklistValue pk : rpk.values ) {
                                if(pk.fullName != NULL) {  
                                    String pickVal = EncodingUtil.urlDecode(pk.fullName, 'UTF-8');
                                    if(!fieldNameAndPickValMap.containsKey(rpk.picklist)) {
                                        List<SelectOptionWrapper> optionList = new  List<SelectOptionWrapper>();
                                        optionList.add(new SelectOptionWrapper('','-None-'));
                                        optionList.add(new SelectOptionWrapper(pickVal,pickVal));
                                        fieldNameAndPickValMap.put(rpk.picklist,optionList);
                                    } else {
                                        fieldNameAndPickValMap.get(rpk.picklist).add(new SelectOptionWrapper(pickVal,pickVal));
                                    }
                                }
                            }
                        } 
                        System.debug(':::fieldNameAndPickValMap:::' + fieldNameAndPickValMap);
                    }
                }
            }
            if(fieldNameAndPickValMap.size() > 0) {
                returnRecordTypeAndFieldNameAndPickValSetMapMap.put(rt, fieldNameAndPickValMap);
            }
            System.debug(':::returnRecordTypeAndFieldNameAndPickValSetMapMap:::' + returnRecordTypeAndFieldNameAndPickValSetMapMap);
        }
    }
    return JSON.serialize(returnRecordTypeAndFieldNameAndPickValSetMapMap);
}

public class SelectOptionWrapper{
    @AuraEnabled
    public String label;
    @AuraEnabled
    public String value;

    public SelectOptionWrapper(String value,String label){
        this.label = label;
        this.value = value;
    }

}

public static MetadataService.MetadataPort createService() {
    MetadataService.MetadataPort service = new MetadataService.MetadataPort();
    service.SessionHeader = new MetadataService.SessionHeader_element();
    service.SessionHeader.sessionId = UserInfo.getSessionId();
    return service;
}
}

PickListCmp.cmp

<aura:component controller="PickListController">
   <aura:handler name="init" value="{!this}" action="{!c.getPickValue}"/>
</aura:component>

PickListCmpController.js

({
getPickValue : function(component, event, helper) {
    var action = component.get("c.getPickListByRecordTypes");
    action.setParams({
        "recTypeStr":'RecordType1',
        "fieldStr":'Ownership',
        "objectName":'Account'
    });
    action.setCallback(this,function(response){
        var state = response.getState();
        var result = response.getReturnValue();
        if(state === 'SUCCESS'){
            console.log(result);
        }
        else{
            console.log("error:::",response.getError())
        }
    });

    $A.enqueueAction(action);
}
})

FYI,When I use getPickListByRecordTypes as RemoteAction instead ,and use it in VF page,am getting the picklist values

Best Answer

Here is the answer and you are not going to like it Lightning: is direct API access on the roadmap?

With that said:

  • are you building component(s) that need to run inside Lightning Experience (LEX) or S1 or a standalone app or Visualforce/Communities?

  • if you are using Lightning Components for Visualforce then you are not subject to the CSP rules and you also have access to a full API sessionID

  • if you have to run inside of LEX/S1 there is a not too difficult client side proxy using a hidden iframe and a small VF page "shim" that also works

FWIW I've become a much bigger fan of the inversion (use Lightning components inside of a Visualforce page as the container) in the past few months.

Related Topic