function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
VintaraVintara 

Flex applications and force.com authentication.

I have an existing application developed with Adobe Flex and the Salesforce Flex/Flash object library. My understanding is that the current implementation requires a browser authenticated session for the Flex application to inherit in order to connect to the Salesforce data objects. However, there is no such authentication occurring if I try to host my app in a force.com site.

Any thoughts as to how to resolve this issue? Perhaps user authentication through force.com? However that option seems to be disabled in the developer preview.
WardsterWardster
I am having this problem too.  I think my problem might be with the SessionId and URL settings I'm passing in as parameters.  I'm having trouble location the documentation on these $API properties/methods.

VintaraVintara
As far as I can tell, there is no session ID being set.
WardsterWardster
Vintara,

I finally solved this problem but it wasn't easy to figure out.  In order to get this working I had to create an SControl for my Flex component.  When you call the SControl versions of $API.Session_ID, it gives you the proper id to interact with the Web Services API.  Obviously, this is only important if you need to do a query from your Flex.  In the SControl component I put all the code from the "main.html" which is generated when you build your Flex component with the Flex Builder.  I think by default it goes into the "bin-debug" directory of your Flex project.  I also loaded up the AC_OETags.js file into Salesforce.  I loaded all my components as Documents -- the Javascript and the Flash file -- rather than Static Resources.  The AC_OETags.js creates the Object and Embed tags on the fly and tries to attach .swf to the end your url.   I don't believe you can load up a document with a file extension as a static resource.

There is also an undocumented issue with Salesforce connection object.  You need to declare a connection object in your code and point the connection to specific server to resolve a connection error.  I believe this has to do with some security enhancements which Adobe made to the flash plugin recently.

 
Code:
[Bindable]
 private var sfdc:Connection = new Connection();
 
 private function login(): void {
                initVariables();
                sfc.login(  new LoginRequest({
                    server_url : this.parameters.server_url,
                    session_id : this.parameters.session_id,
                    // put your own info here to test standalone
                    username : 'blahblah@blahblahblah.com',
                    password : 'xxxxxxxx',
                    callback : new AsyncResponder(render, faultHandler)
                   
                   })
                );

            }
           
            // initializes the building id variable
            private function initVariables():void {
                modelId = Application.application.parameters.modelId;
                sfc.protocol = "https";
                sfc.serverUrl = "https://na6.salesforce.com/services/Soap/u/14.0";
            }

 

VintaraVintara
Not sure I follow, I have a simple sControl with HTML configurations for the Flex object. I'm then loading it into the flex.com page using an iFrame with a srouce of {!$SControl.Vintara__sControlName}.

Are you saying I should put a javascript login system to ensure that the API.Session_ID is set?


Code:
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="FlexSalesforce" width="100%" height="100%"
codebase="https://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">
<param name="movie" value="{!Scontrol.JavaArchive}" />
<param name="quality" value="high" /><param name="play" value="true" />
<param name="bgcolor" value="#f3f3ec" /><param name="allowScriptAccess" value="always" />
<param name="flashvars" value="session_id={!API.Session_ID}&server_url={!API.Partner_Server_URL_110}&js_xml=true" />
<param name="allowScriptAccess" value="sameDomain" />
<param name="allowFullScreen" value="true" />

<embed src="{!Scontrol.JavaArchive}" play="true" bgcolor="#f3f3ec" width="100%" height="700"
name="FlexSalesforce" align="middle"
flashvars="session_id={!API.Session_ID}&server_url={!API.Partner_Server_URL_110}&js_xml=true""
loop="false" allowScriptAccess="always"
type="application/x-shockwave-flash"
allowFullScreen="true"
pluginspage="http://www.adobe.com/go/getflashplayer">
</embed>
</object>

 


WardsterWardster
Vintara:

I didn't find that worked for me, but I'm not sure our situations are exactly the same.  When I just laid the HTML as you have in an SControl the $API.Session_ID worked fine.  I could login to Salesforce but I couldn't get the record id of my custom object to populate dynamically to the Flashvars.  The result was a poorly formed query with an error.  It looks like to me though that the last parameter of your flashvar param string is static: 
js_xml=true

So the static approach might work for you with plain ol' html. I don't know what you'll need an SControl full of javascript to building the <Object> and <Embed> tags dynamically. One other thing your partner server url

!API.Partner_Server_URL_110

is perhaps a little out of date. We're up to version !API.Partner_Server_URL_140 now I believe.

