Archive for the ‘Coding’ Category

Variable scope in ActionScript Flex

Monday, March 8th, 2010

Hoisting, the strangest ActionScript/Flex “feature” I’ve ever seen (at the moment of writing). Probably you’ve never heard of hoisting. I was hinted to this feature when I had two variables with the same name in one function. Flex was warning about this, but I didn’t really understand why.

Check the following example:

private function existsInSources(searchFor:String):Boolean {
	if(searchFor.length > 10) {
		for each(var valueObj:Object in longStringsCollection) {
			if(valueObj.key == searchFor) {
				return true;
			}
		}
	} else {
		for each(var valueObj:Object in shortStringsCollection) {
			if(valueObj.key == searchFor) {
				return true;
			}
		}
	}
	return false;
}

By default Flex will give the following warning at the second declaration of valueObj, line 9:

3596: Duplicate variable definition.

Coming from other program languages this will (should) strike you as odd behaviour. Both variables ‘valueObj’ exist in their own scope… right?
Not in ActionScript, ActionScript has “Hoisting”.
From adobe.com:

An interesting implication of the lack of block-level scope is that you can read or write to a variable before it is declared, as long as it is declared before the function ends. This is because of a technique called hoisting, which means that the compiler moves all variable declarations to the top of the function.

So basically, the code from the example is transformed to:

private function existsInSources(searchFor:String):Boolean {
	var valueObj:Object;
	var valueObj:Object;
	if(searchFor.length > 10) {
		for each(valueObj in longStringsCollection) {
			if(valueObj.key == searchFor) {
				return true;
			}
		}
	} else {
		for each(valueObj in shortStringsCollection) {
			if(valueObj.key == searchFor) {
				return true;
			}
		}
	}
	return false;
}

“It just shows a warning and doesn’t have any impact on that beautiful piece of code you wrote there, so who gives a ….”.

The problem lies in the fact that this “feature” also means you can refer to objects before they are even initialized.

if(myString.length > 20) {
	trace('Length is over 20!');
} else {
	trace('Length is 20 or smaller');
}
var myString:String = "Hello world!";

Result: a runtime error.

Cannot access a property or method of a null object reference.

Flex compiles (yes, this code compiles fine…) this to:

var myString:String;
if(myString.length > 10) {
	trace('Length is over 10!');
} else {
	trace('Length is 10 or smaller');
}
myString = "Hello world!";

Pay attention to your variable scope, especially when using Flex/ActionScript.

Setting width and height in Flex using CSS

Saturday, May 9th, 2009

In the current version of Flex (3) it’s not possible to set width and height using CSS. The application I’m working on has a lot of screens containing a lot of TextInput fields. I want to be able to control the width and height of these text fields using CSS.

Sean Christmann has a nice solution for this. He uses HBox, I’ll use TextInput as an example:

package com.yourpackage {

	import mx.controls.TextInput;
	import mx.styles.StyleManager;

	public class ExtTextInput extends TextInput {

		public function ExtTextInput():void {
			super();
			// Default styleName for this component
			this.styleName = "extTextInput";
		}

		/**
		 * This method makes styles "width", "height", "percentWidth", "percentHeight", "x", "y" and "visible"
		 * valid from css.
		 */
		override public function styleChanged(styleProp:String):void{
			super.styleChanged(styleProp);
			if(!styleProp || styleProp == "styleName"){
				//if runtime css swap or direct change of stylename
				var classSelector:Object = StyleManager.getStyleDeclaration("." + styleName);
				if(classSelector != null){
					applyProperties(classSelector, ["width", "height", "percentWidth", "percentHeight", "x", "y", "visible"]);
				}
			}
		}

		private function applyProperties(styleObj:Object, arr:Array):void{
			for each (var item:String in arr){
				var prop:Object = styleObj.getStyle(item);
				if(prop != null) this[item] = prop;
			}
		}

	}
}

As the implementation extends the standard TextInput it will behave just like the standard TextInput. Databinding, runtime style changes… it all works.

