Nov 14

Associative Arrays in Flash Player 11.0.1.152

A user recently reported that he was unable to generate any dashboards while using DashConn within SAP Crystal Dashboard Design.  This set me off on what turned out to be an interesting and surprising investigation.

My main lead in the investigation was that the user was working with the recently released Flash Player 11.0.1.152.   Once I installed this update I also quickly reproduced the problem.

I found that an error:

TypeError: Error #1009: Cannot access a property or method of a null object reference.

was occurring in the DashConn code that was interacting with the Force.com Toolkit for Adobe AIR and Flex

Specifically this was occurring while iterating over the Field objects within a DescribeSObjectResult object.

 

for each(var fieldObj:Field in allSObjectFields)
{
 if (fieldObj.name.toUpperCase() == fieldName.toUpperCase())
 {
 return fieldObj;
 }
}

Diagnosis

Looking at the source code for DescribeSObjectResult it was quite perplexing how null Field objects could be associated with the fieldArray property. These fields are always assigned through the call to a constructor. See lines 10 and 11.

 

 public function DescribeSObjectResult(obj:ObjectProxy=null) {
 if (obj != null)
 {
 for (var key:String in obj) {
 var val:Object = obj[key];
 if (val is ArrayCollection || val is ObjectProxy) {
 if (key == "fields") {
 var fieldArray:Array = new Array();
 for (var i:int = 0;i<(val as ArrayCollection).length;i++) {
 var field:Field = new Field((val as ArrayCollection)[i]);
 fieldArray[field.name] = field;
 fieldArray.length++;
 }
 this[key] = fieldArray;
 } else if (key == "childRelationships") {
 var crArray:Array = new Array();
 var cr:ChildRelationship;

 if ( val is ObjectProxy ) {
 cr = new ChildRelationship(val as ObjectProxy);
 crArray[cr.relationshipName] = cr;
 crArray.length++;
 } else {
 for (var i2:int = 0;i2<(val as ArrayCollection).length;i2++) {
 cr = new ChildRelationship((val as ArrayCollection)[i2]);
 crArray[cr.relationshipName] = cr;
 crArray.length++;
 }
 }
 this[key] = crArray;
 } else if (key == "recordTypeInfos") {
 var rtArray:Array = new Array();
 var rt:RecordTypeInfo;

 if ( val is ObjectProxy ) {
 rt = new RecordTypeInfo(val as ObjectProxy);
 rtArray[rt.name] = rt;
 rtArray.length++;
 } else {
 for (var i3:int=0;i3<(val as ArrayCollection).length;i3++) {
 rt = new RecordTypeInfo((val as ArrayCollection)[i3]);
 rtArray[rt.name] = rt;
 rtArray.length++;
 }
 }
 this[key] = rtArray;
 }
 } else {
 this[key] = obj[key]
 }
 }
 }

Once I debugged into this code I discovered the surprise Flash Player had waiting — incrementing the length property on the Array was causing an additional key/value pair to be added to the Array with a key of 0 and a value of null!

Quick checks showed that this errant behavior also occurred with the other Array properties on DescribeSObjectResult.  Finally I created a simple test case which shows that the problem is  easily reproducible and occurs whenever the length property on an associative Array is incremented.  I’ve submitted the issue to Adobe https://bugbase.adobe.com/index.cfm?event=bug&id=3020393 .

If you are reading this because you’ve also come across this problem I encourage you to vote for this on the Adobe site.

Work Around

Since properly executed byte code should not produce null Field object values I did not want to change my code in the many places that iterate over the associative array properties of fields and childRelationships.  Instead I decided to post-process each DescribeSObjectResult immediately after it is retrieved from the request on the Connection.  This required a code change in only a couple of spots.


public function fixupDescribeSObjectResult(sobjResult:DescribeSObjectResult):void
{
     fixupAssociativeArray(sobjResult.childRelationships);
     fixupAssociativeArray(sobjResult.fields);
     fixupAssociativeArray(sobjResult.recordTypeInfos);
}

public function fixupAssociativeArray(values:Array):void
{
 if (values != null)
 {
     delete values[0];
 }
}

Using Array objects to store key/value hashes is discouraged as an ActionScript 3 practise.  Had the Force.com Toolkit for Adobe AIR and Flex followed the recommended approach of storing these in a plain Object this issue would have been avoided.  Perhaps a future update to the Toolkit will make this change.

Jun 21

Obtaining User Session state from a Visualforce page

When deploying non-native content such as Flash within a Visualforce page it is often necessary to pass user session information from the page into the content. This allows the embedded content to seamlessly use the session and not inconvenience the end user with an additional login prompt.

I first encountered this use case when starting development of DashConn using the Force.com Toolkit for Adobe AIR and Flex. This problem is supposed to have a very simple solution – access the User SessionId from the standard Visualforce global variable {!$Api.Session_ID} and pass this to the embedded content. At the time I soon encountered a bug where this SessionId did not correctly resolve to the user session. The result was that the login would fail within the Flash component.

As it turns out Visualforce pages maintain their own session id, different than the session id associated with Apex. The reason for this is that Visualforce pages have a different lifetime scope and communicate with different server URLs than Apex code. While both these unique session ids are intended to resolve to the same user session, this was not happening with the Visualforce SessionId.

The work-around for this issue was to instead use the session id obtained from Apex by implementing a simple custom Controller. This solution is documented here on the Force.com Discussion Boards.

I recently revisited this issue and happily discovered that the Visualforce global variable {!$Api.Session_ID} does now correctly resolve to the user session in Summer 2011. So the need for the custom controller appears to be gone.

One word of caution is that in following up with Salesforce.com support they could not find a specific fix put in at any time to address this bug. So hopefully this will continue to work correctly moving ahead!

Jun 21

SAP BusinessObjects Dashboards 4.0 Cookbook Review

SAP BusinessObjects Dashboards 4.0 Cookbook succeeds in providing “Over 90 simple and incredibly effective recipes for transforming your business data into exciting dashboards”.   The book’s 10 main chapters cover progressively more complex topics, and its unique design presents step-by-step recipes for completing specific tasks.

The possibilities for what one can accomplish with SAP BusinessObjects Dashboards 4.0 are indeed quite broad.  The authors have done a commendable job in selecting their recipes to cover common use cases most designers will face.  This approach allows readers confronted with a specific issue to skim through the Table of Contents for a relevant recipe and to then work through the provided example.

For example, the first chapter provides some straight-forward but quite useful time saving tips for working with the embedded Excel spreadsheet within SAP BusinessObjects Dashboards.  There one can quickly learn how to best use Excel’s cell formatting features.  This is typical of the nice balance the authors provide.  This brief introduction gives readers an appreciation for the possibilities for data manipulation and representation within the product, while leaving the exhaustive topics of Excel formulas, etc. to other reference materials.



The middle chapters of the book cover recipes for using the variety of out of the box product components and present detailed coverage of topics including alerting, interactivity, and dynamic visibility.  In the later chapters, one finds lessons for accessing dynamic server data.  I particularly liked the recipe for accessing SAP BusinessObjects universe data from your own website or portal without prompting dashboard users to login.  This lesson included both the necessary server side jsp code and client side html.

Another nice feature is that the book is up to date with the SAP BusinessObjects Dashboards 4.0 release, and contains recipes for using Universe queries and directly binding query data to other canvas components.

I have been working with the e-book version of the Cookbook and have been able to fully absorb lessons from many of the recipes by simply following along with the annotated color screenshots of Dashboard Design.  The corresponding (xlf) project files available as a separate download are a very useful addition when working through some of the later more involved recipes.

SAP BusinessObjects Dashboards 4.0 Cookbook is a recommended resource for a wide range of users. Dashboard designers new to the product as well as more experienced users will each find many useful recipes and gain an appreciation for extending these lessons to create their own best practices.