I'm then loading it into the flex.com page using an iFrame with a srouce of {!$SControl.Vintara__sControlName}

This statement confuses me a little.
SControls get put into an IFrame automatically without doing anything. Just wanted to make sure you're not adding complexity to your deployment that you don't need, by inadvertantly creating an IFrame within another IFrame.

Here is the code for my SControl:

Code:
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title></title>
<script src="https://na6.salesforce.com/servlet/servlet.FileDownload—file=01581000000cfLF" language="javascript"></script>
<style>
body { margin: 0px; overflow:hidden }
</style>
<script language="JavaScript" type="text/javascript">
<!--
// -----------------------------------------------------------------------------
// Globals
// Major version of Flash required
var requiredMajorVersion = 9;
// Minor version of Flash required
var requiredMinorVersion = 0;
// Minor version of Flash required
var requiredRevision = 124;
// -----------------------------------------------------------------------------
// -->

function getUrlParam( name ){
  name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
  var regexS = "[\\–&]"+name+"=([^&#]*)";
  var regex = new RegExp( regexS );
  var results = null;
  try   {
   results = regex.exec( window.parent.location.href );
  }
  catch (err)   {
    results = regex.exec( document.referrer );
  }

  if( results == null )   {
    alert("Unable to find parameter " + name);
    throw new Error("Unable to find parameter " + name);
  }
  else { 
    return results[1];
  }
    
}



</script>
</head>

<body scroll="no">
<script language="JavaScript" type="text/javascript">
<!--
// Version check for the Flash Player that has the ability to start Player Product Install (6.0r65)
var hasProductInstall = DetectFlashVer(6, 0, 65);

// Version check based upon the values defined in globals
var hasRequestedVersion = DetectFlashVer(requiredMajorVersion, requiredMinorVersion, requiredRevision);

if ( hasProductInstall && !hasRequestedVersion ) {
 // DO NOT MODIFY THE FOLLOWING FOUR LINES
 // Location visited after installation is complete if installation is required
 var MMPlayerType = (isIE == true) ˜ "ActiveX" : "PlugIn";
 var MMredirectURL = window.location;
    document.title = document.title.slice(0, 47) + " - Flash Player Installation";
    var MMdoctitle = document.title;

 AC_FL_RunContent(
  "src", "playerProductInstall",
  "FlashVars", "MMredirectURL="+MMredirectURL+'&MMplayerType='+MMPlayerType+'&MMdoctitle='+MMdoctitle+"",
  "width", "100%",
  "height", "100%",
  "align", "middle",
  "id", "main",
  "quality", "high",
  "bgcolor", "#f8f8f8",
  "name", "main",
  "allowScriptAccess","sameDomain",
  "type", "application/x-shockwave-flash",
  "pluginspage", "http://www.adobe.com/go/getflashplayer"
 );
} else if (hasRequestedVersion) {
 
 var modelId = getUrlParam('id');
 // if we've detected an acceptable version
 // embed the Flash Content SWF when all tests are passed
 
 AC_FL_RunContent(
   "src", "https://na6.salesforce.com/servlet/servlet.FileDownload™file=01581000000cgAc",
   "width", "100%",
   "height", "100%",
   "FlashVars", "sessionId={!API.Session_ID}&serverUrl={!API.Partner_Server_URL_140}&modelId=" + modelId,
   "align", "middle",
   "id", "main",
   "quality", "high",
   "bgcolor", "#f8f8f8",
   "name", "main",
   "allowScriptAccess","sameDomain",
   "type", "application/x-shockwave-flash",
   "pluginspage", "http://www.adobe.com/go/getflashplayer"
 );
  } else {  // flash is too old or we can't detect the plugin
    var alternateContent = 'Alternate HTML content should be placed here. '
   + 'This content requires the Adobe Flash Player. '
    + '<a href=http://www.adobe.com/go/getflash/>Get Flash</a>';
    document.write(alternateContent);  // insert non-flash content
  }
// -->
</script>
<noscript>
   <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
   id="main" width="100%" height="100%"
   codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">
   <param name="movie" value="https://na6.salesforce.com/servlet/servlet.FileDownload?file=01581000000cgAc" />
   <param name="quality" value="high" />
   <param name="bgcolor" value="#f8f8f8" />
   <param name="allowScriptAccess" value="sameDomain" />
   <embed src="https://na6.salesforce.com/servlet/servlet.FileDownload?file=01581000000cgAc" quality="high" bgcolor="#f8f8f8"
    width="100%" height="100%" name="main" align="middle"
    play="true"
    loop="false"
    quality="high"
    allowScriptAccess="sameDomain"
    type="application/x-shockwave-flash"
    pluginspage="http://www.adobe.com/go/getflashplayer">
   </embed>
 </object>