The code sets a default styleName for the component, the style could look like this:

.extTextInput {
	percentWidth: 100;
	height: 18;
}

Of course you can set a different styleName while declaring the component in your application.

Installing Flex Builder on Ubuntu 9.04

Saturday, April 11th, 2009

For my work I’ve been working with Adobe Flex. If you’re doing Flex development you (probably) work with Flex Builder. It has features a development tool should provide; code completion, design view, good integrated building/running of projects, debugging etc.

At work I’m tied to my Windows XP laptop, at home I work with Ubuntu Linux. Whenever I do Flex development in private time, I always use the Windows machine… but what if you’d like to develop Flex on Linux?

Google quickly pointed to Flex Builder Linux. ‘Yey! A Linux Flex builder!’ The release notes shows some (minor) inconveniences:

Unsupported Flex Builder Features

  • Design view
  • States view
  • Refactoring
  • Data Wizards
  • Cold Fusion – Data Services Wizard
  • Web Services introspection
  • Profiler

And some known issues:

  • Organize Imports removes necessary imports
  • The default version of Java installed in Ubuntu systems is GCJ. This is not supported by the Flex Builder Linux installer and the installation may fail on Ubuntu Systems. Please ensure you have an installed Sun JRE before installing Flex Builder Linux.
  • Getting a transparent window for AIR App depends on your Linux distro capabilities. You may need to turn-on some settings (ex: Desktop effects on Ubuntu 7.10) or install some special packages (example: compiz-fusion, beryl for installing compositing manager) to get this working (if its not working by default)

I left out anything not related to Ubuntu or Flex Builder in general. Besides the ‘design view’ most issues are minor issues. Usually the ‘design view’ is used for some initial drag and drop interface building or for containers with and ‘absolute’ layout  (i.e. Canvas). The ‘design view’ then limits the build/run/change cycles.

Installing Flex Builder on Ubuntu 9.04

The prerequisites mentioned by Adobe are

  • Eclipse 3.3.x (32-bit)
  • Sun JRE 1.5.x or newer (32-bit)
  • Firefox 1.0, 1.5, or 2.0 (32-bit)

At the moment of writing, the version of Eclipse provided with Ubuntu is 3.2.x. So you’ll have to get a newer Eclipse version from Eclipse.org. I tried the latest version available, which is 3.4.2 (which later turned out to be a bad idea, use a 3.3.x version). Installation of Eclipse is as easy as unpacking to the desired location, so I’m not describing that any further. Make sure you have the Sun JRE 1.5.x or newer installed. I installed ’sun-java6-jdk’ via the package manager, the JDK includes the JRE. Configure Eclipse to use that.

JRE settings Eclipse

JRE settings Eclipse

Download the Flex Builder Plugin for Linux.

Installing Flex Builder Linux

To install Flex Builder Linux:

  1. Prior to installing, remove any previous versions of Flex Builder Linux. Refer to the section ‘Uninstalling Flex Builder Linux’ below for instructions.
  2. Run the installer either marking it as executable (chmod +x) or by using a shell to execute it (sh FlexBuilder_Linux_Plugin.bin).
  3. Accept the license agreement and follow the prompts.
  4. When prompted, specify whether to install Flash Player 9 (note that this is an updated version of Flash Player 9 and that Flex Builder Linux will work with earlier versions of Flash Player 9 for Linux). This is the debug version of Flash Player 9, which is required for debugging support and exception display.
  5. Follow the prompts to complete the installation.
  6. Start Eclipse.
    Note: You must create a new workspace before beginning. Select File > Switch Workspace from the menu bar and enter a new folder name. If the folder doesn’t exist, Eclipse creates it.

Install Folder

Install Folder

When choosing the ‘install folder’ you can leave that to default, the Eclipse folder will be defined in the next window.

Eclipse Folder

Eclipse Folder

As described select the Eclipse folder, it must contain a subfolder named ‘configuration’. Continue the installation untill the installer displays that you’re done.

