Salesforce: Impossible to invoke Lightning or Visualforce actions in Apex Code

When I saw QuickAction class and QuickAction.QuickActionRequest object I assumed that it supports Lightning and Visualforce actions, however, in fact, it doesn’t.

I created two actions. Lightning Action on Account and called it LA and Visualforce action on Account and called it VA.

When I try to execute this code

QuickAction.QuickActionRequest req = new QuickAction.QuickActionRequest();
req.quickActionName = 'Account.LA';
req.contextid = '001xx000003DGcO';
System.debug(LoggingLevel.ERROR, '@@@ req: ' + req );
QuickAction.QuickActionResult res = QuickAction.performQuickAction(req);
System.debug(LoggingLevel.ERROR, '@@@ res: ' + res );

I receive an error

System.UnexpectedException: ActionType LightningComponent not supported yet

and when I try to execute this code

QuickAction.QuickActionRequest req = new QuickAction.QuickActionRequest();
req.quickActionName = 'Account.LA';
req.contextid = '001xx000003DGcO';
System.debug(LoggingLevel.ERROR, '@@@ req: ' + req );
QuickAction.QuickActionResult res = QuickAction.performQuickAction(req);
System.debug(LoggingLevel.ERROR, '@@@ res: ' + res );

I receive an error

System.UnexpectedException: ActionType VisualforcePage not supported yet

It is so big drawback that Actions invocation is not available neither directly from Lightning not through Apex

Advertisements
Posted in Actions, lightning, salesforce, Uncategorized, visualforce | Tagged , , , , , , | Leave a comment

How to get Layout assigned to Profile and Record Type by Apex Code

If you are interested in solution which would work only for Salesforce Classic, I have it.

It is possible to make Tooling API ProfileLayout Object Query

[ select Layout.Name from ProfileLayout where ProfileId = :UserInfo.getProfileId() AND RecordTypeId = :record.RecordTypeId ]

To make it possible to use in Apex Code you need preparation step.

1) Allow Self-Callout. To do this, go to Remote Site Settings by link https://login.salesforce.com/0rp/e?SiteName=self&EndpointUrl=https://yourinstance.salesforce.com/ on production or Developer Edition instance or https://test.salesforce.com/0rp/e?SiteName=self&EndpointUrl=https://yourinstance.salesforce.com/ on any of sandbox instance and input link to your instance and click save.

2) Run the following code from Anonymous Execution Window

static String restGet(String endPoint, String method, String sid) {
    Http h = new Http();
    HttpRequest hr = new HttpRequest();
    hr.setHeader('Authorization', 'Bearer ' + sid);
    hr.setTimeout(60000);
    hr.setEndpoint(endPoint);
    hr.setMethod(method);
    HttpResponse r = h.send(hr);
    return r.getBody();
}
static String toolingAPISOQL( String query) {
    String baseURL = URL.getSalesforceBaseUrl().toExternalForm();
    return restGet( baseURL +
'/services/data/v41.0/tooling/query?q='+ (query.replace(' ', '+'))
,
'GET', UserInfo.getSessionId() );
} 

static String getLayoutNameForCurrentUserProfile( Id recordId ) {
    String body = toolingAPISOQL('select Layout.Name from ProfileLayout where ProfileId = \'' + UserInfo.getProfileId() + '\' AND RecordTypeId = \'' + [ select RecordTypeId  from Account where id = :recordId].RecordTypeId + '\'');
    System.debug(LoggingLevel.ERROR, '@@@ v: ' + body );
    String name = body.substringBetween('"Name":"', '"');
    System.debug(LoggingLevel.ERROR, '@@@ v: ' + name );
    return name;
}
getLayoutNameForCurrentUserProfile('001g000001hLEAj');

You will can the name of desired layout.

Note that this would work only in Salesforce Classic and not in Lightning by strange Salesforce policy which disadvantages Lightning very much since

By security policy, sessions created by Lightning components aren’t enabled for API access. This prevents even your Apex code from making API calls to Salesforce.

Posted in salesforce | Leave a comment

Retrieving Platform Action List and its context sources in Salesforce

