Thursday, November 29, 2007

Placing Flex Error/Fault Information on the Clipboard

The Flash method flash.system.System.setClipboard(String) is a very useful utility function. This method allows a Flash application to put a String onto the user's Clipboard. In this blog entry, I'll provide a simple example of a use I really like for this functionality. It is very convenient during Flex development to have my fault handler methods automatically put fault and error information into my clipboard so that I can easily paste the text messages associated with the error in my application or text editor of choice.

The following code listing (Clipboard.mxml) shows a simple MXML application that demonstrates the utility of the System.setClipboard(String) method.


<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:flash.display="flash.display.*"
width="500" height="300"
applicationComplete="breakMe();">

<mx:Script>
<![CDATA[
/**
* To compile solely this Flex application from the command line, use
* mxmlc -strict=true Clipboard.mxml
*
* This application demonstrates use of the flash.system.System.setClipboard()
* function. The application intentionally tries to access an unavailable
* HTTPService so that the application's default fault handler is invoked and
* that invoked fault handler then puts its fault message on the clipboard.
*/

import mx.controls.Alert;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.utils.ObjectUtil;

/**
* Handle successful result of web service or HTTP service associated with
* this result handler.
*
* @param aResultEvent Successful event.
*/
private function resultHandler(aResultEvent:ResultEvent):void
{
trace( "Successfully returned from "
+ aResultEvent.currentTarget.toString() );
}

/**
* Handle fault result of web service or HTTP service associated with this
* fault handler.
*
* @param aFaultEvent Fault event.
*/
private function faultHandler(aFaultEvent:FaultEvent):void
{
const faultEventTarget:String = ObjectUtil.toString(aFaultEvent.currentTarget);
const faultErrorId:int = aFaultEvent.fault.errorID;
const faultErrorCode:String = aFaultEvent.fault.faultCode;
const faultErrorDetail:String = aFaultEvent.fault.faultDetail;
const faultString:String = aFaultEvent.fault.faultString;
const faultMessage:String = aFaultEvent.fault.message;
const faultName:String = aFaultEvent.fault.name;
const faultErrorString:String =
"Fault " + faultErrorId + " (" + faultName + "):\n"
+ "[" + faultErrorCode + "]\n\n"
+ "FAULT MESSAGE: " + faultMessage + "\n\n"
+ "FAULT DETAILS: " + faultErrorDetail + "\n\n"
+ "FAULT STRING: " + faultString;;
const faultVerboseErrorString:String =
faultErrorString + "\n\n" + "FAULT ON TARGET:\n" + faultEventTarget;
trace(faultVerboseErrorString);
Alert.show(faultErrorString, "Intentional Fault Occurred");
flash.system.System.setClipboard(faultVerboseErrorString);
}

/**
* Function intended to intentionally call a non-existent HTTP Service to
* lead to its fault handler being invoked.
*/
private function breakMe():void
{
brokenService.send();
}
]]>
</mx:Script>

<mx:HTTPService id="brokenService"
resultFormat="e4x"
url="http://marxsoftware.blogspot.com/"
result="resultHandler(event);"
fault="faultHandler(event);" />

</mx:Application>


In the above code listing, I intentionally caused a fault handler to be invoked when the specified HTTPService could not access the provided URL. I took advantage of the information associated with a Fault for all forms of error output (trace(), Alert, and clipboard), but the information on the "current target" associated with the fault event is too verbose for the Alert. Therefore, I only included that information in the trace() and set it to the clipboard. Because the trace output may not always be available (such as when the application is not executed in a Flash Debug Player or a debugger is not connected), it is handy to have this same information sitting in my clipboard waiting for me to paste it into my favorite text editor or IDE.

I intentionally used a different toString() method in the result handler than I used in the fault handler. The toString called directly on ResultEvent.currentTarget only outputs a single line of information (essentially identifying the current target as an HTTPService). The ObjectUtil.toString() applied to the FaultEvent.currentTarget supplies significantly more detail and that is why its output needed to not be placed in the alert. I have compared the inherited Object.toString to the static ObjectUtil.toString(Object) in greater detail in a previous blog entry.

A screen capture of the output of this forced error is shown next:



This Alert pop-up was intentionally kept rather small by not including the lengthy target information in the output. However, that target information was included in the trace() call and to the clipboard. I cannot really show it here in a way that does it justice, but a very handy thing I can do at this point is to open a text editor and simply "paste" (CTRL-V, "Paste" option, etc.) into the editor. The text shown next will be inserted despite the fact that I never did a "copy" explicitly.


Fault 0 (Error):
[Channel.Security.Error]

FAULT MESSAGE: faultCode:Channel.Security.Error faultString:'Security error accessing url' faultDetail:'Destination: DefaultHTTP'

FAULT DETAILS: Destination: DefaultHTTP

FAULT STRING: Security error accessing url

FAULT ON TARGET:
(mx.rpc.http.mxml::HTTPService)#0
channelSet = (mx.messaging::ChannelSet)#1
channelIds = (Array)#2
[0] "direct_http_channel"
clustered = false
configured = false
connected = true
currentChannel = (mx.messaging.channels::DirectHTTPChannel)#3
channelSets = (Array)#4
[0] (mx.messaging::ChannelSet)#1
connected = true
connectTimeout = -1
endpoint = "http:"
failoverURIs = (Array)#5
id = "direct_http_channel"
protocol = "http"
reconnecting = false
requestTimeout = -1
uri = ""
messageAgents = (Array)#6
[0] (mx.rpc::AsyncRequest)#7
channelSet = (mx.messaging::ChannelSet)#1
clientId = "DirectHTTPChannel0"
connected = true
defaultHeaders = (null)
destination = "DefaultHTTP"
id = "E671BD31-DE99-42D6-7453-8F6F1FE32BC4"
requestTimeout = -1
session = (null)
subtopic = ""
concurrency = "multiple"
contentType = "application/x-www-form-urlencoded"
destination = "DefaultHTTP"
headers = (Object)#8
lastResult = (null)
makeObjectsBindable = true
method = "GET"
request = (Object)#9
requestTimeout = -1
resultFormat = "e4x"
rootURL = "file:///C:/flexExamples/Clipboard/Clipboard.swf"
showBusyCursor = false
url = "http://marxsoftware.blogspot.com/"
useProxy = false
xmlDecode = (null)
xmlEncode = (null)


As you can see, the information on the current target associated with the handled event is much more verbose than the fault information itself. Rather than having to subject myself to so much text in the Alert window or having to try to view the trace output in a debugger window, it was nice to be able to simply paste it all into a favorite text editor. Note that I can always redirect trace output to a file, but this setClipboard(String) tactic is a nice backup in case I forget to do that or forget to run in the appropriate mode or simply do not want to deal with that effort.

One other interesting observation is that Fault.message contains the contents of Fault.faultCode, Fault.faultDetail and Fault.faultString. This means, of course, that you'd normally not need to output all four properties and could go with just Fault.message to get the contents of the other three.

The examples associated with the Flex 2 Language Reference documentation on the flash.system.System class show using a handy property of this class (totalMemory) and writing that to the clipboard with setClipboard(String).

The section "Saving Text to the Clipboard" in the Programming ActionScript 3.0 System Class write-up is what originally gave me the idea of using the flash.system.System.setClipboard(String) method to place error and fault information in the clipboard for easy pasting. Thanks to the author(s) of that for a very useful idea!

Finally, the documentation makes it very clear that there is no getClipboard() method because of security concerns associated with the ability to grab data off of a user's clipboard.

JFreeChart 1.0.8 Released

Dave Gilbert recently announced the release of JFreeChart 1.0.8. In my tests, all of the sample code from Visualize Your Oracle Database Data with JFreeChart worked correctly against this new release. This is not very surprising because the 1.0.8 changes sound like mostly fixes to bugs introduced with JFreeChart 1.0.7 changes.