Start Eclipse and open the Flex perspective. If you get the following error while opening a MXML file:

Could not open the editor: Assertion failed:  org.eclipse.jface.util.Assert$AssertionFailedException: Assertion failed

Make sure you have the correct Eclipse version, I used 3.3.2 on Ubuntu 9.04.

Flex Builder Linux

Flex Builder in Linux with code completion

It seems Flex Builder accepts Flex 3 license keys, which is then ignored as it still displays “Flex Builder Linux will expire in xxx days.” If you use charting you can enter your license to remove the trial message.

You already choose to use the trail period and didn’t enter your license key? Open ‘license.properties’ in  ‘home/username/.adobe/Flex’. And add:

flexbuilder3=yourlicensekey

Or change:

flexbuilder3.displayedFirstLaunchMessage=true

to:

flexbuilder3.displayedFirstLaunchMessage=false

Restart Flex Builder and enter your license key in the launch message.

Applying Game Mechanics to Functional Software

Monday, March 16th, 2009

Just finished watching a Google Tech Talk by Amy Jo Kim of Shuffle Brain, regarding game mechanics in functional software (video embedded below). She has worked as a social architect on for example Rockband, and applying game mechanics on the eBay infrastructure. She has great ideas and examples of game mechanics applied to software (almost) everyone is using; YouTube, Twitter, eBay etc.

How can we apply these ideas to ‘boring’ business applications?

Fast debugging statements

Monday, August 25th, 2008

While reading Code Complete 2nd Edition I ran into a chapter which covers defensive programming. Defensive programming includes debugging, but not to any price of course. We don’t want performance of the application to suffer from debugging statements, at least not in production fase. Debugging is mainly used during development.

Implementation (Java)

So how do we implement debugging so that it minimally affects performance? According to the log4j website :

Actual logging is also quite fast, ranging from 21 microseconds using the SimpleLayout, 37 microseconds using the TTCCLayout. The performance of the PatternLayout is almost as good as the dedicated layouts, except that it is much more flexible.

Pretty fast huh?

logger.debug("Number of products: " + order.getNumberOfProducts());

Now we move to our production environment, we’ve changed the logging level to ‘error’ (thus not displaying the debug level).

The log will not show the debug message, but we don’t want the debug statement to be executed even! It’s creating a string instance, adding a integer value to it… we just don’t want that. We change it to:

if(logger.isDebugEnabled()){
	logger.debug("Number of products: " + order.getNumberOfProducts());
}

According to the log4j website:

It costs about 5 nanoseconds to determine if a logging statement should be logged or not.

Just to put things into context, 20 microseconds is 20000 nanoseconds. The only drawback of this implementation is that the check performed in ‘isDebugEnabled’ is also performed in ‘debug’. But who cares? If you’re debugging, you’re obviously not interested in 5 nanoseconds performance win (at that moment).

If you don’t mind recompiling your code for different environments you can make it even faster…

class Debug {
	public static final boolean DEBUG = false;
}

//somewhere in a method
if(Debug.DEBUG){
	logger.debug("Number of products: " + order.getNumberOfProducts());
}

How this is faster? The Java compiler sees the code within the if-statement is unreachable and the code will be left out, and that’s of course even faster than 5 nanoseconds. If someone decides to decompile your code, the debug statements will be gone.

Implementation (C/C++)

The last solution is comparable to something called ‘precompilation’ in the C-language (C and C++). There it looks like this:

#define DEBUG

#ifdef DEBUG
print("Debugging in C++");
#endif

If DEBUG is not defined, the code within ‘ifdef’ will not pass the preprocessor, and therefore will not make it into the compiled code.

JMS and SAP, avoid this combination?

Thursday, August 14th, 2008

I told a colleague “I’m going to use JMS topics to solve this problem”. His answer was: “SAP in combination with JMS… you don’t want to go there.”. Based on the fact that several SAP applications which use JMS seem to have complications… Is JMS and SAP a bad combination? Or at least a combination to avoid as developer?