Today I have been investigating how to get list of platform actions and how to get context source for given action.

This is clear that we could use Metadata API to retrieve list and metadata of Lightning Platform Actions, but it is interesting that it is possible to get it by Apex code also.

If we know the layout name for which we want to get list of platformActions or quickActions we can use Metadata.Operations.retrieve method and PlatformActionListItem class assuming we have custom object Test_Object__c which has the only Test Object Layout

Metadata.layout layout =  new Metadata.layout();
List<String> layoutList = new List<String>{'Test_Object__c-Test Object Layout'};

List<Metadata.Metadata> components = Metadata.Operations.retrieve(Metadata.MetadataType.Layout, layoutList);
layout = (Metadata.layout)components.get(0); 

Metadata.Layout class has platformActionList and quickActionList

PlatformActionList class has platformActionListItems property of List<PlatformActionListItem> class which has only four properties: actionName, actionType, sortOrder and subtype.

QuickActionList class has quickActionListItems property of List<QuickActionListItem> which has the only quickActionName property.

Also there is another way to get list of all actions. It is possible to use code

QuickAction.DescribeAvailableQuickActions('Global')

to get all actions (both platform and quick) and also it is possible to use code

QuickAction.DescribeAvailableQuickActions('Account')

to get all actions related to standard Account object or

QuickAction.DescribeAvailableQuickActions('Test_Object__c')

to get all actions related to custom Test_Object__c object.

QuickAction.DescribeAvailableQuickActions method would return the list of DescribeAvailableQuickActionResult instances with four fields: 1.
actionEnumOrId which appears to be id of Tooling API QuickActionDefinition object record; 2. label; 3. name; 4. type.

To get more information we need to call another method called QuickAction.DescribeQuickActions which returns returns list of DescribeQuickActionResult which have more information about content source, for example, it is possible to get visualforcepagename and visualforcepageurl for Visualforce action and lightningcomponentbundlename and lightningcomponentqualifiedname for Lightning actions.

Posted in salesforce, Uncategorized | Leave a comment

Bye-bye Test.isRunningTest()! Welcome Test.createStub and StubProvider!

Today I have found about wonderful feature which I have never heard before, it is mocking tests with stub interface

It is now possible to create sophisticated stub interface implementation and use it with method Test.createStub.

Yahoo! There is no need to use Test.isRunningTest() method anymore!

Posted in salesforce | Leave a comment

Salesforce Winter 18 feature to customize Lightning home page layout

For a long time I have been struggling about how to make Lightning Home Page to have only one column. Looks like there is an option in Winter’18 release.

You need to create the following component HomePageSingleColumnTemplate with the following code

<aura:component implements="lightning:homeTemplate">
    <aura:attribute name="main" type="Aura.Component[]" /> 

    <div>
        <lightning:layout horizontalAlign="spread">
            {!v.main}
        </lightning:layout>
    </div>
</aura:component>

Also you have to specify design for it

<design:component >
    <flexipage:template >
        <flexipage:region name="main" defaultWidth="Xlarge">
        </flexipage:region>
    </flexipage:template>
</design:component>

You might or might not specify an icon for it, you can read interface description here and advanced configuration guide here about how to specify an icon or image for your template.

Then you just need to create a new Lightning Home page based on created layout and you will see one column.

Posted in salesforce, Uncategorized | Tagged , , , , , , | Leave a comment

Notes from talk

Effective Java Joshua Bloch
Java Puzzlers Joshua Bloch and Neal Gafter

Java Generics naming conventions: E, T…

Java Reflections isSynthetic

Posted in Uncategorized | Leave a comment

Salesforce: Territory Field.

One doesn’t simply query for standard Salesforce Territory Field.
One has to query [ select RelatedId, Related.Name from Group where Id IN (select UserOrGroupId from AccountShare where AccountId = :accId and RowCause IN (‘Territory Management’,’Territory’,’TerritoryManual’)) ].Related.Name

Thanks to eyescream who shed a light on this.

Posted in Territory Management, Uncategorized | Tagged , , , | Leave a comment