UPDATE: A 1.0.8a (7 December 2007) version of JFreeChart is now available online at http://sourceforge.net/project/showfiles.php?group_id=15494. It appears that this version may have been released to fix the security vulnerability associated with HTML image maps originally discovered and identified by Rapid7.

Wednesday, November 28, 2007

Oracle-Related Conferences News

RMOUG Training Days 2008

The Rocky Mountain Oracle Users Group (RMOUG) Training Days 2008 Schedule-At-A-Glance is now available here. The two presentations that I will be giving at RMOUG Training Days 2008 are Excel with Apache POI and Oracle Database (Wednesday, February 13, 2008, Session 3, 1:30 pm - 2pm) and Introduction to XQuery: A Multipurpose XML Tool (Thursday, February 14, 2008, Session 7, 8:30 am - 9:30 am).

Oracle OpenWorld 2007

Oracle Corporation has also provided many of the presentations from Oracle OpenWorld 2007 online under Content Catalog. The required username and password are displayed on this page along with fields for searching for desired presentations. The presentations include coverage of Ruby on Rails, PHP, Java EE, and SOA in addition to the expected Oracle-specific product and services coverage. Other resources available at the main Oracle OpenWorld 2007 page include PDF versions of the daily newspaper provided at the conference and keynote addresses.

Tuesday, November 27, 2007

Not So Stupid Java Questions

Question #20 (Primitives and Collections) in the (Not So) Stupid Java Questions series was published today. I have found this to be an interesting series because some of the questions are about things that never would have crossed my mind to do or try and because the answers are all over the board. The answers section for each question is free for anyone to contribute to and the answers posted vary from very insightful, to less insightful, to not even related to the question, to downright wrong.

Until fairly recently, there was no single page (that I could find anyway) that linked to all of the questions. In am effort to remedy this, Sachin posted a blog entry with some (first 15) of the questions and I was maintaining a page with links to each of the questions (first 18). I was pleased to see that these pages are no longer necessary because there is now a central page with links to all of the questions and it is updated as new ones are added. This provide a single location to look these up and reference them when desired. The URL to this page is http://today.java.net/pub/ct/9.

Sahoo's Javac Plugin for Persistence.xml Generation

In the article Better JPA, Better JAXB, and Better Annotations Processing with Java SE 6, I wrote about using JAXB to generate a Java Persistence API (JPA) object-relational mapping (ORM) file (usually called orm.xml) from in-source JPA annotations. In that article, I mentioned Sahoo's blog on using the Java 5 apt tool to generate a persistence.xml file. Sahoo has now posted a blog entry on A javac Plugin to Manage Your persistence.xml in which he demonstrates using javac in different contexts (directly, Maven, etc.) to generate a JPA persistence.xml file.

In a related blog, Sahoo lists some of his observations and experiences using the Java SE 6 annotation processor.

The persistence.xml file and the orm.xml (or one or more files fulfilling the same purpose) are the two main outside-of-code configuration files needed with JPA. The OTN article I cited above talks about generation of the orm.xml or equivalent file from in-source annotations and Sahoo's blogs cover creation of the persistence.xml file.

Monday, November 26, 2007

JAXX and JFreeChart

JAXX is an XML-based user interface framework for developing Swing applications. As such, JAXX looks and feels like OpenLaszlo's LZX language and Flex's MXML language. Like LZX and MXML, JAXX code is written primarily in XML and supports scripting in special tags within the XML. In the case of JAXX, the scripting language is Java (compared to a JavaScript subset for OpenLaszlo and to ActionScript 3 for Flex 2 MXML).

JAXX shares other characteristics with OpenLaszlo LZX and Flex MXML. All three frameworks support an id attribute to uniquely identify each tag in the XML. The id attribute provides a handle for code in the script to access what is in the XML elements. JAXX also supports data binding, a very nifty feature of both Flex MXML and OpenLaszlo LZX. In fact, its syntax is exactly like Flex's MXML binding syntax (use of curly braces { and } around binding) and very similar to OpenLaszlo's LZX binding syntax (curly braces with $ in front similar to Ant).

In our article Visualize Your Oracle Database Data with JFreeChart, Michael Martin and I demonstrated an extremely simple example of using JFreeChart in conjunction with a Swing application (Code Listing 4 and Figure 7). In this blog entry, I will be adapting that example to use JAXX rather than direct Swing (JAXX compiles into Swing).

JAXX can be downloaded at http://www.jaxxframework.org/wiki/Download and can be installed as described at http://www.jaxxframework.org/wiki/Installing_JAXX. The version of JAXX that I used for this example is JAX 1.0.2. The zip file you download for this is well under 1 MB. Installation consists of unzipping the downloaded file (expanded directories and files still come in under 1 MB), setting JAVA_HOME to point to your JDK directory (this may already be the case on your system for Ant or other Java-based applications to use), and placing the JAXX installation's bin directory in your environment's path.

The following code listing shows the JAXX code for my file jaxxexample.jaxx (notice the extension .jaxx).

<Application title="Jaxx Example Using JFreeChart"
width="750"
height="450">
<JLabel id="mainLabel"
icon="{generateBarChartImage()}" />
<script>
private ImageIcon generateBarChartImage()
{
org.marx.hr.charting.HrChartCreator chartCreator =
new org.marx.hr.charting.HrChartCreator("");
org.jfree.chart.JFreeChart barChart =
chartCreator.createSalaryPerFinanceEmployeeBarChart(
org.jfree.chart.plot.PlotOrientation.VERTICAL );
return new ImageIcon(barChart.createBufferedImage(750,450));
}
</script>
</Application>


The above code is compiled using the following syntax (assuming that JAXX has been downloaded and installed as described previously):


jaxxc -cp "C:\jfreechart\articleSourceCode\visualizeOracleDb\build\classes;C:\jfreechart\jfreechart-1.0.7\lib\jfreechart-1.0.7.jar" -keep jaxxexample.jaxx


There are several things worth special mention regarding the jaxxc compilation shown above.

First, jaxxc works much like javac in terms of available options. The -keep option keeps the intermediate .java files and another option (-java, not shown here) only generates the .java files without building the corresponding .class files.

Second, I needed to place quotation marks around my classpath after the -cp if I had more than one path in the classpath designation. A single path in the classpath worked appropriately (compiled), but having more than one without the quotes led the JAXX compiler to showing its usage instead of compiling the .jaxx file. For this example, I did need two paths: one to the Java class with the chart generation code and one to the JFreeChart library.

After the .class files have been generated (and in this case, the .java file was retained as well), the code needs to be run to show JAXX in action. The following command was used to run this code:


java -cp .;C:\jaxx-1.0.2\lib\jaxx-runtime.jar;C:\jfreechart\articleSourceCode\visualizeOracleDb\build\classes;C:\jfreechart\jfreechart-1.0.7\lib\jfreechart-1.0.7.jar;C:\jfreechart\jfreechart-1.0.7\lib\jcommon-1.0.12.jar;C:\batik-1.7\batik.jar;C:\iText\itext-2.0.2.jar;C:\jdevstudio1111\jdbc\lib\*;C:\jdevstudio1111\lib\* jaxxexample


The highlighted portion of the classpath shows that the JAXX runtime JAR is necessary for running this code compiled with jaxxc. Several other libraries must be added to this classpath as well because the included chart generation class access iText (for PDF), Batik (for SVG), and JDeveloper (for Oracle datasource) libraries. Notice that no quotations are needed for multiple paths in this classpath because this is a normal Java launcher executable. Quotes are not needed for Java's javac and java commands to use multiple paths in their classpaths.

When the above command is run with the Java application launcher, output similar to that shown in the next snapshot should be displayed (click on image to see larger version):