SAP about their JMS implementation:

Full compliance with the JMS 1.0 specification. Software-based high availability solution.

Problem/task description

A short description of the problem/task:

The application’s caching mechanism caches retrieved data for 1 hour. We want it to cache until we tell it to clear it. If we change something in the back-end now, we want the cache to be cleared now. Don’t change the logic of the application too much

Logic at that moment

So what was the caching logic at that moment? A stateless session bean with static fields (class variables) which contained the cached objects. The same cache object was used in a normal class (pojo). A property file determined which was to be used.. none of the environments (development, quality, production) was configured to use the pojo. The cache was stored for one hour, no reset method.

Desired logic

Now we’re going to cache the entries… forever! Or at least until someone decides to reset it. Static objects exist in each JVM (actually per classloader… but for the sake of simplicity we assume per JVM), so per node there is a cache. The fact that there are multiple cache instances doesn’t matter, it has been like this for ages and was always sufficient. ‘Create a method to clear the cache, deploy and you’re done’. Not really, what will happen to a call to reset the cache? User clicks ‘Reset Cache’ (where does not really matter), the load balancer determines to which node the request for reset is headed. The load balancer decides node 1 is the lucky one… the cache on node 1 is cleared… How to make sure every node gets the request for reset? Sounds like something for JMS topics!

Why JMS topics?

How does it work? Each cache object is subscribed to the “cache reset”-topic. The application running on (for example) node 1 receives the request for reset and posts a message on the “cache reset”-topic. All cache objects, on every node, get the message (even the posting object) and clear their cache. Sounds good. It does not only sound good, it works as described. But it cost a bit more time than anticipated…

Problems

What problems did we run into? Mainly a OutOfMemoryException. It’s hard, but not impossible, to write a memory leak in Java. Research showed the JVM had tons of free memory, where the hell does this error come from then? It took not long to find out JMS had a limited amount of connections available (100 per node on our installation), and somehow we ran out of connections (and therefore throwing an OutOfMemoryException…?). Could it be that the amount of connections used till that moment was close to that 100? And that the connections from the cache object were just enough to fill it? A listing of JMS connections with their topics/queues quickly showed the caching objects were taking up 60 connections… on one node! My expectation was to have 2 connections, as there were 2 instances of object cache.

JMS connections listing

Example of displaying JMS connections, click for larger version

Analysis

Analysis showed the following behaviour

  1. Connections were created over time (not all at once)
  2. Starting/stopping the application does not close the connections, neither does a redeployment
  3. The objects belonging to the connections still responded to topic updates (even after stopping the application)

Clearly there was something wrong. What was the logic at that moment? The connection was closed in the finalize of the cache object.

protected void finalize() throws Throwable {
	if(topicConn != null){
		try {
			topicConn.stop();
		} catch (JMSException e) {
			e.printStackTrace();
		}
		try {
			topicConn.close();
		} catch (JMSException e1) {
			e1.printStackTrace();
		}
	}
	super.finalize();
}

So whenever the garbage collector decides to clean up the object, the connection is closed. You never know when the garbage collector is going to do its round… my idea was that when the JVM is running low on memory it would start and collect. That somehow does not go for our cache object, even when it’s throwing an OutOfMemoryException.

Where did all those connections come from?

As described above, the cache objects were used in a stateless session bean, and in a pojo. The session bean is created upon start of the application, the EJB container keeps at least one instance of this bean active for requests. If stopping/redeploying the application does not clean up the cache objects (and therefore the connections) I would expect just a few connections (should still be fixed!). So somehow the connections come from the pojo… but the application isn’t even configured to use that cache!
How was that implemented?