</noscript>
</body>
</html>

 







Message Edited by Wardster on 12-17-2008 01:28 PM

Message Edited by Wardster on 12-17-2008 02:04 PM
testortestor
I cut and pasted your code segment Wardster and it wouldn't compile for me.  "Undefined property sfc" and undefined property faulthandler were two of the errors.

WardsterWardster
Vintara:

Here is a revised code sample of the complete component.

Code:
<—xml version="1.0" encoding="utf-8"–>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
 xmlns:salesforce="com.salesforce.*" 
 layout="horizontal"
 applicationComplete="login();" backgroundGradientAlphas="[1.0]" backgroundColor="#F8F8F8" backgroundImage="">

      
     <mx:Script>
        <![CDATA[
        
            import mx.collections.ArrayCollection;
            import mx.controls.Alert;
            import mx.utils.ObjectUtil;
        
            import com.salesforce.results.*;
            import com.salesforce.events.*; 
            import com.salesforce.objects.*;
            import com.salesforce.*;
            
            [Bindable]
            private var revenueExpectedArray:ArrayCollection = new ArrayCollection();
            [Bindable]
            private var revenueReportedArray:ArrayCollection = new ArrayCollection();
            [Bindable]
            private var buildingId:String;
                      
            
            private function login(): void {
             initVariables();
             sfc.login(  new LoginRequest({
           server_url : this.parameters.server_url,
           session_id : this.parameters.session_id,
           // put your own info here to test standalone
           username : 'xxxx@xxxxxxx.com',
           password : 'xxxxxxxxxx',
           callback : new AsyncResponder(render, faultHandler)
           
                })
                );

            }
            
            // initializes the building id variable
            private function initVariables():void {
             buildingId = Application.application.parameters.buildingId;
             // Alert.show(buildingId);
                //buildingId = "a0G80000000xF4xEAE";
                sfc.protocol = "https";
                sfc.serverUrl = "https://na6.salesforce.com/services/Soap/u/14.0";
            }
            
            private function faultHandler(fault:Object):void {
             Alert.show(ObjectUtil.toString(fault));
            }
            
            private function render(result:Object):void {
             var numberOfRevenueExpectedRecords:int = 6;
       sfc.query("Select Date__c, Month_Year__c, Revenue_Expected__c From Revenue_Entry__c WHERE Building__c = '" + buildingId + "' AND Revenue_Expected__c != null ORDER BY Date__c DESC LIMIT " + numberOfRevenueExpectedRecords,
       new AsyncResponder(
        function (qr:QueryResult):void {
                  
         if(numberOfRevenueExpectedRecords < qr.size){
          numberOfRevenueExpectedRecords = qr.size;
         }
         // we've gotten the last six records now we need to iterate backwards through the results
         for (var j:int=numberOfRevenueExpectedRecords - 1;j >= 0;j--  ) {
                      revenueExpectedArray.addItem( {Month:qr.records[j].Month_Year__c, Value:qr.records[j].Revenue_Expected__c/1000000});
                  }
                  
                 
              }, function (fault:Object):void {
                   faultHandler(fault);
              }
        ));
        var numberOfRevenueReportedRecords:int = 6;
        sfc.query("Select Date__c, Month_Year__c, Revenue_Reported__c From Revenue_Entry__c WHERE Building__c = '" + buildingId + "' AND Revenue_Reported__c != null ORDER BY Date__c DESC LIMIT " + numberOfRevenueReportedRecords,
                 new AsyncResponder(
                    function (qr:QueryResult):void {
                     
                     if(numberOfRevenueReportedRecords < qr.size){
                            numberOfRevenueReportedRecords = qr.size;
                        }
                     // we've gotten the last six records now we need to iterate backwards through the results
                        for (var j:int=numberOfRevenueReportedRecords - 1; j >= 0;j--  ) {
                            revenueReportedArray.addItem( {Month:qr.records[j].Month_Year__c, Value:qr.records[j].Revenue_Reported__c/1000000});
                        }
                       
                    }, function (fault:Object):void {
                         faultHandler(fault);
                    }
                 ));
            }


            
        ]]>
        
        
    </mx:Script>
    
    <salesforce:Connection id="sfc" />

    
    <mx:Stroke id = "s1" color="blue" weight="2"/>
    <mx:Stroke id = "s2" color="red" weight="2"/>
    
    <mx:SeriesInterpolate id="interpolateIn" duration="1000"/>
    
    
     <mx:Panel title="Revenue Entries" layout="horizontal" color="0xffffff" borderAlpha="1.0" width="963" height="429"
         paddingTop="10" paddingRight="5" paddingBottom="10" paddingLeft="5" horizontalAlign="center" borderColor="#00335B">
   <mx:LineChart id="revenue_entry_chart" width="710" dataProvider="{revenueReportedArray}" showDataTips="true" fontFamily="Arial" height="350" color="#000000">
 
       <mx:horizontalAxis>
                    <mx:CategoryAxis  id="x_axis" categoryField="Month"/>
                </mx:horizontalAxis>
                <mx:horizontalAxisRenderers>
                    <mx:AxisRenderer axis="{x_axis}" showLine="true" showLabels="true"/>
                </mx:horizontalAxisRenderers>
                
                <mx:verticalAxis>
                 <mx:LinearAxis id="y_axis" title="Revenue in Millions ($)" />
               </mx:verticalAxis>
                <mx:verticalAxisRenderers>
                    <mx:AxisRenderer axis="{y_axis}" showLine="false" showLabels="true"/>
                </mx:verticalAxisRenderers>
                                    
    <mx:series>
     <mx:LineSeries displayName="Revenue" yField="Value" lineStroke="{s2}" showDataEffect="{interpolateIn}"/>
    </mx:series>
   </mx:LineChart>
   
   <mx:VBox color="0x323232" width="30%" borderColor="0x9096A1" borderStyle="solid" height="352"
             paddingLeft="5" paddingRight="0" paddingTop="5">
             
             <mx:Text color="#000000" width="100%" text="Choose a data series:"/>
             
             <mx:RadioButton groupName="stocks" label="Revenue Reported"
                 selected="true" click="revenue_entry_chart.dataProvider=revenueReportedArray;"/>
             <mx:RadioButton groupName="stocks" label="Revenue Expected"
                 click="revenue_entry_chart.dataProvider=revenueExpectedArray;"/>
            </mx:VBox>
   
  </mx:Panel>
  
 
