Andy in the Cloud

From BBC Basic to Force.com and beyond…


11 Comments

FinancialForce Apex Common Updates

This blog starts a series of updates leading up to Dreamforce 2014, where I am pleased to announce that my Advanced Apex Enterprise Patterns session has just been selected! In the coming series of blogs I will be covering enhancements to the existing base classes supporting the Apex Enterprise Patterns and highlighting some of the more general classes from within the FinancialForce Apex Common repository both reside in.

This time I will be highlighting some excellent contributions from fellow Force.com MVP Chris Peterson who has recently added more general utility classes to support security and dynamic queries. As well as some improvements from myself to the existing Domain and Selector classes.

In a following blog I’ll be going over in more detail the current results of some experimental work I’ve been doing relating to generic Field Level Security enforcement within the patterns base classes, meanwhile enjoy the new fflib_SecurityUtils class..

New fflib_SecurityUtils.cls

SecurityUtilsThe Salesforce Security Review currently requires that both object level and field level security is enforced by your code. The later of which, field level security has recently stirred up quite a lot of discussion and concern in the ISV community, more on this in the follow up blog post! In the meantime if you read the two Salesforce articles (here and here) describing the requirement and how to implement it in your Apex code (Visualforce offers some built in support for you). If like me, you’ll quickly realise the sample code provided is in reality somewhat verbose for anything more than a single object or field usage!

Enter the fflib_SecurityUtils class! As you can see from the UML representation shown here it’s methods are pretty simple and thus easy to use, an Apex exception is thrown if the user does not have access to the given object and/or fields. Here are some examples of it in use, you can choose to check individually or in bulk a set of fields and the object, covering both CRUD and Field Level Security.


fflib_SecurityUtils.checkObjectIsInsertable(Account.SObjectType);

fflib_SecurityUtils.checkInsert(
   Account.SObjectType,
   new List<Schema.SObjectField>{
      Account.Name,
      Account.ParentId, } );

fflib_SecurityUtils.checkUpdate(
   Lead.SObjectType,
   new List<Schema.SObjectField>{
     Lead.LastName,
     Lead.FirstName,
     Lead.Company } );

This class will also help perform object and field read access checks before making SOQL queries, though you may want to check out the features of the QueryFactory class as it also leverages this utility class internally.

New fflib_QueryFactory.cls

QueryFactory

The key purpose of this class is to make building dynamic SOQL queries safer and more robust than traditional string concatenation or String.format approaches. It also has an option to automatically check read security for the objects and fields given to it.

If your using Fieldsets in your Visualforce pages you’ll know that it’s generally up to you to query these fields, as you can see from the UML diagram, the class supports methods that allow you to provide the Fieldset name and have it automatically include those fields for you in the resulting query.

 

Chris has done an amazing job with this class not only in its feature and function but in its API design, leveraging the fluent model to make coding with it easy to use but also easy to read and understand. He first presented in at the FinancialForce DevTalks event this month, his presentation can be found here. In the presentation he gives some examples and discusses when you should use it and when not. So if your writing code like this currently…

String soql = ‘SELECT ‘;
for(Integer i = 0; i< fieldList.size(); i++){
  soql += fieldList + ‘, ‘;
}
soql = soql.substring(0,soql.length()-2);
soql += conditions != null && conditions.trim().size() > 0 ?  ‘ WHERE ‘ +
    soqlConditions : ‘’;
soql += limit != null && limit.trim().size() > 0 ? ‘ LIMIT ‘+limit;
List<Contact> nonBobs = Database.query(soql);

In it’s simplest form it’s use looks like this..

String soql =
  new fflib_QueryFactory(Contact.SObjectType)
    .selectField(Contact.Name)
    .setLimit(5)
    .toSOQL();

With object and field read security enforcement and Fieldset support would look like this…

String soql =
  new fflib_QueryFactory(Contact.SObjectType)
    .assertIsAccessible().
    .setEnforceFLS(true).
    .selectFields(myFields)
    .selectFieldSet(Contact.fieldSets.ContactPageFieldSet)
    .setCondition(‘Name != “Bob”’)
    .toSOQL();

The class is fully commented and the associated test class has further examples, also Chris is keen to work on API for the SOQL where clause in the future, i look forward to seeing it!

fflib_SObjectSelector.cls (Selector Pattern) Updates

I have updated this base class used to support the Selector pattern, to leverage the fflib_QueryFactory, in doing so you now have the option (as a constructor argument) to enable Field Level Security for fields selected by the selector. The default constructor and prior constructors are still supported, with the addition of the following that now allows you to control Fieldset, object and field level security enforcement respectively. For example…

