Use the Force Luke!

The “Force” in this case being Salesforce.com (or SFDC). If you haven’t heard of it, Salesforce.com is a cloud platform, Software as a Service (SaaS) offering for sales related activities. It also has modules for customer relationship management (CRM) as well as more general computing services.

You can sign up for a free developer account and find plenty of documentation to get you started here. SFDC allows you to create or modify database tables by creating custom objects or fields, query the data using a SQL like language  – SOQL (Salesforce Object Query Language) , write business logic in a Java like language called Apex and display code using Visualforce pages which is javascript with custom tags.

One thing to keep in mind when you start working with SFDC are the governor limits. Because you’re working in a shared environment, Salesforce doesn’t want you hogging all the resources so there are limits set to make sure things don’t get out of hand. When developing using Flex, you’re using a wrapper for the web services api so the “WSDL method” column in the link above is what you’re interested in. Basically, what this means is you should try and limit the number of queries you do (<100) and the amount of data you return for them (<10,000 rows).

One annoying factor  is that SFDC counts the number of rows it has to look at to perform a query to determine if you hit the limit so if you issue a query like “select count() from Opportunity” and you have more than 10,000 opportunity records, you’re going to get a system exception. Not only that, you can’t catch that type of exception so you’ll need to use a limit clause  if you think you’re going to get near that level.

Salesforce Flex APIs

There are two APIs for Flex provided by Salesforce. The older Flex toolkit SFDC page, Adobe Page which is basically a wrapper for the web services interface as a library swc file and a newer Flash builder interface SFDC page, Adobe page which is still currently in Beta and involves a custom version of the Flash builder tool. It seems to be suited more to Air apps working outside of SFDC as it contains data synchronization capabilities. For the rest of this post, I’m going to concentrate on the older API as it’s the one I’ve actually used for a deployed app. You can find documentation for the classes it provides here.

Internal or External

You can design your Flex app to run either within SFDC or as an external app (either hosted on your own webserver or as an Air application). If you’re going to run externally, your users will need to login to SFDC via your app to allow you to access the data.  When logging in externally, users must append a security token to the end of their password (from setup on the top of the page, My Personal Information on the left, Reset My Security Token) unless the ip address they are logging in on has been entered as a member of a trusted network (from setup, Security Controls, Network Access).

Regardless of how you connect to SFDC, the method of the Connection class you use is the same, login() the data you provide is what changes. For an external app, you’ll provide serverURL. username and password in your LoginRequest object, for an internal app, server_url and session_id.

Unless you have specific reasons not to, it makes sense to let SFDC host your Flex app and have your users access it in the same place they’re using for their other activities related to that data.

During development, I would hard code a login to run your app externally so you can use it with your debug player to get trace data etc and then convert it to use the internal SFDC data before you build it for deployment.

Deploying a Flex Application to Salesforce

Once you have a swf for your application, you can load it onto SFDC as a static resource. To do this, select setup, Develop, Static Resources, new, provide a name for your app and browse to the swf file on your machine.

Now you have the swf, you’ll need a wrapper page to access it. Select setup, Develop,Pages, new and you can enter your visualsource code to display the swf. If you’re going to be doing a lot of SFDC development, they provide an eclipse based IDE which is worth getting to know.

If you look at the getting started code through the “Flex toolkit” link above, you’ll see the use of an <apex:flash> tag. This works but causes a security warning pop up when running on IE which might cause problems for some of your users. The way around this is to use  swf wrapper code more like the example below.

