10/21/2009

Mac OS X: Using IntelliJ IDEA on 64bit JDK6

UPDATE 2:
The retail version of IntelliJ Idea 9 uses the JDK6 32bit by default on Snow Leopard (in contrast with the betas which were using JDK6 64bit).
The article has been updated to reflect this.

IntelliJ Idea 9.0 - Mac OSX 10.6 Snow Leopard

The default installation of IntelliJ IDEA 9.0 uses JDK6 32bit on Mac OSX 10.6 "Snow Leopard". With a little configuration we can force it  to use the 64 bit JDK6, which is also part of the operating system.

After you installed IntelliJ IDEA, Cmd+click on the IDEA launcher-icon to open it in Finder. Ctrl-click on the IntelliJ IDEA icon and choose Show Package Contents. Select Contents and right-click Info.plist. Select Open with -> TextEdit. This brings up the file in the text editor.

Do a search (CMD+f) on the string JVMArchs. You'll find the following entry:

<key>JVMArchs</key>
<array>
  <string>i386</string>
  <string>x86_64</string>
  <string>ppc</string>
</array>

Put the x86_64 entry on top (e.g. swap the i386 and the x86_64 lines), save the file (CMD+s) and close TextEdit (CMD+q). If you restart Idea, you'll see it is using the 64bit JDK if you check it in the IntelliJ Idea->About.

You can also check if a given process is 64bit in Applications->Utilities->Activity Monitor. Check out the last column called Kind.

IntelliJ Idea 8.0, 9.0 - Mac OSX 10.5 Leopard

In contrast, Idea uses JDK5 on MacOS X 10.5 "Leopard", and that's 32bit only. Again just a little configuration and we can force it to use the 64bit JDK6.

After you installed IntelliJ IDEA, CMD+click on the IDEA launcher-icon which brings up the entry in Finder, now right-click (or ctrl-click) on the IntelliJ IDEA icon and choose Show Package Contents. Select Contents and right-click Info.plist. Select Open with -> TextEdit. This brings up the file in the text editor.

Do a search (CMD+f) on the string JVMVersion. You'll find the following entry:
<key>JVMVersion</key>
<string>1.5*</string>
Change the 1.5* to 1.6*, save the file (CMD+s) and close TextEdit (CMD+q). Since the JDK6 in Leopard is 64-bit only, we don't have to touch the JVMArchs section.

Start IDEA and check in About IntelliJ IDEA if it is indeed using the 64bit JDK6.

IntelliJ Idea 8, 9 betas: if IntelliJ does not start anymore, and honors us with a [JavaAppLauncher Error] unable to find a version of Java to launch in the log file, we have to replace the launcher with a 64bit executable. Open a terminal:

cp /System/Library/Frameworks/JavaVM.framework/Resources/MacOS/JavaApplicationStub64 /Applications/Maia-IU-90.94.app/Contents/MacOS/idea

Replace Maia-IU-90.94 with the proper name of your application - I was using a developer preview of IntelliJ IDEA 9, but this same method works for version 8 as well.

32bit or 64bit?

To me IntelliJ Idea seems more responsive on 64bit JDKs. I'm wondering if you consider it faster as well? If you are developing for JDK6 on Leopard you should use similar amount of memory now (the 64-bit JDK footprint is bigger but there's only one copy of the JDK in memory), and - as a question of personal taste - the display looks nicer since JDK6 uses the native font smoothing style of OSX (a mixture of regular antialiasing and subpixel rendering), whilst JDK5 uses plain anti-aliasing without subpixel rendering. There are some comments online about memory leaks using JDK6, but personally I didn't experience this.

Happy developing using this great tool!











10/20/2009

ExtJS: Getting the selection from a TextField