OpportunitiesSelector oppsSelector =
    new OpportunitiesSelector(includeFieldSetFields, enforceObjectSecurity, enforceFLS);

NOTE: You can of course implement your own Selector default constructor and enable/disable these features by default within that, if you find yourself constantly passing a certain combination of these configurations parameters.

For custom selector methods you can leverage a QueryFactory constructed and initialised based on the Selector information, leaving you to add the additional where clause for the particular query logic the method encapsulates. Because of this you no longer need to add assertIsAccessible as the first line of your custom Selector methods. Prior to adopting QueryFactory a custom selector method might have looked like this…

public Database.QueryLocator queryLocatorReadyToInvoice()
{
  assertIsAccessible();
  return Database.getQueryLocator(
     String.format('SELECT {0} FROM {1} WHERE InvoicedStatus__c = \'\'Ready\'\' ORDER BY {2}',
     new List<String>{getFieldListString(),getSObjectName(),getOrderBy()}));
}

The updated patterns sample applications OpportunitiesSelector example to use the new newQueryFactory base class method, because this method pre-configures the factory with the selector object, fields, order by and fieldsets (if enabled), the new implementation is simplified and more focused on the criteria of the query the method encapsulates.

public Database.QueryLocator queryLocatorReadyToInvoice()
{
  return Database.getQueryLocator(
    newQueryFactory().setCondition('InvoicedStatus__c = \'\'Ready\'\'').toSOQL());
}

This updated fflib_SObjectSelector base class is backwards compatible from the API perspective, so you can choose to continue with the original String.format approach or adopt the newQueryFactory method accordingly. You can further review the old example here, against the new one here.

fflib_SObjectDomain.cls (Domain Pattern) Updates

This base class has to date had minimal functionality in it other than the routing of trigger events to the applicable virtual methods and object security enforcement. To support better configuration of these features and those in the future, i have added a new Domain class configuration feature, accessed via a new Configuration property.

Despite the focus on enforcing security in the above new features and updates, there are times when you want to enforce this in the calling code and not globally. For this reason the base class can now be configured to disable the object security checking (by default performed during the trigger after event), leaving it up to the calling code to enforce. Methods accessed from the new Configuration property can be used to control this.

public class ApplicationLogs extends fflib_SObjectDomain
{
  public ApplicationLogs(List<ApplicationLog__c> records)
  {
    super(records);
    Configuration.disableTriggerCRUDSecurity();
  }
}

Domain Trigger State

I have also been asked to provide a means to maintain member variable state between invocation of the trigger handler methods. Currently if you define a member variable in your Domain class it is reset between the before and after trigger phases. This is due to the default trigger handler recreating your Domain class instance each time.

If you want to retain information or records queried in the before handler methods in your class member variables such that it can be reused in the after handler methods, you can now enable this feature using the following configuration. The following illustrates the behaviour.

public class Opportunties extends fflib_SObjectDomain
{
  public String someState;

  public TestSObjectStatefulDomain(List<Opportunity> sObjectList)
  {
    super(sObjectList);
    Configuration.enableTriggerState();
  }

  public override void onBeforeInsert()
  {
    System.assertEquals(null, someState);
    someState = 'Something';
  }

  public override void onAfterInsert()
  {
    System.assertEquals('Something', someState);
  }
}

This feature is also aware of trigger recursion, meaning if there is such a scenario a new Domain class instance is created (since the records it wraps are new).


32 Comments

More power to your Flows in Summer’14

Since an earlier blog post describing how to hookup a Flow to a Custom Button, I have been promoting this #clicksnotcode platform feature further at my local DUG and recently the Salesforce1 World Tour London and internally within FinancialForce, the response has been great.

I have also been working on some new use cases showing the use of Flow from Workflow which is capability in pilot for Spring’14. Then before i knew it I had i had found even more new Flow features in my hands delivered via the upcoming Summer’14 release! You can read all about these features in the excellent Visual Workflow Implementation Guide. This blog provides step by step guide as to how I’ve explored these new features and a summary of their current and general availability. Note: The Flow Trigger functionality looks to remain in Pilot beyond Summer’14.

Flow SObject Collections Summer’14 (GA)

NewElements

Lets take a look at two new Resource types in Flow and how they work in conjunction with four new Data elements, known as Fast Create, Fast Read, Fast Update and Fast Delete. With these new elements you can drag them onto the Flow canvas as with the previous ones. The difference is these allow you to basically manage multiple records at once, or in bulk to use Apex term.

NewVariables

The Fast prefix comes from a reflection on what you would have to have done in the past to manipulate several records of the same object. The previous alternative was to create your own loop around the existing Create element creating a single record at time. Which in general is much slower and gives greater rise to hitting platform governors around the number of database operations that can be performed in a single Flow execution. Flow is grow up for greater volumes!