Not surprisingly, this image looks very similar to that in Figure 7 of the article that was generated with straight Swing. This is not surprising because JAXX compiles first to Swing. Ideally, I'd have most of the code in the <script> tag in the JAXX example in a separate Java class so that very little scripting would be in the file and it would be almost all XML.

There is much more to JAXX than what is shown here. This blog entry is merely an introduction to an approach to non-web Java HMIs that is very similar to that used in OpenLaszlo and Flex.

I have just started to investigate JAXX, but have already made a few observations in addition to those listed above that are worth consideration.

  • Perhaps the best method for further investigating JAXX is to read the newbie-friendly article Introducing JAXX: A New Way To Swing. This article is written by JAXX's author, Ethan Nicholas.

  • Ethan Nicholas also presented on JAXX at JavaOne 2006: User Interfaces in XML: The JAXX Framework.

  • It appears that JAXX has not been significantly supported in over a year. The last "News" release on the main page (as of today, November 26, 2007) is dated October 9, 2006, and announces the release of JAX 1.0.3-beta (I'm using JAXX 1.0.2 final for this article and that was announced in August 2006). Similarly, the most recent entry in the JAXX Announcements Forum is dated June 12, 2006, and announces JAXX 1.0.1. These observations, coupled with related observations noted below, create some questions about the current and future state of JAXX.

  • The JAXX Main Page is a Wiki and it seems that someone thought it was a good idea to add links to various lewd messages at the top of many of the JAXX Wiki pages.

  • The JAXX General Chat Forum has over 4000 messages, but this seems to be mostly due to it being overrun by spam.

  • The JAXX How Do I ... Forum does have some non-spam, fairly recent postings, but they are not numerous.

  • In Swing: Its Past, Present, and Future, Hans Muller has nice things to say about JAXX.

  • Having significantly more experience with XML-oriented presentation languages like JavaServer Pages (JSPs), LZX, and MXML than with Java Swing, there is much conceptually about JAXX that appeals to me. I really like the binding support in OpenLaszlo and Flex and like the idea of a Java framework providing this for simple but powerful event handling. However, a significant hurdle for JAXX is lack of the wide community support that MXML and LZX enjoy.

  • A common complaint in OpenLaszlo and Flex forums is the lack of an IDE or lack of features in the available IDEs for developing in these environments or the cost of any available IDEs. JAXX suffers from lack of an IDE and this is especially noticeable because of the powerful Java IDEs that are available and provide Swing GUI builders. This and other limitations are also noted in "JAXX ... Oh My."

Saturday, November 24, 2007

More on ActionScript 3 String Equality Comparison Operators (== Versus ===)

In my last blog entry, I contrasted String equality comparison in ActionScript 3 with String equality comparison in Java. In that blog entry, I brought up the difference in the == and === comparison operators. Generally, it doesn't matter which of these are used in ActionScript when strict type checking is on (compiled with -static=true option) because the compiler reports errors when checking values of two different data types against each other. However, when the application is compiled with -static=false, two values of different data types can be compared and that is where the difference between == and === become interesting (they actually are different!).

For this example, I'll start with the code in the last blog entry, but it is enhanced with some more comparisons. In particular, this example code compares an int against a String with == and ===. As written in the example below, the code only compiles with static explicitly set to false. To make the the code compile with -static=true, the highlighted lines must be changed as described after the example.


<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:flash.display="flash.display.*"
width="750" height="500"
applicationComplete="compareComparisonOperators();">

<mx:Script>
<![CDATA[
/**
* To compile solely this Flex application from the command line, use
* mxmlc -strict=true -output StrictStringComp.swf StringComparison2.mxml
* and
* mxmlc -strict=false -output NotStrictStringComp.swf StringComparison2.mxml
*
* This application demonstrates use of and nuances associated with
* ActionScript 3 String comparisons.
*/

import mx.containers.Panel;
import mx.controls.Alert;

private const firstString:String = "Privacy";

/**
* Demonstrate how == and === work with Strings in ActionScript.
*/
private function compareComparisonOperators():void
{
const origString:String = "An Interesting String";
const sortOfSameString:String = "An Interesting String";
const sameString:String = origString;

const panel:Panel = new Panel();

const compareOrigStringToSortSameStringWith2Eq:Boolean =
origString == sortOfSameString;
const compareOrigStringToSortSameStringWith3Eq:Boolean =
origString === sortOfSameString;

const origStrToSortSameStr2Eq:Label = new Label();
origStrToSortSameStr2Eq.text =
"Original string == same chars: "
+ String(compareOrigStringToSortSameStringWith2Eq);
panel.addChild(origStrToSortSameStr2Eq);

const origStrToSortSameStr3Eq:Label = new Label();
origStrToSortSameStr3Eq.text =
"Original string === same chars: "
+ String(compareOrigStringToSortSameStringWith3Eq);
panel.addChild(origStrToSortSameStr3Eq);

// Result in same Strings, but of different types.
const origNumberString:String = "111";
const origNumber:int = 111;

const compareNumberStringToNumberWith2Eq:Boolean =
origNumberString == origNumber;
const compareNumberStringToNumberWith3Eq:Boolean =
origNumberString === origNumber;

const numStrToNum2Eq:Label = new Label();
numStrToNum2Eq.text =
"Numeric content String == Numeric: "
+ String(compareNumberStringToNumberWith2Eq);
panel.addChild(numStrToNum2Eq);

const numStrToNum3Eq:Label = new Label();
numStrToNum3Eq.text =
"Numeric content String === Numeric: "
+ String(compareNumberStringToNumberWith3Eq);
panel.addChild(numStrToNum3Eq);

const intValue:int = 10;
const uintValue:uint = 10;
const compareIntToUInt2Eq:Boolean = intValue == uintValue;
const compareIntToUInt3Eq:Boolean = intValue === uintValue;

const intToUInt2Eq:Label = new Label();
intToUInt2Eq.text = "int == uint: "
+ String(compareIntToUInt2Eq);
panel.addChild(intToUInt2Eq);

const intToUInt3Eq:Label = new Label();
intToUInt3Eq.text = "int === uint: "
+ String(compareIntToUInt3Eq);
panel.addChild(intToUInt3Eq);

compareComparisonOperatorsBox.addChild(panel);
}

/**
* Compare string entered into input text (providedString) to constant
* String assigned to firstString.
*/
private function compareString():void
{
const textInputString:String = providedString.text;
if ( textInputString == firstString )
{
statusValue.text = "Same Strings!";
statusValue.setStyle("color", "0x00FF00");
statusResultValue.setStyle("color", "0x00FF00");
}
else
{
statusValue.text = textInputString
+ " is not the same String.";
statusValue.setStyle("color", "0xFF0000");
statusResultValue.setStyle("color", "0xFF0000");
}
providedString.text="";
statusResultValue.text = String(textInputString == firstString);
}
]]>
</mx:Script>

<mx:HDividedBox id="mainBox" width="100%" height="100%">
<mx:VBox id="interactiveComparisons" width="50%" height="100%">
<mx:Label id="stringPrompt"
text="Enter a String to compare to '{firstString}':" />
<mx:TextInput id="providedString" enter="compareString();"/>
<mx:HBox>
<mx:Label id="statusLabel" text="Status" />
<mx:Label id="statusValue" text="None tried" />
</mx:HBox>
<mx:HBox>
<mx:Label id="statusResultLabel" text="Status Result" />
<mx:Label id="statusResultValue" text="None tried" />
</mx:HBox>
</mx:VBox>
<mx:VBox id="compareComparisonOperatorsBox" width="50%">
</mx:VBox>
</mx:HDividedBox>

</mx:Application>


As the comments in the code itself suggest, this can be compiled with the static flag turned on and with it turned off. I have added the -output option to differentiate the compiled .swf files produced for each setting of that flag. The -output and -strict flag are described in more detail in About the Application Compiler Options - Flex 2.01.

When running the version generated with -strict=false (NotStrictStringComp.swf), the following output is generated (click on image to make it larger):



There are a few interesting observations from the output in the snapshot above:

1. The == and === comparison operators provide different results when comparing the String "111" to the int 111. The equality operator == returns true when comparing the String "111" to the int 111 while the strict equality operator === returns false for the same comparison. The reason for the different result is that == checks only for equality in terms of value (so "111" does resolve to the same value as 111) while the === operator checks for value equality (like ==) and adds on a check for same data type as well (so false because int and String are not the same data type).

2. Unlike Java's == comparison used on Strings, neither ActionScript equality comparison operator actually checks to make sure the two compared values are the identical piece of data. In Java, when == is used to compare two Strings, it is check that they are not only the same value of data, but are exactly the same piece of data. ActionScript's == is more like Java's String.equals() and its === operator is unlike anything Java has (or needs) because Java is a statically typed language.

3. The comparison operators == and === return true when comparing an int to an unsigned int. This demonstrates that the strict equality comparison operator treats int and uint as the same data type because they are in the same type family. In fact, comparing an int and a unit even compiles when the -static=true flag is sent.


If one tries to compile the code above as-is in strict mode, compiler errors are reported when attempting to compile the code that compares a String to an int. The snapshot below (click on it to make it larger) shows these error messages.



The obvious observation here is that while comparing a String to an int produces different results for == (true if the String value is the same as the int value) and === (returns false no matter what the values of the String and int because they are different data types), comparing a String and int will not even compile in static mode.

To make the code above compile, one must surround the int in the comparison with the global function String(). This converts the int to a String for the comparison and the compiler allows this through. However, in such a case, there will not be any difference between behavior of == and === because now two Strings (same data type) are being compared for equality.

The edited relevant code to make it compile in strict mode is shown next.


const compareNumberStringToNumberWith2Eq:Boolean =
origNumberString == String(origNumber);
const compareNumberStringToNumberWith3Eq:Boolean =
origNumberString === String(origNumber);


Here is the output of running the slightly edited code compiled in static mode (click on image to make it larger):



As expected, all comparisons with == and === return true for same values because they also happen to be of same type in all cases.

Friday, November 23, 2007

String Comparisons (for Equality) in ActionScript 3

While Java and ActionScript have much in common in terms of syntax, their respective handling of String comparisons are a little different.

Many of us learned early in our Java experience that we should generally compare Strings in Java using the String.equals() method rather than using the normal Java equality operator (==) because normally we wanted the equals() method behavior rather than the == behavior. The reason for this is normally we want to know if two Strings consist of the same characters in the same positions and equals provides true if that is the case. Using Java's == operator on the other hand, only returns true in a comparison of Strings if they are literally the same object and not just the same characters.

When using ActionScript, the developer's "default String comparison thinking" shifts from typically using equals to typically using ==. In fact, ActionScript's String class does not even have an equals() method. ActionScript also supports a comparison operator with three equals signs (===), but this seems to behave the same for most String comparison cases I have tried, so I typically stick to the two equals signs version (==).

The following code example (StringComparison.mxml) exercises the == operator to compare two ActionScript Strings.


<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:flash.display="flash.display.*"
width="500" height="300">

<mx:Script>
<![CDATA[
/**
* To compile solely this Flex application from the command line, use
* mxmlc -strict=true StringComparison.mxml
*
* This application demonstrates use of and nuances associated with
* ActionScript 3 String comparisons.
*/
private const firstString:String = "Privacy";

/**
* Compare string entered into input text (providedString) to constant
* String assigned to firstString.
*/
private function compareString():void
{
const textInputString:String = providedString.text;
if ( textInputString == firstString )
{
statusValue.text = "Same Strings!";
statusValue.setStyle("color", "0x00FF00");
statusResultValue.setStyle("color", "0x00FF00");
}
else
{
statusValue.text = textInputString
+ " is not the same String.";
statusValue.setStyle("color", "0xFF0000");
statusResultValue.setStyle("color", "0xFF0000");
}
providedString.text="";
statusResultValue.text = String(textInputString == firstString);
}
]]>
</mx:Script>

<mx:HDividedBox id="mainBox" width="100%" height="100%">
<mx:VBox id="interactiveComparisons" width="50%" height="100%">
<mx:Label id="stringPrompt"
text="Enter a String to compare to '{firstString}':" />
<mx:TextInput id="providedString" enter="compareString();"/>
<mx:HBox>
<mx:Label id="statusLabel" text="Status" />
<mx:Label id="statusValue" text="None tried" />
</mx:HBox>
<mx:HBox>
<mx:Label id="statusResultLabel" text="Status Result" />
<mx:Label id="statusResultValue" text="None tried" />
</mx:HBox>
</mx:VBox>
</mx:HDividedBox>

</mx:Application>


The output for this code when compiled and run is shown in the next two screen shots (click on each image to see larger version):

Output When Entered String is NOT a Match



Output When Entered String IS a Match



If you switch the one highlighted line of code from using == to using ===, the resulting output behavior does not change and the output snap shots would match those above. This is because the comparison ends up comparing Strings, so the type is the same. The only way to see a difference between == and === is to turn off strict compiling and to try to test two different data types with the same core value.

According to MDC JavaScript 1.5 documentation, the === operator checks data type in addition to content and that additional check of type is what separates it from ==. However, with ActionScript 3's more strict data type checking, the compiler often reports this anyway (as long as you compile in strict mode, the default) and I have not found a realistic case where a String comparison in ActionScript differs between == and ===. It might be useful to differentiate between == and === when running non-strict code to ensure that data types are the same as well as content, but I'd normally rather run in strict mode and have the compiler checking this all the time.

If you have run into a realistic situation in which an ActionScript String comparison has differed because of your choice of == versus ===, please feel free to add that to the comments section below. The only way I can see that this would happen is if the code was compiled explicitly in non-strict mode. Because I always compile in strict mode (code example shows that it should be compiled with mxmlc -strict=true StringComparison.mxml), I never see a difference between == and ===. Note that the default is to strictly compile, so you'd need to explicitly state -strict=false to the compiler to see a difference between == and ===.

UPDATE: See another blog entry for additional details on == and ===.

Thursday, November 22, 2007

Using Flex Debugger (fdb) with Flex-Based Browser Hosted Application

In a previous blog entry, I discussed three ways to log or audit Flash applications based on Flex code. In this blog entry, I focus on using the Flex SDK command-line debugger fdb.

It is easiest to use the fdb command-line Flex debugger if the fdb application is in your platform's path. The fdb.exe (for Windows) and fdb script (for Unix) are in the same bin subdirectory under the Flex SDK as are the Flex compiler (mxmlc.exe or mxmlc) and the ASDoc executables (asdoc.exe and asdoc). So, if you already have your path set up so that the Flex compiler is in it, the fdb debugger should already be in your path. If you don't have fdb in your path, you can always run it directly from the bin subdirectory in the Flex SDK installation.

Most web users install the normal Flash Player because they do not need debug capabilities. However, to take advantage of Flash debugging capabilities, Flex developers will want to have the Flash Debug Player installed on their development browsers. The Flash Debug Player can be downloaded at http://www.adobe.com/support/flashplayer/downloads.html (look for "debugger versions"). Once the debug Flash Player is downloaded, install that on your favorite browser according to the download/installation instructions.

Assuming that you have fdb in your path (or are willing to run it directly from the directory in which it resides) and you have installed a Flash debug player on your web browser, you can begin using fdb with the following steps:

1. Compile the Flex Application with Debug Flag Turned On (true)

Compile your Flex code (MXML and ActionScript) with the mxmlc application compiler and be sure to set the option -debug=true. In the example I am using in this blog entry, this command is run as: mxmlc -debug=true -strict=true DemonstrateFlexDebugger.mxml

This is similar to compiling Java programs with its debug flag turned on. It allows the debugger to provide line numbers of errors and additional stack trace information just as the debug flag does for Java. Line numbers can also be included in stack traces when the mxmlc compiler option -verbose-stacktraces is set to true, but setting -debug=true automatically sets this option to true.

A snapshot of how running this Flex compiler looks is shown next (click on image to see larger version):


In this blog entry, I cover how to run the command-line Flex Debugger (fdb) that comes with the Flex SDK.

2. Run fdb in a Console/Terminal Window

To run the command-line debugger, simply run "fdb" if fdb is in your path as described above or else run "fdb" from the bin subdirectory in your Flex 2 SDK installation. You should see a couple lines of introductory information about the command-line debugger and a prompt (fdb) that waits for your input. Typing "help" here (optional) will allow you to see the options you have with this debugger. For this blog entry, we'll go directly to the "run" command. Type run at the (fdb) prompt and you should see the message "Waiting for Player to connect."

3. Run .swf File in Web Browser with Flash Debug Player

The fdb debugger won't do much for you if you don't run the Flash application you've just compiled (the .swf file compiled from your Flex code in Step #1) in a browser equipped with the Flash Player Debugger. In fact, I'll show in the debug example below that even some errant code does not produce any negative output when the special debug player is not installed. This makes a lot of sense because most of us don't want stack traces spewing out on clients' and customers' machines.

The easiest way to run the .swf file in the browser is to simply open that file in the browser and, assuming the Flash Player is properly installed on the browser, the browser will begin to render the Flash application. For a more realistic test, you could load any wrapper HTML file you have for your Flash application.

I stated the browser will "begin to render the Flash application" because you probably will only see a mostly blank page at this point. This is a hint that you need to move onto the next step.

4. Instruct fdb Command-line Debugger to 'continue' Twice

In Step #2, we ran "fdb" and then started fdb listening for an application to debug with the "run" command. Once we have loaded the .swf file into our browser, it will not be fully rendered because the fdb command-line debugger will be waiting for input from us to allow the application to proceed in loading. Specifically, the fdb debugger, which had said it was "Waiting for Player to connect," will not have recognized a Flash Player Debugger trying to run a Flash application. The fdb compiler will tell you that a Player has been connected and that a session has started. It will also explain that you can set breakpoints at this time and that you should enter 'continue' to proceed once you've entered desired breakpoints. For this example, we won't enter any breakpoints and will just type continue. The fdb debugger will continue some additional file loading and instruct you to enter 'continue' again to proceed. We will not enter breakpoints now either and will simply enter continue to proceed.

5. Watch fdb Output and React Appropriately

From this point on, because we did not enter any break points, the fdb command-line tool will display anything that we had in trace() statements in our ActionScript code as that code is executed in the web browser. The only further interaction you would normally have with the fdb tool as this point is to start stepping through code once you hit a break point or if an error occurred. You need to enter continue whenever errors are flagged in fdb to move on in processing.

There is obviously much more one can do with fdb and its help menu (mentioned earlier) provides many of these useful features and their keywords. Because this entry is already longer than I had planned, I am going to show only a very simple case here. I may revisit fdb in a future blog entry to cover some of its other goodies, but they are pretty easy to experiment with once the basics covered in this entry are understood.

For the code we will be processing in fdb, I have constructed a simple MXML file (DemonstrateFlexDebugger.mxml) and a simple ActionScript file (SampleClass.as) that the MXML file imports. They are both shown next:

DemonstrateFlexDebugger.mxml

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:flash.display="flash.display.*"
width="500" height="300"
applicationComplete="doSomeStuffToBeDebugged();">

<mx:Script>
<![CDATA[
/**
* To compile solely this Flex application from the command line, use
* mxmlc -debug=true -strict=true DemonstrateFlexDebugger.mxml
*
* This application provides code to be run through the Flex SDK debugger
* (fdb). The following steps must be followed to use fdb to debug this code.
*
* <ol>
* <li>Compile (mxmlc) Flex application with -debug=true option.</li>
* <li>Run fdb by typing "fdb" at the command prompt.</li>
* <li>In terminal or console window in which "fdb" was run (last step), type
* "run"</li>
* <li>Run compiled Flex application (.swf file) in web browser with
* Flash Debugger Player installed.</li>
* <li>Type "continue" in fdb console window twice (can set breakpoints before
* either continue</li>
* </ol>
*
* Debugging information from the web browser running the Flex application
* will display in the fdb window via trace() statements in the Flex code.
* Execution in the fdb debugger window normally stops only for break points
* or for certain types of errors that require "continue" for the fdb debugger
* to continue on.
* </ol>
*/

import SampleClass;
import mx.controls.Alert;

/**
* Provide some code to be debugged.
*/
private function doSomeStuffToBeDebugged():void
{
trace("This is the doSomeStuffToBeDebugged() method!");
const sample:SampleClass = new SampleClass();
Alert.show(sample.getNullName());
//const sample2:SampleClass = null;
//Alert.show(sample2.getDataName());

}
]]>
</mx:Script>

<mx:HBox id="mainBox">
<mx:Label id="Notice"
text="Run fdb and run this app in Flash Debugger Player" />
</mx:HBox>

</mx:Application>


SampleClass.as

package
{
/**
* This class provides code to be exercised in the fdb debugger.
*/
public class SampleClass
{
private const cName:String = "SampleClass";
private var valuableData:String = "Valuable Data";
private var dataName:String = "The Data with No Name";
private var nullName:String = null;

/**
* Constructor.
*/
public function SampleClass()
{
const mName:String = "SampleClass [constructor]";
logMethodEntry( mName );
}

/**
* Provide my valuable data.
*
* @return My valuable data.
*/
public function getValuableData():String
{
const mName:String = "getValuableData()";
logMethodEntry( mName );
return valuableData;
}

/**
* Provide my Data Name.
*
* @return My Data Name.
*/
public function getDataName():String
{
const mName:String = "getDataName()";
logMethodEntry( mName );
return dataName;
}

/**
* Provide my null name.
*
* @return My null name.
*/
public function getNullName():String
{
const mName:String = "getNullName()";
logMethodEntry( mName );
return nullName;
}

/**
* Log entry to the method whose name is passed in (aMethodName).
*
* @param aMethodName Name of method whose entry needs to be logged.
*/
private function logMethodEntry(aMethodName:String):void
{
trace( "Entered method " + cName + "." + aMethodName + "." );
}
}
}


In the MXML code above, I intentionally defined a variable, sample2, of type SampleClass, but assigned it to null. This allowed me to have an issue that would be flagged by the debugger to demonstrate some interesting aspects of using fdb and the Flash Player Debugger.

Here is a summary of the steps to debug the application shown above:

1. Prerequisite: I set my path to include the bin directory of the Flex 2 SDK installation so that mxmlc and fdb were in the path.

2. Prerequisite: I downloaded the Flash Player 9 Debugger and installed that on my Firefox installation.

3. I compiled my simple example with the command: mxmlc -debug=true -strict=true DemonstrateFlexDebugger.mxml - It was important to specify the -debug=true command. Note that I did not need to include SampleClass.as in the compilation because the Flex compiler knew to look for it and compile it because of its import inside of the MXML file. The output of running this compiler command was named the same as the input MXML file, but with a .swf extension -- in this case, DemonstrateFlexDebugger.swf.

4. I started the command-line Flex 2 SDK debugger in a console with the command fdb and then entered run at the (fdb) prompt.

5. I opened DemonstrateFlexDebugger.swf in Firefox via its File->Open File option. The browser did not fully load the Flash application because it was waiting on the debugger to allow it to continue loading (see next step).

6. I entered continue and then another continue in the command-line fdb tool and watched the rest of the output from my Flash application.

At this point, with the highlighted lines in the code above still commented out, the debug process was finished. An example of how all of this looks in the console window in which fdb was run is shown next (click on image to make it larger). You can look for the (fdb) prompts to see what I needed to enter (initial invoking of fdb executable followed by run and then continue and continue). You can also see the output from the trace() calls I included in my ActionScript code both in the MXML file and in the separate ActionScript class.






Ensure That All Steps of the Debugging Process Are Followed

I cannot overemphasize the importance of compiling with -debug=true, with having a Flash Player Debugger installed on your browser, and in running fdb to listen to debugger output from the debug-enabled Flash application running on the Debug Player. The rest of this entry covers what types of information you will miss during debugging if any one of these steps is left out.

To make things more interesting, I removed the comments from the two highlighted lines of code above so that they'd be executed. The main thing about these lines is that a variable is declared that is initialized to null and then the code tries to use that null object. This leads us to something of interest in terms of debugging.

Had I defined sample2 without assigning it to anything, the compiler would have warned me about an uninitialized variable. As coded above, however, with sample2 initialized to null, the compiler compiles completely successfully without errors or warnings. It is at runtime where this will bite us and that is where the debugger shines!

When I have complied (mxmlc) with -debug=true and have executed the compiled .swf file on a browser with a Flash Player Debugger (with or without fdb running), I see the following output when trying to run the code against a null (click on image to enlarge it):



If I fail to compile my application with -debug=true, but I do have a Flash Player Debugger installed on my browser, I see the following output (click on image to enlarge):



The two examples above both displayed error messages to in my browser because the Flash Debug Player was installed. However, the example where the code was compiled with -debug=true is more informative and includes line numbers to help in the debug process. Note that neither example provided trace() statement output or in any other way gave me any idea of the values of different properties and variables during execution.

If I fail to install the Flash Player Debugger on my web browser, it doesn't matter how I compile my Flex application because I won't see any debug information at all. The next image shows this case. Note that there is no pop-up message warning of any problem. The application just doesn't work quite right (the troublesome code is seemingly ignored), but the user does not have to deal with a messy stack trace. This is good for an end user, but not very helpful for the developer.



In the three above examples, I did not really address whether fdb was being run in the console or not. Whether fdb is being run or not does not affect the output you see above for those three cases. If you don't have the Flash Player Debugger on your browser, you won't see any debug information regardless of whether or not fdb is running. In fact, the browser won't even try to communicate to fdb in that case. If you do have a Flash Player Debugger installed on your browser, you will still see the same output on the web browser shown above for when the -debug=true flag is set and for when it is not set. The only difference here is that the fdb debugger will report it first and require you to enter continue and then the browser will pop-up the same windows you see above for the respective case.

So why use the fdb debugger? The reason you would want to use the fdb debugging in association with code compiled with -debug=true and run on a Flash Debug Player is that fdb will provide you with much more detail than simply the errors. As shown above, fdb provides you with all trace() statement output and this is helpful for seeing flow of logic through your application before and after an error. Also, the fdb debugger allows you to step through lines of code one at a time and, as with most code debuggers, dump the values of properties and objects at any step along the way. While this was not shown here, it is often highly useful, especially for thorny runtime issues.

There is much more to fdb than covered here, but hopefully this entry provides an overview of how to use the command-line fdb debugger and how to use it with the mxmlc compiler and the Flash Debug Player.

This entry showed how to watch trace() output and other debugger output via the console window in which fdb is run. This output can alternatively be stored to a file as discussed in Logging Flash trace() Output to a File, in Flex Trace and Logging, and in Troubleshooting Tips for flashlog.txt Not Being Generated.

Another useful resource on Flex 2 Debugging is Using Flex 2 SDK Flash Debugger.

Monday, November 19, 2007

MXML Vs. ActionScript: Properties, Events, Effects, and Styles Declarations

The Adobe Flex documentation describes the Relationship of MXML Tags to ActionScript Classes (livedocs.adobe.com/flex/201/html/mxml_013_4.html). Essentially each MXML tag (an XML tag conforming to the MXML grammar) corresponds to an ActionScript class. However, not every ActionScript class in the Flex framework (classes in a package starting with mx) has a corresponding MXML tag and, of course, the Flash API ActionScript classes (classes in packages beginning with flash) also do not have MXML counterparts. Examples of Flex ActionScript classes that do not have MXML counterparts include mx.controls.Alert, mx.utils.StringUtil, mx.utils.ObjectUtil, and the mx.logging classes.

Conversely, there are MXML tags that do not have corresponding ActionScript classes and these (mx:Binding, mx:Component, mx:Style and more) are listed in the Flex Language Reference.

The Flex 2.0.1 Language Reference provides detailed information regarding MXML tags and their underlying ActionScript classes. The information included in each class/tag description includes the package the class/tag belongs to, the ancestry/inheritance tree for the class/tag, interfaces implemented by the class/tag, and subclasses of the class/tag.

Perhaps even more importantly, the language reference supplies the public and protected properties of the class/tag, the public and protected methods of the class/tag, the events that can be associated with the class/tag, the styles that can be applied to the class/tag, the effects that can be associated with the class/tag, and public constants provided by the class/tag.

When using an MXML tag, the specification of a property, event, effect, or style is typically almost trivial and often amounts to simply specifying an XML attribute on the MXML tag to specify the propery, event, effect, or style.

When using an ActionScript class equivalent of an MXML tag, some differences are introduced in terms of handling of properties, events, effects, and styles. However, ActionScript classes provide easy access to the methods associated with the class.

The following code example demonstrates using both MXML and direct ActionScript to accomplish the same thing. This example provides an easy way to contrast MXML syntax with ActionScript syntax.


<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:flash.display="flash.display.*"
width="500" height="300"
applicationComplete="compareThem();">

<mx:Resize id="enlargeButton"
widthTo="{BUTTON_WIDTH_LARGER}"
heightTo="{BUTTON_HEIGHT_LARGER}" />
<mx:Resize id="reduceButton"
widthTo="{BUTTON_WIDTH}"
heightTo="{BUTTON_HEIGHT}" />

<mx:Script>
<![CDATA[
/**
* To compile solely this Flex application from the command line, use
* mxmlc -strict=true Comparator.mxml
*
* This application demonstrates how MXML tags and direct ActionScript code
* handle specification of properties, events, effects, and styles.
*/

import mx.controls.Alert;
import mx.events.FlexEvent;

public const BUTTON_WIDTH:int = 250;
public const BUTTON_HEIGHT:int = 22;
public const BUTTON_WIDTH_LARGER:int = 400;
public const BUTTON_HEIGHT_LARGER:int = 75;

/**
* Compare MXML approach to ActionScript approach for designating properties,
* events, effects, and styles.
*
* Compare the examples to see how MXML and ActionScript handle some of these
* same designations differently. For example, in the Button constructed in
* both MXML and ActionScript, the following similarities and differences can
* be observed:
*
* <ul>
* <li>The "label" and "width" PROPERTIES are handled very similarly between
* the two approaches. Like everything else, MXML specifies properties
* with attributes on the XML tag. ActionScript assigns the property
* directly to the new value and typically takes advantage of underlying
* get / set accessor functions.</li>
* <li>The event handler for clicking down on the button is specified in the
* MXML tag as simply the buttonDown attribute with the value of that
* attribute set to the event handler method. In ActionScript, this same
* event handler method is associated with the button through the use of
* the method <code>addEventListener</code>.</li>
* <li>Styles are applied to components with <code>setStyle()</code> in
* ActionScript while they are specified in MXML via an attribute with
* the style name and the value of the attribute being the value to set
* that particular style to.</li>
* <li>Effects are applied to components in ActionScript in the exact same
* manner that styles are applied -- using the <code>setStyle</code>
* method. Likewise, effects are specified in MXML just as styles are
* specified in MXML -- using an attribute with the effect trigger name
* and supplying that attribute with the effect to occur.</li>
* </ul>
*/
private function compareThem():void
{
// The MXML button will be displayed as part of the normal application, so
// now call method to build second button with direct ActionScript.
generateAndApplyButton();
}

/**
* Construct a button with direct ActionScript and add it to main view box.
*/
private function generateAndApplyButton():void
{
const button:Button = new Button();
button.label = "Direct ActionScript Button"; // property
button.width = BUTTON_WIDTH; // property
button.addEventListener( FlexEvent.BUTTON_DOWN, // event
respondToButtonDown );
button.setStyle( "borderColor", "#0000FF" ); // style
button.setStyle( "color", "#FF0000" ); // style
button.setStyle( "rollOverEffect", enlargeButton ); // effect
button.setStyle( "rollOutEffect", reduceButton ); // effect
mainBox.addChild(button);
}

/**
* Event handler for button clicked down.
*
* @param aEvent Event associated with button down.
*/
private function respondToButtonDown(aEvent:Event):void
{
Alert.show("Thanks for clicking on the button!");
}
]]>
</mx:Script>

<mx:VBox id="mainBox">
<mx:Button id="mxmlButton"
label="MXML Button"
width="{BUTTON_WIDTH}"
buttonDown="respondToButtonDown(event)"
borderColor="#0000FF"
color="#FF0000"
rollOverEffect="enlargeButton"
rollOutEffect="reduceButton" />
</mx:VBox>

</mx:Application>



It is impossible to capture all of the event handling and effects handling in a single snapshot, but the image below (click on it to see it larger) shows some of them in action.



From the code comparison we can quickly ascertain some differences between MXML and direct ActionScript for handling of events, effects, and styles. Note that properties are handled very similarly for both coding approaches. However, there are cases where properties are handled a little more differently between MXML and ActionScript. A good example of a different handling situation is the UIComponent width property (which is inherited by Button in the example). While not shown in the above example, the width can be expressed as a percentage in MXML, but not in ActionScript, where a percentWidth property should be used instead. In the above example, the width was declared as an absolute width in terms of pixels and so could be declared in the same manner in both MXML and ActionScript.

The example above shows that even when using binding the approach to setting properties is similar across MXML and ActionScript. Note that the ActionScript property assignment approach typically takes advantage of ActionScript's get/set accessor functions.

Event handling is specified differently in ActionScript than in MXML. An event handler is specified in MXML as an attribute similar to how properties were specified in MXML (but with the specification of a method name with the implicit event parameter). In ActionScript, however, the addEventListener method is used instead. The results are the same, however.

The Flex documentation for Button shows the styles that can be applied to a Button. Two of the styles that are available that are set in this example are the "color" (of text) style and the "borderColor" style. As for properties and events in MXML, styles in MXML are simply specified by placing the appropriate style name as an attribute on the MXML tag and then setting that attribute's value to the value desired for that style. In ActionScript, the setStyle method must be called and the name of the style is passed to the method along with the value for the style.

It is fairly obvious from the API and the method name setStyle that this is the appropriate method to set style on a component in ActionScript. However, it is less obvious that the setStyle method is also the ActionScript method for setting effect handling. Again, MXML allows the effect to be set simply as an attribute with attribute name matching the effect triggers supported by the component and with attribute value being the effect to take place when the effect trigger occurs. The Button class inherits all of its effect handlers and even has some default effects applied without additional specification. For this example, two Resize effects are used. Interestingly, the effects applied in this example to enlarge and shrink the buttons on rollOver and rollOut respectively are applied on top of the effect changes that occur on the button by default.

Note that I listed resources for locating the standard Flex events in my last blog entry.

As the examples above and the analysis after the examples showed, MXML handles properties, events, styles, and effects in really the only way that it can -- as XML attributes because MXML is XML. ActionScript, on the other hand, sets properties directly using get/set accessor functions, sets events with addEventListener(), and sets styles and effects with setStyle().

There are several conveniences that can be enjoyed when using MXML tags that are not similarly enjoyed when using ActionScript directly. These include the ability to associate properties, styles, events, and effects with the MXML tag in essentially the same manner (as XML attributes for the XML tag) instead of different approaches for each as is necessary with ActionScript. Another advantage of MXML is that all Flex ActionScript classes are automatically visible to the application and no import statement is required. ActionScript requires non-global classes to be imported.

The conventional Flex wisdom is to use MXML for view and layout purposes and then to use ActionScript for business logic purposes. This corresponds roughly with the idea of using JavaServer Pages HTML/XML syntax for view with Java code for the business logic.

Flex: The Standard Effects

There are several methods for determining the standard effects provided by Flex. Here are a few that come to mind:

1. See "Available Effects" in the documentation (livedocs.adobe.com/flex/201/html/behaviors_068_05.html). As with most of the Flex 2 Language Reference, the effects classes have example code included in their documentation.

2. Use the Adobe Flex 2 Component Explorer. This is my favorite method because clicking on the various effects allows you to see an example of the effect in action and example code for producing that example effect is shown. In the Component Explorer, look under "Effects, View States, and Transitions" and then under "Effects" to see the available effects.

3. Examine mx.effects package API documentation or mx.effects.effectClasses package documentation.

In addition to these standard Flex effects, custom effects can be created as described at livedocs.adobe.com/flex/2/docs/00001640.html .

There Are Few Absolutes in Software Development

Bill Jackson recently posted a blog entry on the “80-20 rule”. As Bill points out in the blog, he is not talking about the Pareto Principle, but is instead talking about that fact that many “rules,” “guidelines,” “best practices,” and other recommended approaches are really meant for general cases and not for all cases. In fact, there seems to be very few situations in software development in which we can safely use words like “never” and “always.”

Like Bill, I am always assuming the 80-20 rule when recommending a certain practice unless I am covering some of the more interesting cases that occur (the 20%). Whenever I recommend a practice, technique, or approach, the implicit caveat is that “Generally this approach is best.”

To avoid my blog entry becoming just a “yeah, me too!” entry in relation to Bill’s entry, I thought I’d add some common software development examples of the 80-20 rule.

Use of return, break, and continue

I have heard experienced developers state that a method should only have one return statement and that break and continue statements are always bad form. However, I have seen some awful code that is difficult to read and follow because the developer used many convolutions to adhere to the single return statement or to avoid using break and continue. That being said, gratuitous use of multiple return statements, continue statements, and break statements can also have their own readability issues and sometimes reflect potential problems with the code design. The Scala programming language specifically does not provide continue or break.

Coding Standards Enforcement

More than once, I have seen code flagged for not meeting specified coding standards. I generally like the idea of coding standards and think there are significant benefits to adhering to coding standards, especially in large development teams and/or with large code bases. However, this is also one of the best examples of where engineering judgment needs to be used to know which standards to enforce most rigorously.

One common standard is that a method should not exceed X number of lines. There are good reasons for this (including maintainability, modularity, etc.), but blind adherence to this can be more troublesome than it is worth. Questions should be asked like the following
* Is it really so bad if this particular method has X+2 lines of code?
* Is there a way to break this method up that makes more sense? This might apply even to a method that already has fewer than X lines.
* Is it worth making an unnatural break in the method or making the code unnecessarily complex just to keep the method line count under X?

Assuming that X is defined as a reasonable number of lines, I would expect that adhering to the standard of having methods having no more than X number of lines will be a good one. However, there will be cases where a particular method is actually more readable and maintainable if allowed to exceed the standard.

Avoid Magic Numbers

This is generally sound advice, but I have seen even this overdone. It is maddening to see things like the starting 0 in a for loop defined as ZERO. Any time the code uses the number as it is (not as a value representing a concept but as an actual implementation details of the language), that number generally does not need to be defined as a constant. This applies to using zero in for loops, using 1 in single index increment and decrement statements, etc. Numbers that are not tied to the language, such as the temperature at which water boils at sea level or the radius of the earth, are the types of numbers that should be defined as constants.

Related to this is the idea of placing constants in a common file that multiple files can reference. This is a good idea if multiple files actually need to use it, but sometimes it is much easier to have a constant defined in the file that uses it if that is the only file that uses it. The short of all this is that while I generally do prefer to define constants in a common location, there are times when they are best defined in the local class file to which they apply and some numbers should not be made into constants.

Getter and Setter Methods

This controversial topic deserves a blog entry of its own, but I generally see this implemented exactly backwards. Whereas getters and setters should probably be automatically generated (via IDE or manually out of habit) for about 20% of the classes, it seems like they are instead generated for about 80% of newly created classes.

Use of Composition Rather than Inheritance

Many of us learned object-oriented design and development in the 1990s and many of us fell into the trap of using inheritance far more than we should have. It seems that the software development community is reaching consensus on the overuse of inheritance and the preference of composition over inheritance in many situations. Until fairly recently, we seemed to have this one backwards and were using inheritance 80% of the time when we really should have been using inheritance about 20% of the time and composition 80% of the time. I think we’re moving toward that now.

Java Exception Handling

The debate over checked versus unchecked exceptions (Java) has rivaled other techno-debates at its peak, but a majority consensus seems to have largely settled upon the concept of using checked exceptions only when the client code can be expected to do something about the exception and to otherwise use unchecked exceptions. In my experience, that has resulted in using unchecked exceptions far more often than checked exceptions and so this fits the 80-20 rule. It would be wrong, in my and many others’ opinions, to say “always use checked exceptions” or “always use unchecked exceptions.”


I am transitioning here in my examples from examples of rules and guidelines that often apply more often than not, but have their exceptions to examples of successful software development innovations that owe at least some of their success to focusing on the “common 80 percent.” The common theme is that most guidelines, rules, and recommended practices fit the common 80 percent of development situations.


Enhanced Java for-each Loop

The enhanced Java for loop (Java for-each loop) that was introduced with Java 5 provides an example of the 80-20 rule. The generics-enabled enhanced for loop has really grown on me. I enjoy the much tighter code with no need to cast objects in the collections I am iterating over. However, the enhanced for loop does not cover all collection iteration needs and does not cover less standard iterations like reverse iteration. Instead, the enhanced for loop focuses on the simple collection iteration cases. This still works pretty well, though, because the majority of loop iterations do fit the nominal (or simple) case that the enhanced for loop covers. As I think about the loop iterations I have written since the advent of the enhanced for loop, I think I have probably used that syntactic sugar for well over 80% of my collection iterations.

For in-depth coverage of the nuances of the Java for-each loop, see the article Nuances of the Java 5.0 for-each loop.

Ruby on Rails

Like Java’s for-each loop, Ruby on Rails was designed to address the most common cases. Ruby on Rails creator David Heinemeier Hansson has been quoted (in Ruby on Rails: Making Programmers Happy) as stating that Rails has always been meant to cover the common cases that make up roughly 80% of web application development and that developers should expect to deal with the last 20% that includes the highly customized, application-specific type problems. The Ruby on Rails concept of “convention over configuration” and the Java Persistence API’s similar “configuration by exception” concept rely heavily on the 80-20 rule.


An interesting corollary to this 80-20 rule is the significance of the occasional concept that truly “always” applies or truly “never” applies. Because it is very difficult to find anything that is “always” or “never,” we may have to settle for “almost always” or “almost never.” The difficulty of coming up with examples for these absolutes or “almost absolutes” is evidence of the importance of adhering to these recommendations. Here are some ideas for concepts that fit this categorization:

Do Not Rely on Java finalizers

Do Not Rely on Programmatic/Explicit Java Garbage Collection

Do Not Programmatically Manage Threads from Enterprise JavaBeans

Overload a C++ operator with Functionality Congruent with the Overloaded Operator

Even these “almost always” or “almost never” recommendations may have their exceptions, but they are closer to following a 95-5 or 99-1 rule than the 80-20 rule.


All of this really boils down to the common sense admonition: Use guidelines, conventions, standards, and other recommended practices as "rules of thumb" or baselines for making decisions, but be prepared to change an approach based on differences encountered in a specific situation or problem. Just as no single programming language is best for all types of software development, a single guideline can rarely apply to every possible situation. This is a big part of what makes software development interesting -- we must think through the problems and use our experience and skillset to apply the best solution to the problem at hand.

Saturday, November 17, 2007

Simple Pie Chart Labels in JFreeChart 1.0.7

In the OTN article Visualize Your Oracle Database Data with JFreeChart, we showed multiple examples using JFreeChart to generate pie charts. However, in all the pie charts in this article and its accompanying source code, the labels for the pie chart sections were displayed outside of the actual pie and had lines connecting the labels to the appropriate pie section.

Recently released JFreeChart 1.0.7 makes it easy to place these pie section labels directly on the applicable pie slices. The following code snippet is taken from Listing 18 in the OTN article and the one additional line necessary to use "simple" labels rather than "extended" labels for a JFreeChart pie chart is highlighted:

/**
* Create 3D pie chart displaying the number of employees at each
* commission level. This method demonstrates use of DatasetReader to
* translate data from XML format to JFreeChart data format.
*
* @return 3D Pie Chart showing number of employees at each commission
* level.
*/
public JFreeChart createCommissionsPercentagePerLevelPieChart()
{
PieDataset pieData = null;

final String xmlData = databaseAccess.getCommissionPercentageBreakdownAsXml();

final DatasetReader reader = new DatasetReader();
try
{
pieData = reader.readPieDatasetFromXML(
new ByteArrayInputStream(xmlData.getBytes()) );
}
catch (IOException ioEx)
{
ioEx.printStackTrace();
}

JFreeChart chart =
ChartFactory.createPieChart3D( "Commissioned Employees at Each Commission Level",
pieData,
false, true, false );

// Chart specifically provides getCategoryPlot() and getXYPlot() methods,
// but not a getPiePlot() or getPiePlot3D() method.
final PiePlot3D plot = (PiePlot3D) chart.getPlot();
plot.setDepthFactor(0.35); // pie depth 35% of plot height
plot.setCircular(false);
plot.setForegroundAlpha(0.5f); // Declare explicitly as float (50%)

plot.setLabelGenerator(new HrCommissionsPieGenerator());

plot.setSimpleLabels(true);

return chart;
}


In the above example, a PiePlot3D was already being used, so only one line of new code was needed to move the pie section labels onto the sections themselves. This line was plot.setSimpleLabels(true).

There are a couple interesting side notes to make here. First, this also works with PiePlot even though PiePlot3D was used in the example above. Second, passing false to the setSimpleLabels method is the equivalent of not calling this method at all. In other words, not using simple labels (using "extended" labels) is the default. This makes sense because this was the case for JFreeChart 1.0.5 and JFreeChart 1.0.6 (the versions we wrote our article against) and the behavior remains the default.

I also like the default being "extended" pie section labels rather than "simple" pie section labels because the labels start appearing on top of each other fairly quickly when there are numerous or very small pie sections. The following image (click on it to see larger version) shows what the chart shown in the article's Figure 15 looks like with "simple" labels rather than the extended labels used (by default) in the article.



The simple labels look pretty good here because of the relatively small number of pie sections and the relatively large size of each section that provides sufficient room to place the labels within the section. However, even in this example, a few of the labels do overlap each other.