It is not possible to get the selected text from a TextField in ExtJS 2.2. Fortunately it can easily be solved by introducing a getSelection() method to TextField:
Ext.form.TextField.prototype.getSelection = function() {
 var domElement = this.getEl().dom; 
 if (Ext.isIE){ 
  var sel = document.selection;
  var range = sel.createRange();
  if (range.parentElement()!=domElement) return null;
  var bookmark = range.getBookmark();
  var selection = domElement.createTextRange();
  selection.moveToBookmark(bookmark);
  var before = domElement.createTextRange();
  before.collapse(true);
  before.setEndPoint("EndToStart", selection);
  var after = domElement.createTextRange();
  after.setEndPoint("StartToEnd", selection);
  return {
   selectionStart: before.text.length,
   selectionEnd: before.text.length + selection.text.length,
   beforeText: before.text,
   text: selection.text,
   afterText: after.text
  }
 } else {
  if (domElement.selectionEnd && domElement.selectionStart) {
   if (domElement.selectionEnd > domElement.selectionStart){ 
          return {
           selectionStart  : domElement.selectionStart,
           selectionEnd : domElement.selectionEnd,
           beforeText   : domElement.value.substr(0, domElement.selectionStart),
           text    : domElement.value.substr(domElement.selectionStart, domElement.selectionEnd - domElement.selectionStart),
           afterText   : domElement.value.substr(domElement.selectionEnd)
          };
   } 
  }
 }
 return null;
}
Ext.form.TextField.prototype.getSelectedText = function() {
 var selection = this.getSelection();
 return selection==null?null:selection.text;
}
Unfortunately Internet Explorer and Firefox give us a hard time by implementing the functionality of getting the selection so different; this small listing gives us a getSelection() function returning a JS object very similar to the one Firefox returns, and adapts to IE accordingly. This object can be used to treat not just the selection itself, but the text before and after as well.

The getSelectedText() method returns the selection simply as a text.


Learning Ext JS

Ext JS 3.0 Cookbook

Ext JS in Action

Professional JavaScript Frameworks: Prototype,YUI, ExtJS, Dojo and MooTools (Wrox Programmer to Programmer)

10/01/2009

Resolve NoClassDefFoundException: Find a given JAVA class in JARs

NoClassDefFoundException occures when the classloader was not able to load a class, possibly because of multiple versions present in the classpath (contrary to what we would think at first, it does not actually mean the class was not found - since that would be a ClassNotFoundException).

To find the JAR files containing the conflicting versions, we have to iterate over every JAR file in a given directory, to look for the one which file contains the given class.

So let's assume we have a NoClassDefFoundException: org.jboss.remoting.marshal.Marshaller. This means, we have to find all the JAR files containing this class to look for the duplicates; and then decide which one to get rid of. In a web-application, the application libraries are in WEB-INF/lib, so we should start looking there. The other libraries' placement depends on the platform and the Servlet Container; for example on Ubuntu 9.04/Tomcat 6.0, the system libraries are at /usr/share/tomcat6/lib and the common libraries are at /var/lib/tomcat6/common/lib. These folders should be checked for duplicates as well.

On Solaris, the following script lists all JARs, spitting a line when the class is found:
cd webapps/ROOT/WEB-INF/lib
find . -name "*.jar" -print -exec jar tf {} \; | /usr/xpg4/bin/grep -e '.jar' -e 'org/jboss/remoting/marshal/Marshaller'
The -print parameter prints out the JAR filename, and grep prints either the JAR filename or the classname if found (we have two conditions in grep: either print the JAR name, or the match found).

On Mac OSX, the following is the equivalent:
cd webapps/ROOT/WEB-INF/lib
find . -name "*.jar" -print -exec jar tf {} \; | grep -e '.jar' -e 'org/jboss/remoting/marshal/Marshaller'

In Windows it is not so easy, having a more limited command-line. UnxUtils (download it from http://sourceforge.net/projects/unxutils/files/unxutils/current/UnxUtils.zip/download) can help: after installing, and changing our PATH to include its usr\local\wbin folder:
cd webapps\ROOT\WEB-INF\lib
find . -name "*.jar" -print -exec jar tf {} ; | grep -e "\.jar\|org/jboss/remoting/marshal/Marshaller"

Renaming multiple files with Flexible Renamer using Regular Expressions: removing numbers from filenames

Flexible Renamer is a free tool to rename multiple files written by a Japanese developer Naru. It is very straightforward to rename multiple files with it; my task was to remove the numbers from filenames, which were automatically appended by Outlook when I copied some messages from an Exchange Server, so that my subject is untouched. At the moment the author's download site is down, still the tool can be downloaded from CNET.

First you have to go to the folder where your files are. This you can do at the leftmost part of the application (see screenshot below).

To identify the filenames with numbers, we can use Regular Expressions, so choose RegEx from Rename Method. Since we want a complete match, click on the small triangle and select Only completely matched. The regular expression to match numbers in filenames is (.*)\(\d*\).msg : which can be broken down like this:
  • (.*) Take any characters any number of times (. and *), and group them in group 1 (so the matched content will be accessible by \1 in the Replace texbox)
  • \( Look for an opening bracket (the backslash before is there for escaping: so that the interpreter won't think it is a grouping we are about to do)
  • \d* Look for digits, any number of them (\d: digit, *: any)
  • \) Look for a closing bracket
  • .msg Look for the exact text .msg at the end of the filename.

Then just click Rename and voila: the files are renamed to the contents of the New Name column!