Tuesday, April 29, 2008

How to add new events types to ExtJS components

I needed to be able to click on an Ext.Panel and have a window popup. The 'click' event is not a supported event for Ext.Panel. It turns out it is pretty easy to do in ExtJS. Almost every component has a getEl() method.

var myPanel = new Ext.Panel({
html: '<> Click Me < / h2>',
autoHeight: true
});

Once the panel has been rendered you simply, need to do the following.
var element = myPanel.getEl();
element.on('click', this.handleClick.createDelegate(this));

Now when ever a mouse clicks on the panel, the handleClick method will be called. The trick is that you have to wait until the panel has been rendered, to be able to add the event to it.

You may be tempted to use
myPanel.on({'click':this.handleClick.createDelegate(this), scope: this});

This method works great for events that the ExtJS Component supports by default, but doesn't work for other events.

How to add a keymap to an existing FormPanel in ExtJS

Recently I needed to add a key map to an existing FormPanel in our ExtJS project. This sounded like a simple thing to do and in the end the code was simple, but it wasn't obvious how to do it. So I thought I would try to save you the pain I went through to figure it out.

In the JavaScript, you might have something like the following.

this.myForm = new Ext.form.FormPanel({ ...your parameters....});
this.myWindow = new Ext.Window({ ...your parameters....
items: this.myForm,
buttons: [{
text: 'Save',
handler: this.onSave.createDelegate(this)
},{
text: 'Cancel',
handler: this.onCancel.createDelegate(this)
}]
});

Now how do you go back and add a KeyMap after the fact.

The panel has to be rendered before you can add the KeyMap to it. To do that simple call the following.

this.myWindow.show();
this.myWindow.doLayout();

Now you can create the KeyMap.
new Ext.KeyMap(this.myForm.body, [{
key: Ext.EventObject.ESC,
fn: this.onCancel.createDelegate(this),
scope: this
},{
key: Ext.EventObject.ENTER,
fn: this.onSave.createDelegate(this),
scope: this
}]);

Now, the user can either click the cancel button or hit 'esc' to cancel what he was doing and to save what he was doing he can either press the save button or press the 'enter' key on the keyboard. I hope you find this helpful.

Friday, April 25, 2008

Debugging JavaScript in IE

Firebug is so powerful and easy to use, I almost never need to debug JavaScript in IE. However, every once in a while I will come across a bug that only occurs in IE. A co-worker of mine told me about the best free IE JavaScript debugger he was aware of. It has been a real life saver at times. I thought I would share the information here so that you too can debug JavaScript in IE, if you must.

It does take a while to download and install the Mircosoft Visual Web Developer 2008 Express Edition, http://msdn.microsoft.com/vstudio/express/vwd/

This blog entry has steps on how to set up and use the tool the first time.
http://www.berniecode.com/blog/2007/03/08/how-to-debug-javascript-with-visual-web-developer-express/

There some special instructions in that blog for getting it to work, if IE is not your default browser.

Hope you find this helpful



Friday, April 11, 2008

Configuration Management: Bugs and Branches

Most software when the time comes to make a release will establish a branch. As the branch is tested bugs will be found that must be fixed. A very common dilemma is do we fix it on the main branch then merge the fix to the release branch, or do we fix it in the release branch and merge it back to the main branch. Either way, the changes must be in both locations.

This is a very old debate, and developers will usually be adamant about which side they support. I have been involved in projects that have practiced both methods. I would simply like to share my experiences from both sides.

Branch to Main:
Pros
  • One of the main rationals for this method is that the release is on a time line to get out. The fixes need to be put into the branch first to be able to maintain schedule and insure that the problems are fixed to support the customer.
  • Mainline code will continue to be enhanced for future releases so it will diverge from the branch code and the fix for the main branch may not be valid for the branch, so you should fix the branch first.
Cons
  • The biggest risk is that the fix never makes it back to the main branch so the next release you risk breaking the customer. Or even worse, an enhancement that was requested at the last minute by the customer, never makes it back to the main line.
Main to Branch:
Pros
  • It guarantees that the main branch always has all the fixes and enhancements, so that future releases are not at risk of missing critical bug fixes or minor customer enhancements.
Cons
  • It takes longer to update the branch with fixes, potentially causing a delay in the software release.
  • Risk that the fixes from the main branch don't get merged to the release branch.
  • The longer the branch lives the more difficult the merges to the branch become. You only want the bug fixes, not the new development.
Experiences:
My experiences have shown me that the testing involved on the release branch is much more rigorous than the testing on the main branch. No one wants the software to fail for the customer so must of the testing is focused on the release. Due to new development, the main branch is "broken" more frequently and while that is not desired, it is not entirely unexpected. It is more difficult to test reliably the main branch because the development my not be finished, and bugs would be written against code that wasn't ready to be tested. The release branch is usually much more stable with only critical defects being fixed, which makes it easier to test.

