In Salesforce, a custom permission allows one to define whether or not a user has access to some custom feature declaratively through profiles and permission sets.
When custom permissions originally came out, one could only “easily” check if a user had access through Visualforce, Formula Fields, or Validation Rules. One could check in Apex through querying some system Objects but that was not as “easy”. Andy Fawcett’s Native Apex support for Custom Permissions idea show’s the exact usage and why he requested that it be easier.
Recently, I discovered that Salesforce did provide an easier way through the native “FeatureManagement” Apex API and it’s as easy as calling the “checkPermission” function.
Recently, I ran into this use case:
Show a link to a Visualforce page only if the current user has access to it. This is usually done for a pilot or a dark launch scenario so that a subset of users only have access to a feature.
Originally, I thought I was going to have to implement this through a custom permission or some other configuration setting without being able to use out-of-the-box visualforce page access through profiles and permission sets. Needless to say, I’m glad I stumbled across the How do I find out if a user has access to a visualforce page through apex? stackoverflow post. In it, Gennadiy describes how one can use the following SOQL to query the SetupEntityAccess standard object to see if someone has access to a given Visualforce page or not.
If the accessSettings list has any records, then the current user has access to the desired Visualforce page. If there are no records, the current user doesn’t have access to the page.
This works with the page being granted access through either the user’s profile or a permission set, despite the ParentId being looked up against the PermissionSetAssignment object.
In my last post, Apex Tips & Tricks, Bobby Watson commented:
For the two solutions for getting SObject record IDs, it would be interesting to see which one is the most efficient given a list of 1,000 or even 10,000, 50,000 records. Using the map is definitely easier, and I would assume is also the most efficient (but I’ve never done a test on this myself).
To answer Bobby’s question, 1,000 accounts were inserted into a Dev org. Next, apex code was run 5 times through execute anonymous to collect the queried accounts’ ids into a set of ids using three methods:
- For Each Loop. The account ids were collected using a For Each loop.
- For Loop. The account ids were collected using a For Loop using the more traditional for(int i = 0; i < numAccts; ++i).
- Map Constructor. The map has a constructor that takes in a list of SObject and automatically creates a Map<Id, SObject> from it. One can then use map.keySet() to get the set of Ids from it.
The For Each Loop takes the longest followed by the For Loop and finally the Map Constructor. The For Each Loop is roughly 8-9 times slower than using a Map Constructor. The For Loop is roughly 4 times slower than using the Map Contructor.
|Test Run #
||For Each Loop
Apex Profiling Code
The following apex code was run in a Developer org on na9 using Execute Anonymous. The 1,000 accounts were already inserted in the org.
Were the results as you expected? Have you done any other apex profiling?
Here are Tips & Tricks that I’ve found useful in Apex.
Get Salesforce Record Ids
There are times when you need to get the set of record ids from a list of SObject records. An easy way to get them is to loop over them and collect them like so:
An easier way using a map:
Request / Response Pattern
The request / response pattern refers to using a “Request” Parameter Object for an apex method’s input and a “Response” Parameter object for what is returned.
- In managed packages, a global method can’t have its signature changed once the package is released. Additional input or output in newer versions is fairly common so adding new request or response fields is how one can get around having to create additional global methods.
- No method overloads are needed.
Apex Can Invoke Salesforce APIs
While counter-intuitive, apex can be used to invoke the Salesforce APIs such as the Metadata, Bulk, Partner or Enterprise APIs. This is helpful when you want to stay on the Salesforce platform without having to manage servers and infrastructure off of it.
See Calling Salesforce Web Services Using Apex as an example.
Interfaces Can Extend Interfaces
While Apex started as a scripting language, it evolved into a feature rich, object-oriented language. While used infrequently, one can have an interface extend another interface. This has been helpful in managed packages where new methods are needed on an existing interface. A new interface is created that extends the old one and then used where needed.
It seems that apex developers often forget that Apex has Enums enumerated values. As a result, it’s fairly common to see code where a string variable is assigned various values and then checked against different values.
Whenever possible, I prefer enums.
What Apex tips and tricks do you have?