Appirio's Tech Blog

Tuesday, October 27, 2009

Developer Preview of the Adobe® Flash® Builder™ for Force.com

Jeff Douglas

Yesterday Salesforce.com released a developer preview of the Adobe® Flash® Builder™ for Force.com allowing developers to create powerful, engaging offline applications running on the Force.com platform. I had a chance to download the software, build a sample application and really go through all of the documentation.

The product, codename Stratus, is a jointly developed Eclipse-based IDE that combines the Force.com IDE, Flex 4 Builder beta, Flash 4 beta and LiveCycle Data Services and is tightly integrated with Force.com Connect Offline. It also includes a SQLite database embedded within the Adobe AIR runtime that provides the offline data cache of Salesforce.com data. There is no pricing available yet and Salesforce.com expects final delivery in the first half of 2010.

Adobe Flash Builder for Force.com

Salesforce.com states that you can create both Flex and Air applications with the new offering but it is apparent from their marketing materials, documentation and tutorials that it is squarely aimed for developing offline Air applications. I emailed Dave Carroll and he confirmed that the Force.com Toolkit for Adobe AIR and Flex is part of Stratus so you can use the same tool to build offline applications as well as applications that run inside the browser.

Stratus is a new data access and synchronization framework that ships with the offering. Stratus builds on the client-side data management included in Adobe LiveCycle Data Services, but does not include the LCDS server-side data management functionality. A LCDS license is included for Force.com but if you would like to connect to other backend system you'll have to contact Adobe for additional pricing. Stratus provides login functionality, network detection and online and offline data synchronization, a conflict resolution service, and UI components that look and act just like data input fields on Salesforce.com.

The framework includes:
  • Login functionality including a UI and error messages.
  • An API for making multiple, asynchronous, web service requests to the Force.com cloud to retrieve, save, or delete records.
  • UI components and data classes for displaying, editing, and managing local data changes.
  • The automatic creation and management of a local data store of salesforce.com data for offline support. When importing the Salesforce.com Enterprise WSDL, Stratus generates ActionScript classes for your objects on the Force.com platform.
  • An API for saving changes to both the local store and the Force.com cloud.
  • Automatic periodic synchronization of data between the local data store and the Force.com cloud.
  • Online and offline data synchronization and management.
  • Support for "select *" SOQL queries.

Dave Carroll has built a great video on installing, setting up a briefcase for offline data access and creating your first Adobe® Flash® Builder™ for Force.com application.

Adobe has created a developer site with links to relevant info as well as a tutorial Quick start: Create your first Force.com Flex desktop application. If you are interested in the architectural aspects of the offering, you should look at Understanding data management in applications built with Adobe Flash Builder for Force.com.

Wednesday, October 14, 2009

Integrated Gmail Add-In for Firefox

I came across a great new add-in for Firefox this afternoon. Personally, I have Firefox set to open Google Reader, Google Voice, and my Google Apps Mail app. The new Integrated Gmail feature for Firefox consolidates these windows into your Mail interface. Take a look below.

One of our most common questions asked is "How do I integrate my other Google services w/ Google Apps?". While they are still working on integrating the services, you can get a step closer to a fluid interface with community add-ins such as this one. Since this add-in is using iFrames to build the tabbed view of the Google services, you're out of the box experience is a bit awkward due to the multiple headers and search forms (one for each service in each tab). From the Tools -> Integrated Gmail menu in Firefox you can customize which of the <div> tags the add-in will render for each service. Basically, you can collapse all child headers and search forms... leaving a nice clean interface. I've only been using it a few hours now... but, seems to be keeping up nicely. We're always interested in community projects that drive the adoption of on-demand technology. Drop us a line if you want to introduce us to new solutions!

(P.S. Only complaint so far... they snuck in a free ware feature on the Calendar tab for a third party free / busy type service. I have no opinion of that service, having never used it, but I'd rather enable my own features. Take note of it and make your own decision. But, be advised it's enabled by default)

Other Views...

With the sidebar collapsed

With both the sidebar and the header collapsed


Friday, October 2, 2009

Preventing Recursive Future Method Calls In Salesforce

Jeff Douglas

Governor limits are runtime limits enforced by the Force.com platform to ensure that your code doesn’t, among other things, hog memory resources, lock up the database with an excessive amount of calls or create infinite code loops. Working within governor limits requires you to sometimes become creative when writing Apex.

One way to work within Force.com platform limits as to use asynchronous Apex methods with the future annotation. Calls to these methods execute asynchronously when the server has available resources and are subject to their own additional limits:
  • No more than 10 method calls per Apex invocation
  • No more than 200 method calls per Salesforce.com license per 24 hours
  • The parameters specified must be primitive dataypes, arrays of primitive datatypes, or collections of primitive datatypes.
  • Methods with the future annotation cannot take sObjects or objects as arguments.
  • Methods with the future annotation cannot be used in Visualforce controllers in either getMethodName or setMethodName methods, nor in the constructor.
  • You cannot call a method annotated with future from a method that also has the future annotation. Nor can you call a trigger from an annotated method that calls another annotated method.