I have been involved in releases of software that went out to the customer only to have bugs reported back, that were fixed in a previous version and are broken again in the version they just received. Customers are not very understanding of this situation, especially on government contracts. They will call into question the processes you use, the reliability of your release process, even your ability to write bug free code. Some very uncomfortable meetings to have to go through.

One project I was on, the branch lived for a year and a half. The mainline code had diverged so much that bug fixes were completely different in both places. In fact we branched 3 times from the original branch without ever going back to the main. It was truly a nightmare to maintain. Which ever method you choose, the longer the branch lives, the more difficult the merges become, either direction.

There are pros and cons to both sides. From my experience, release branches should be short lived, and bug fixes should be merged in as quickly as possible after you branch. This negates a lot of the code divergence cons used as arguments for both sides. Due to the heavy testing on the release branch, it is not very likely that a required bug fix will be missed on the branch.

For the reasons stated above I am a proponent of fixing in the main branch then merging to the release branch. That said both methods can work. Going from the branch to the main requires a well defined process that everyone must follow to guarantee that changes are merged into main once they are verified on the branch.

Thursday, April 10, 2008

Getting Internationalization to work on Windows

Recently, I wasted several days trying to resolve an internationalization issue within our web application. Now I would like to share my experience and the solution I found in order to save others time.

Our web application has a requirement to support multiple languages, English and Hangul(Korean). Our application uses ExtJS for the front end and Jersey for the REST services, and we had difficulties getting i18n working in the javascript.

Initially all the Korean characters would appear as ??? in our ExtJS widgets. After some research we added a call to get the UTF-8 bytes, new String(bundle.getValue(key).getBytes(“UTF-8”)). and setting the content type charset to UTF-8 on the Jersey StringRepresentation. The issue with this approach was that certain Korean characters would appear in our ExtJS widgets as ?? and others would appear fine, so it was only a partial solution.

The solution ended up being pretty simple. Based on some information here, you basically have to set the default charset for the JVM to UTF-8. The default charset on Windows is windows-1252. To do this set the system property file.encoding=UTF-8 in the JVM, for JBoss you can do this by modifying the run.bat and adding -Dfile.encoding=UTF-8 to the JAVA_OPTS variable. Please note this is a Windows specific issue, since UTF-8 is the default charset for both Linux and Macs.

The following is the code before and after the changes to the JVM default charset , that will allow you to properly visualize Hangul(Korean) in your application.

The following displayed ?? for certain Korean characters.
ResourceBundle bundle = ResourceBundle.getBundle(bundleName, locale);

Enumeration keys = bundle.getKeys();

String key = keys.nextElement();

String value = bundle.getValue(key);
byte[] bytes = value.getBytes("UTF-8");
String newValue = new String(bytes);
StringRepresentation representaiton = new StringRepresentation(newValue);
representaiton.setLanguage("ko");
representaiton.setMediaType("text/plain; charset=UTF-8");
return representation;

After configuring the JVM to set the default charset to UTF-8
ResourceBundle bundle = ResourceBundle.getBundle(bundleName, locale);
Enumeration keys = bundle.getKeys();

String key = keys.nextElement();

String value = bundle.getValue(key);
StringRepresentation representaiton = new StringRepresentation(value);
representaiton.setLanguage("ko");

representaiton.setMediaType("text/plain; charset=UTF-8");

return representation;


For those that want some additional details as to why it wasn't working, read on.
bundle.getValue(key) always returns a UTF-8 String, even if the default charset is windows-1252.

The Jersey REST Service is returning a JSON StringRepresentation back to the client code. But the StringRepresentation class expects the string you construct it with to be in the default charset . Setting the media type on the StringRepresentation to "text/plain; charset=UTF-8" will cause it to try to convert the string it was provided from the default charset to UTF-8.

The first case it was trying to convert a UTF-8 String(thinking it was windows-1252) to a UTF-8 String. This produces all ?????? on the client for the Hangul(Korean) characters.

The second case, we get take the UTF-8 string returned from the bundle and convert it to an array of UTF-8 byte codes. We then take those byte codes and create a new windows-1252 string. The string representation class basically takes that windows-1252 string and converts it back to a UTF-8 string. So why didn't this work? Some byte codes can't be represented in windows-1252, specifically(129, 141, 143, 144, and 157). So any Korean characters that had one of those specific byte codes, would show up as a '?'.

The final solution, eliminates all the extra conversions. Bundle returns a UTF-8 string, StringRepresentation sees that the default charset is UTF-8, and it is sending UTF-8 so it doesn't need to convert anything and the result is the client correctly displays all the Korean characters.

In summary, just set the default charset on the JVM to UTF-8.

To find out what default charset your system is set to you can execute the following Java command:
System.out.println(java.nio.charset.Charset.defaultCharset().name());