EnterAmountTo illustrate these new features i decide to implement in Flow something i have previously written using Apex code. The following use case is to Apply a user entered discount to selected Quote Line Items from the Related list. The flow will prompt the user for the Discount amount and they apply it, before returning the user back to the Quote detail page.

ApplyDiscount

Here is the high level steps i took to achieve this.

  1. Created a Flow that exposes an Input only variable of type SObject Collection and used by the new  Loop and Fast Update elements to perform the calculations and update the rows passed in.
  2. Created a Visualforce page (no Apex required) that uses the standard platform Selected field to pass in the users selected records (from a List View or Related List). This was a little more Visualforce than i wanted personally, but is still a pretty good template for other use cases with minimal changes required.
  3. Created a List View Custom Button and associated it with the above Visualforce page.
  4. Edited the Quote layout to add the above button the Quote Line Items related list

 

Lets take a look at the Flow I created and then I’ll go into some more detail on the Visualforce page needed to call it. First things first is to create an SObject Collection variable of the appropriate object type, in this case QuoteLineItem.

SObjectCollection

Keep a note of the Unique Name used, it will be important when we create the Visualforce page to call this flow. The next step is to loop over the SObject (or QuoteLineItem) records and apply the discount. The new Loop element is super easy to use, it has two arrows, one for each iteration and another arrow to point to the next step once all records in the collection have been processed.

ApplyDiscountFlow

The following screenshots show the elements in more detail. The Loop element uses new SObject Variable QuoteLineItem, for each record, which allows you to operate at the field level using the existing Assignment element. I also used the existing Formula functionality in Flow to perform the discount calculation. After this i added the record to a another SObject Collection variable that i would later pass to the Fast Update method.

The Visualforce page that runs the Flow looks similar to the one i used in the previous blog to invoke a Flow from the Detail Page Custom Button. The difference is passes in multiple record from those selected by the user via the Selected binding. There is some magic above the flow:interview element that ensures the fields used by the Flow are queried by the platform, otherwise an error occurs when the Assignment steps are executed stating the UnitPrice field has not been queried (I’m open to better ways of resolving this!).

<apex:page standardController="QuoteLineItem" recordSetVar="Quotes">
    <apex:repeat value="{!Selected}" var="SelectedRow" rendered="false">
        {!SelectedRow.QuoteId}{!SelectedRow.UnitPrice}
    </apex:repeat>
    <apex:variable var="QuoteId" value="{!Selected[0].QuoteId}"/>
    <flow:interview name="ApplyDiscount" finishLocation="/{!QuoteId}">
        <apex:param name="SelectedQuoteLines" value="{!Selected}"/>
    </flow:interview>
</apex:page>

Flow Triggers via Spring’14 (Pilot)

CreateElementThe use case I chose here was one i found on IdeasExchange, it related to someone who wanted to use Workflow to create a new child record when a parent record was inserted. In this demo i create a new Task child record whenever an Account is created, this could be for example, to ensure a follow up is made on the Account. The Flow i created was insanely simple, just one Flow variable (set to Input Only) and a Create element!

RecordCreate

Once this is created in my pilot org i found a new Workflow Action, called Flow Trigger. This Workflow action allowed me to pick the Flow and define any parameters i wanted to pass in. In this case the WhatId parameter which would later be used by the Flow when populating the Task fields to associate the task with the Account being created. Finally (not shown) i linked this new Workflow Action with a Workflow Rule to try it out.

FlowTriggers
FlowTriggerEdit

Any that was it! I created a new Account and sure enough my new Task appeared, no Apex code in sight!

TaskChild

Some thoughts and observations…

  • No UI Flows. Flow’s used in this context cannot use any Screen elements, and are thus known sometimes as “Headless” flows. The platform will automatically validate for this and prevent you assigning a UI Flow to a Flow Trigger.
  • Bulkification of Flow Triggers or not? Normally when doing things at a record level Apex developers have it drummed into them to think about bulk or multiple record situations (for example Data Loader use cases) not just a single record at a time. However you will notice this was not the case above? I did expect the new SObject Collection to take a role here but not so. What Salesforce attempts to do is internally bulk insert Tasks for you by running your Flow in parallel and synchronising the executions at the time they all need to insert a record to ensure it’s done optimally. This is cleverly transparent from the Flow designer and i think intentionally so, as it is quite an advanced topic for the target user of Flow. However i do wonder how well this will stand up to more complex Flow’s. No doubt why Salesforce is being so careful over how long this remains in Pilot.

When are these features available (Safe Harbour)?

FlowRoadmap