You’ll need to use flashvars to import the session id and server url to your app (along with any other startup data you might want. I’ve had issues sometimes using the !API.Session_ID parameter so you’ll see a reference to !mySessionID in the code below which comes from the custom Apex class SessionUtil provided as the page controller which we’ll discuss later.

Here’s an example visualsource page for a Flex app:

<apex:page controller="SessionUtil" sidebar="false" showHeader="false">
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
  id="FlexAPP" width="1200" height="820"
  codebase="https://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">
  <param name="movie" value="{!$Resource.FlexAppName}" />
  <param name="quality" value="high" />
  <param name="bgcolor" value="#869ca7" />
  <param name="allowScriptAccess" value="sameDomain" />
  <param name="flashvars" value="uid={!$User.Id}&sid={!mySessionID}&surl={!$API.Partner_Server_URL_150}
  &name={!$User.FirstName} {!$User.LastName}" />
  <embed src="{!$Resource.FlexAppName}" quality="high" bgcolor="#869ca7"
    width="1200" height="820" name="Name of my App" align="middle"
    play="true"
    loop="false"
    flashvars="uid={!$User.Id}&sid={!mySessionID}&surl={!$Api.Partner_Server_URL_150}
    &name={!$User.FirstName} {!$User.LastName}"
    quality="high"
    allowScriptAccess="sameDomain"
    type="application/x-shockwave-flash"
    pluginspage="http://www.adobe.com/go/getflashplayer">
  </embed>
</object>
</apex:page>

The FlexAppName after $Resource is the name you gave the Static Resource for your swf file. You can get data from the user record for the user logged in using $User everything else is either boilerplate stuff or pretty obvious.

The Apex class SessionUtil needs to be added using Apex Classes under the Develop menu. Here’s the most basic version of it:

public class SessionUtil
{
    public String mySessionID {get; private set;}

    public SessionUtil() {
        mySessionID=UserInfo.getSessionId();
    }
}

You can expand on this to use SOQL queries to grab more data if you need it to initialize your app. This solution is based on the one provided by Wintermute (love that username!) I just didn’t want to work off a standard controller.

Once you have your page setup you can access it directly by <salesforce url>/apex/pagename or you can configure it to appear wherever Salesforce lets you reference a visualforce page (dashboard, custom links etc).

Tips for Developing using the Salesforce API

The API pages linked to above are a great place to start. Both the Adobe pages have videos going over what they provide and  Adobe evangelist James Ward has a number of great posts on both APIs.

Although the old API has been around for a while, it works perfectly well with Flex 4 – that’s what I built my app with.

The API documentation is pretty light and doesn’t go into a whole lot of detail – the thing to remember is it’s basically the web services API so you can usually find more detail looking at that documentation. Look for the “see also” link to Apex Developer Doc in the top description of the API class documents or go directly to the Web services API document.

The interface is asynchronous – you’ll declare a success and failure handler for each request. Usually you can reuse your fail handler and you should at least check for  “INVALID_SESSION_ID” so you can warn the user their session has timed out. Different Requests give rise to different result objects – QueryResult, SaveResult, UpsertResult so make sure your result handler is using the correct one for your request. All results are provided as an array.

A lack of a fault event does not necessarily mean your insert/update/upsert was successful. You need to check your result object for an id. Here’s an example upsert handler:


//upsert  handler
 private function handleUpsert(result:Object):void {
     if (!(result[0] as UpsertResult).id) {
     //failed to update/add
     trace('error on change: ' + (result[0] as UpsertResult).errors.getItemAt(0).message);
     Alert.show("Unable to update SalesForce: "+(result[0] as UpsertResult).errors.getItemAt(0).message,"Error");
     }
 }

Salesforce has field level security so one reason you’ll see an error is if your user does not have permission to write to that object or field.

Keep your SFDC interaction encapsulated in it’s own class and define data objects to carry the information you work on for the rest of your app. I used an XML file to generate the data I wanted within my Salesforce class initially, it gave me the chance to work on the display side while I was still figuring out my SFDC queries and generate data conditions to test for without having to alter data in SFDC. I could then switch that out for the real code without having to change anything else as the interface stayed the same.

Don’t forget to test logged in as your target users. As a developer, you’ll probably have a profile that allows you full access to everything, your users will likely be more restricted so you need to make sure they can access everything your app is going to need.

Advertisements