One issue that you can run into when using future methods is writing a trigger with a future method that calls itself recursively. Here is a simple scenario. You have a trigger that inserts/updates a record (or a batch of them) and then makes a future method call that performs more processing on the same record(s). The issue is that this entire process becomes recursive in nature and you receive the error, “System.AsyncException: Future method cannot be called from a future method…” Here is what it looks like:


mockup



There are a couple of ways to prevent this recursive behavior.

1. Add a new field to the object so the trigger can inspect the record to see if it is being called by the future method.

The trigger checks the value of IsFutureContext__c in the list of Accounts passed into the trigger. If the IsFutureContext__c value is true then the trigger is being called from the future method and the record shouldn’t be processed. If the value of IsFutureContext__c is false, then the trigger is being called the first time and the future method should be called and passed the Set of unique names.

trigger ProcessAccount on Account (before insert, before update) {
Set<String> uniqueNames = new Set<String>();
for (Account a : Trigger.new) {
if (a.IsFutureContext__c) {
a.IsFutureContext__c = false;
} else {
uniqueNames.add(a.UniqueName__c);
}
}
if (!uniqueNames.isEmpty())
AccountProcessor.processAccounts(uniqueNames);
}


The AccountProcessor class contains the static method with the future annotation that is called by the trigger. The method processes each Account and sets the value of IsFutureContext__c to false before committing. This prevents the trigger from calling the future method once again.

public class AccountProcessor {

@future
public static void processAccounts(Set<String> names) {
// list to store the accounts to update
List<Account> accountsToUpdate = new List<Account>();
// iterate through the list of accounts to process
for (Account a : [Select Id, Name, IsFutureContext__c From Account where UniqueName__c IN :names]) {
// ... do you account processing
// set the field to true, since we are about to fire the trigger again
a.IsFutureContext__c = true;
// add the account to the list to update
accountsToUpdate.add(a);
}
// update the accounts
update accountsToUpdate;
}

}


2. Use a static variable to store the state of the trigger processing.

According to the Apex docs, static variables are used to store information that is shared within the confines of a class. All instances of the same class share a single copy of the static variable. All triggers that are spawned by the same request can communicate with each other by referencing static variables in a related class. A recursive trigger can use the value of this class variable to determine when to exit the recursion. I’ve used this method many times before and was pleasantly surprised to find that this class is also shared when calling a method annotated as future.

The shared ProcessControl class with the static variable that is shared by the trigger and used to determine when to exit the process.

public class ProcessorControl {
public static boolean inFutureContext = false;
}


In this case the trigger inspects the current value of the static variable ProcessorControl.inFutureContext to determine whether to process the records. If the value is false, then the trigger is being called the first time and the future method should be called and passed the Set of unique names. If the value is true then the trigger is being called from the future method and the records should not be processed.

trigger ProcessAccount on Account (before insert, before update) {
Set<String> uniqueNames = new Set<String>();
if (!ProcessorControl.inFutureContext) {
for (Account a : Trigger.new)
uniqueNames.add(a.UniqueName__c);

if (!uniqueNames.isEmpty())
AccountProcessor.processAccounts(uniqueNames);
}
}


With this methodology, the method with the future annotation processes each Account and sets the value of the shared static variable to false before committing the records. This prevents the trigger from calling the future method once again.

public class AccountProcessor {

@future
public static void processAccounts(Set<String> names) {
// list to store the accounts to update
List<Account> accountsToUpdate = new List<Account>();
// iterate through the list of accounts to process
for (Account a : [Select Id, Name From Account where UniqueName__c IN :names]) {
// ... do your account processing
// add the account to the list to update
accountsToUpdate.add(a);
}
ProcessorControl.inFutureContext = true;
// update the accounts
update accountsToUpdate;
}

}


One of these examples should work in most cases with one caveat. With the increased usage of future method in installed packages, you may run into problems if your trigger is called from other package’s future method. You’ll again run into the “System.AsyncException: Future method cannot be called from a future method…” error. What Salesforce needs is an Apex function that determines whether the method is currently executing in a future call.


ideas-logo
Vote for this Idea

ISFUTURE Function in APEX


Please Note: In the case our Account object contains a unique string field thereby making it easy to call the same code from an insert or update. Your org will probably not have this field so you will need to make some change to pass the IDs to the future method based upon whether you are doing an insert or update.
 
2006-2010 Appirio Inc. All rights reserved.
Appirio.com | Support | Resource Center | Contact | Careers | Privacy Policy