</mx:Application>

 

gtuerkgtuerk

I'm having a similar problem and wonder if there is an easy answer here.  I can get data just fine, hooking into prod, hardcoding my connection information.  When I try to monkey with parameterizing this so that the page (visualforce, not sControl) passes in flashvars

"session_id={!API.Session_ID}&server_url={!API.Partner_Server_URL_90}"
, I can't do that with a page that has a standard controller so I removed all the other code on the page including the standardController tag for the page and just made the page the embedded flex object.  The query appears to be 'spinning' - the bottom of the page shows 'Transferring data from cross-domain.xml but nothing comes back.  any ideas on how to debug this?

 

 

private function login(event:Event):void {
                var lr:LoginRequest = new LoginRequest();
                lr.server_url = parameters.server_url;
                lr.session_id = parameters.session_id;
                lr.callback = new AsyncResponder(getCandidateSOs);
                connection.login(lr);
            }
   
    private function getCandidateSOs(o:Object=null):void
    {
        connection.query("Select Id, Name, Product__c, Account__c from Service_Order__c where Order_Stage__c = 'Customer Signature'"
        , new AsyncResponder(
        function (qr:QueryResult):void {
            candidateSOs.dataProvider = qr.records;
        }));
    }

Message Edited by gtuerk on 02-04-2009 02:40 PM
fgwarbfgwarb

The $ in front of the Visualforce global variables are missing, which would explain why no data was being passed (don't know if this was a requirement back in Feb-09.) 

 

"session_id={!$API.Session_ID}&server_url={!$API.Partner_Server_URL_90}"

 

 

I'm trying to parameterize as well (swf in test org gets test org data, swf in prod gets prod data operating as the logged in user) as well by using the session_id passed via flashvars.  I'm getting the session ID, but no query results.  Any assistance would be greatly appreciated!

 

Here's the approach as of this posting:

 

 

var lr:LoginRequest = new LoginRequest();
lr.callback = new AsyncResponder(loginSuccess, loginFailure);
lr.server_url = parameters.ent_URL; //$API.Enterprise_Server_URL_190
lr.session_id = parameters.usrSess_id; //$API.Session_Id
force.login(lr);

 

--Edit--

The toolkit doesn't seem to support the Enterprise endpoint; replacing that with the $API.Partner_Server_URL_190 made this function.  

--end edit--