public class Mapping {
	private static ObjectCache metaObjectCache = new ObjectCache();
	private static ObjectCache dataObjectCache = new ObjectCache();
	....

We didn’t pay much attention to this class, until now. Every time the class was loaded, a static instance of ObjectCache was created! As long as the class isn’t loaded everything is fine, but as you can guess: it didn’t matter how the cache was configured in the properties file… a request always goes through this class. And thus a cache was created, a connection was opened. Fixing this was easy, initialize the cache objects null and do a check upon reading.

if(metaObjectCache==null){
	metaObjectCache = new ObjectCache();
}
...

This should fix the problem of more and more connections being opened. Still leaves open the problem that connections aren’t closed.

Cleaning up

You cannot rely on the garbage collector, I should have thought of that…
Documentation on the JMS Connection object:

Since a provider typically allocates significant resources outside the JVM on behalf of a connection, clients should close these resources when they are not needed. Relying on garbage collection to eventually reclaim these resources may not be timely enough.

Not timely enough, certainly not. After a week all connections were still open, the objects still responded on topic posts. Maybe they aren’t even eligible for garbage collection when the connection is still open. Solution? Close the connection as soon as it is no longer needed, sounds pretty obvious actually. How do we know it’s no longer needed? In our case it is whenever the stateless session bean gets removed (ejbRemove). The J2EE will keep at least one instance of this bean running as long as the application is active. The bean will be removed when stopping/redeploying the application, at that moment we want to close the JMS connection. If we don’t close it at that moment we’re too late and the objects get lost in cyberspace. As the J2EE container can create multiple instances of the bean when it feels the need to (many requests) we cannot just kill the connection as soon as ejbRemove is called. A simple solution for that is to keep track of the number of ‘clients’ in the cache.

	public void ejbRemove() {
		metaObjectCache.removeClient();
		dataObjectCache.removeClient();
	}

A similar solution was created for the pojo that contained the cache objects.
Closing the connection is the responsibility of the cache itself, the client told the cache object that it’s no longer interested, the cache object must decide if the connection can be closed.

	public void addClient(){
		numberOfClients++;
	}

	public void removeClient(){
		numberOfClients--;
		if(numberOfClients < 1){
			//no more clients... close everything
			this.cleanUp();
		}
	}

	private void cleanUp(){
		if(topicConn != null){
			try {
				topicConn.stop();
			} catch (JMSException e) {
				e.printStackTrace();
			}
			try {
				topicConn.close();
			} catch (JMSException e1) {
				e1.printStackTrace();
			}
		}
	}

Conclusion

  • Pay really, really, really good care to your JMS connections. Do NOT trust the garbage collector to collect the object containing the connection. Assume the object with the connection will NOT be garbage collected for the next couple of years.
  • Create the connection only when you will use it, yes… sounds obvious, read on. I created a connection in the constructor of the cache object, but missed a static field declaration of this cache object in an other object! Resulting in creation of connections at places/times you don’t want/expect it.
  • Find a place to close the JMS connection, in my case it was easiest to close it when the last stateless session bean is removed.

In other words, handle it like you would any (database) connection.

No more comments in your code

Friday, July 25th, 2008

Comments, the more the better… right? Well I thought so too, in fact this is some of my code of a few days ago:

// handle the initialization of jobs
if (request.getParameter("initiateJobs") != null && request.getParameter("initiateJobs").equalsIgnoreCase("true")) {
	initializeJobs();
}

// get the trigger info, which will be displayed on the jsp page
List triggerInfo = getTriggerInfo();
request.setAttribute("triggerInfo", triggerInfo);

But what does it really add? Besides two lines of text. The code in the ‘if’ statement should be clear enough for a web programmer, and the method ‘initializeJobs’ tells as much as the comment. Same goes for the two lines of code below that. What would my intention be by putting ‘triggerInfo’ on the request scope? Point made.

Maybe you say ‘it’s faster to read’. Well… I don’t think it is.

if (request.getParameter("initiateJobs") != null && request.getParameter("initiateJobs").equalsIgnoreCase("true")) {
	initializeJobs();
}

List triggerInfo = getTriggerInfo();
request.setAttribute("triggerInfo", triggerInfo);

Looking at one of my last lines of code I realized Sammy Larbi and Jeff Atwood have a point.