OS X Development at its finest!

May 11, 2008

This is development at its finest - three (3) 30″ Cinema Displays hooked into an 8 core 3.2 Ghz Mac Pro tower.  Unfortunately, this is not my daily setup - yet.  I was lucky enough to experience a week on this setup and experienced withdrawal when having to ‘downsize’ to my single 30″ display powered by my 17″ Macbook Pro.  The girl scout cookies were an added bonus! 


SWT / AWT bridge users meet Albireo

May 6, 2008

Yes its alpha and yes its a hard name to pronounce but it solved a lingering SWT / AWT bridge issue I was facing on OS X Leopard.  

Specifically, I had an issue with native dialogs such as DirectoryDialog and FileDialog on Leopard.  When these would pop up, they would fight for focus with the application window, resulting in flickering and non-functional controls. 

I’m happy to say that Albireo made problem go away!

http://www.eclipse.org/albireo/


Building OS X Install Packages with Ant

May 6, 2008

Lets say you want to create a nice installer for your OS X application that looks something like this -

Lets also say you want to it completely automated so you can do it with a simple one line command OR make it part of an integration build process.

Using XCode’s PackageMaker tool and ant, its pretty simple to create a build.xml that automatically creates a package for you.  In fact, its even easier for you because I’ve already created a sample project that does this!

Requirements

You will need the following tools

This article assumes you have are familiar with Apache ant.

Quick Start

Download the AntPackageMaker sample project -

  1. Open a teminal
  2. cd into its directory
  3. Type ‘ant’ 

This will create a package installer for the world famous TextEdit application in the directory ‘pkg’.  You can open this directory in Finder and double click ‘TextEdit.pkg’ to see the results!  Move on to the next section for customizing AntPackageMaker for your own project.

AntPackageMaker Project Overview

This sample project contains a template package to use for creating a customized package, a sample application (TextEdit.app) and ant files necesary to create the package.  

Files and Directories

  • build.xml - The ant build file
  • bundle/ - Put your application bundle here - i.e. MyApp.app.  Don’t forget to remove TextEdit.app!
  • pkg-src/ - The package template files
  • pkg.properties - The ant properties files for building the package

Customizing

Here’s what you need to do to customize this project for own app. 

  1. Copy your application into the ‘bundle’ directory. Make sure you remove TextEdit.app
  2. Customize the files License.rtf and Welcome.rtf in the ‘pkg-src’ directory.
  3. Change the background.gif image in the ‘pkg-src’ directory and, yes, it has to be a GIF.  
    TIP - Make sure you save it with transparency and set the transparency matte to #EEEEE
  4. Open pkg.properties in a text editor and change the values as necessary.  You could even use TextEdit - just make sure to keep the formatting pain text!

Here’s a look at pkg.properties - all you need to change is ‘pkg.name’ to the name of your application.

## Package Properties

# Application name - here we’re bundling TextEdit
pkg.name=TextEdit

# Location for the application bundle, i.e. TextEdit
# This sample project has TextEdit in the local ‘bundle’ directory
pkg.bundle=${basedir}/bundle

# Directory where the package template lives
pkg.src.dir=${basedir}/pkg-src

# Directory where we will create the package
pkg.dir=${basedir}/pkg

# The actual package
pkg=${pkg.dir}/${pkg.name}.pkg

# The package Info.plist - gets autogenerated
pkg.info=${pkg.src.dir}/Info.plist

# The package Info.plist template to use
pkg.info.template=${pkg.info}.template

# The package Description.plist - gets autogenerated
pkg.description=${pkg.src.dir}/Description.plist

# The package Description.plist template to use
pkg.description.template=${pkg.info}.template

Usage

Feel free to use this however you wish! If it helps you out, I’d love to hear about it.


Handle Native OS X Application Events in SWT

May 3, 2008

If you’ve been stumped on how to cover that ‘last mile’ with making your SWT application look completely native on OS X, take a peek at the open source project Azureus.  In my case, I had 2 issues left to figure out -

  1. Capture and handle dock icon click events
  2. Add additional menu items to the application menu

Follow the link below and look at the class ‘CarbonUIEnhancer’.  This class demonstrates how to hook into OS X’s application menu and handle AppleScript events.

Browse Azureus swt.osx source package 


Twitterrific Feature - Automatic Tinyurls!

April 30, 2008

I like Twitterrific alot but I hate having to take the URLs I want to post and manually converting them using tinyurl. It would be awesome if there was an option (turned on by default of course!) that scanned my tweet and converted all urls *on the fly* to tinyurls.  

I sent a tweet to the Twitterrific twitter account requesting this feature.  I’m sure I’m not the first but I’m hoping my vote influences the next feature set for Twitterrific. 


SWT OS X HelpBook Registration

April 29, 2008

Lets say you’re building a stand-alone SWT application (read: not eclipse RCP) and want to use the native OS X help system. You’d like to have the nice Apple Help menu in the menu bar and have your application register a HelpBook that gets indexed by the native help system. A very admirable goal that most developers would assume to be a trivial last step before the ship date.

Trivial depends on one key element in the preceding paragraph and that element is SWT. If I had typed Swing instead, well, you would have found many articles that tell you exactly what you need to do and you wouldn’t be reading this one.

This article walks you through a simple process to get your HelpBook registered properly if you’re developing a stand-alone SWT application.

NOTE - Before preceding, you should already be familiar with deploying Java applications in OS X as application bundles. There are various ways to do this, some better than others, but that is for another article.

The Problem

You google and search Apple’s developer connection site, eventually finding documentation on how to deploy and register your HelpBook.

Most developers, including myself, stop at registering the HelpBookFolder and HelpBookName properties in “Info.plist”.  This works great for Cocoa applications, however, if you read a bit further, Apple lays down the money quote -

Carbon applications must call AHRegisterHelpBook even if they do not use any other Apple Help. If a Carbon application does not call AHRegisterHelpBook, the application’s help book does not open when the user chooses the application help item from the Help menu. In addition, Help Viewer does not include the help book in the Library menu.

Apple tells you exactly what you need to know IF you understand that SWT, as of version 3.4 and below, is based on Carbon and therefore your Java application is effectively a Carbon app.

Solution Time

First, make sure you register properties HelpBookFolder and HelpBookName in your Info.plist as described in Apple’s HelpBook documentation. You then need to use JNI so you can call AHRegisterHelpBook from your SWT application.  

Java JNI Stub

This class is what you call from your SWT application to force the registration of your helpbook. All you do is call ‘HelpBookCarbon.registerHelpBook()’ at some point in your application’s startup.

package your.package.name;

public class HelpBookCarbon {
	static {
		System.loadLibrary("HelpBookCarbon");
	}
	public static native void registerHelpBook();
}

Native Code

Next you’ll need to create a simple native library called “HelpBookCarbon”. I suggest using XCode as its the easiest way to build a unversal binary JNI library.

JNIEXPORT void JNICALL Java_your_package_name_HelpBookCarbon_registerHelpBook(JNIEnv *env, jclass clazz) {
  	FSRef bundleRef;

        CFBundleRef bundle = CFBundleGetMainBundle();
	if (bundle == NULL) {
		return;
	}

	CFURLRef bundleUrl = CFBundleCopyBundleURL(bundle);
	if (bundleUrl == NULL) {
		return;
	}

	if (CFURLGetFSRef(bundleUrl, &bundleRef)) {
		AHRegisterHelpBook(&bundleRef);
	}
}

You should end up with a library called ‘libHelpBookCarbon.jnilib’. Place this in your java system library path and you should be good to go. If you’re not familiar with loading JNI libraries, checkout
Sun’s guide to JNI

Other Notes

There are a couple of solutions posted on Apple’s mailing list that are a waste of time if you’re not planning on providing contextual help or controlling the Help viewer from within your application.

One of those is Apple’s Help Hook. While interesting to play with, this does not address the issue at hand - SWT/Carbon applications need to explicitly register their help with a call to AHRegisterHelpBook.

Download

I need to find a good place for providing file downloads.  In the meantime, just send me an email, mcoopet@gmail.com, and I’ll send you the universal JNI library / XCode project. 


Building SWCs with Flex Ant Tasks

October 3, 2007

Using Flex Ant Tasks with the Flex SDK is a great way to do automated builds for your Flex Projects. Flex Tasks provide Ant task interfaces for compiling both applications (*.swf) and libraries (*.swc).

<compc> Requires Manually Specified Class Names!

The compc task comes up a little short in that you have to specify ALL of your classes you want in your component library like this

<compc

output=“MySWC.swc”

include-classes=“my.package.MyClass1 my.package.MyClass2″>

<source-path path-element=“${basedir}”/>

</compc>

 

Most of the time, I find myself wanting *all* of my actionscript classes in the component library SWC file. More importantly, I do not want to have to update an Ant target if I add classes to the library.

You might ask ‘well why not generate a fileset and pass it to the include-source attribute?’ Great idea except the compc task doesn’t support include-source. Boo!

*Sigh* - it would be nice if I could just have my classes auto-generated for this compilation task!

Use Ant to Auto-generate Class Names

After some googling, I found that there really isn’t a built-in mechanism for doing this. Below you’ll find a sample target I put together that auto-generates the class names to pass to compc based on the actionscript filenames it compiles.

<target name=“swc”>

<fileset id=“sources” dir=“com”>

<include name=“**/*.as”/>

</fileset>

<pathconvert property=“classes” pathsep=” “ refid=“sources”>

<chainedmapper>

<globmapper from=“${basedir}/*” to=“*”/>

<mapper type=“package” from=“*.as” to=“*”/>

</chainedmapper>

</pathconvert>

<echo message=“classes is set to = ${classes}”/>

<compc output=“MySWC.swc” include-classes=“${classes}”>

<source-path path-element=“${basedir}”/>

</compc>

</target>

 

 

The target uses the fileset, pathconvert and mapper tasks available in Ant.

  1. It finds all of the actionscript source files with a fileset.
  2. It converts the list of files to a single line with each file separated by a space
  3. Using mappers, it then converts the filename to a package/class name notation

Note that your project should define the ‘basedir’ property in the initial ‘project’ tag.

By using Ant to autogenerate classnames from actionscript filenames, my library build files are alot easier to maintain. Hopefully it’ll do the same for you!


Command-line History Autocomplete in OS-X

October 3, 2007

A really nice command-line trick is to enable history autocomplete via up and down arrows. For example, if I am looking for an old ‘grep’ command, I could cycle through all greps in my history simply by typing ‘grep’ UP-ARROW.

All you need to do is add the following lines to the ‘.profile’ file in your home directory.

# make bash autocomplete with up arrow/down arrow
bind '"\e[A":history-search-backward'
bind '"\e[B":history-search-forward'

Note - You’ll need to start a new terminal session for this to take effect.


Creating Eclipse Workspace Launchers in OS-X

September 1, 2007

The Problem

I often run multiple instances of Eclipse in different workspaces for development -

  • One for front-end application work in Flex
  • One for back-end services work in Java

Since I develop on OS X and use Quicksilver, I’d love to just launch each instance using Quicksilver.

Step 1 - Create a Separate Eclipse Launcher

There are lots of ways to launch separate Eclipse instances. The way outlined below lets you launch separate instances from the dock, Spotlight or, my preferred mechanism, Quicksilver.

First, open up a Terminal and type the following. Make sure to replace ‘/Applications/eclipse’ with the path to your eclipse installation.

cd /Applications/eclipse

Next we make a copy your existing Eclipse.app. Name this whatever you like as long as it ends with ‘.app’. For this example, we’ll call it ‘MyEclipse.app’.

cp -R eclipse MyEclipse.app

Now we need to edit some files in MyEclipse.app. Note - Replace ‘vi’ with your favorite editor.

cd MyEclipse.App/Contents
vi Info.plist

Now you’ll want to replace

<key>CFBundleName</key>
    <string>Eclipse</string>

with

<key>CFBundleName</key>
  <string>MyEclipse</string>

Step 2 - Set Default Workspace

Now that we have a separate Eclipse Launcher, lets configure it to open a specific workspace. For the example, replace ‘/Full/Path/To/Your/Workspace’ with your actual workspace directory.

Using the same Terminal session, we edit the file ‘eclipse.ini’ to configure Eclipse. Make sure you are still in the ‘/Applications/eclipse/MyEclipse.app/Content/’ directory.

cd MacOS
vi eclipse.ini

At the top of the file, add

-data
/Full/Path/To/Your/Workspace

Note - Its important that you put -data and /Full/Path/To/Your/Workspace on separate lines. ‘eclipse.ini’ is parsed in such away that options and the arguments to the options have to be on their own line.

Problem Solved!

At this point, you can open a Finder window to your Eclipse installation directory (i.e. ‘/Applications/eclipse’) and drag ‘MyEclipse.app’ to your dock if you wish. Or you can just launch it using Spotlight or Quicksilver. ‘MyEclipse.app’ will launch an eclipse using the workspace you assigned in Step 2. You can repeat this process for any number of Eclipse launchers you want.

Launching under Spotlight

MyEclipse.app in Spotlight

Launching in Quicksilver

MyEclipse.app in Quicksilver


Get Method Parameter Names with Java2WSDL

August 2, 2007

Are you using Axis for web services and wondering why your WSDL describes services whose parameter names appear to be auto-generated, i.e. ‘in0′,’in1′,’in2′? This post is for you!

Say you want to use the Axis utility Java2WSDL to generate a WSDL from your Java class. Assume you have a file called Test.java like this -

public class Test {
    public void test(String testParam) {
    }
} 

Java2WSDL, via ant task or command-line, would ideally generate a WSDL with an operation called ‘test’ and a parameter to the ‘testRequest’ called ‘testParam’.

<wsdl:message name=”testRequest“>
      <wsdl:part name=”testParam” type=”soapenc:string”/>
   </wsdl:message> 

However, if you compiled Test.java without the -g option (debug) and run Java2WSDL on the resulting class file, you’ll end up with ‘testRequest’ having a a parameter named ‘in0′.

  <wsdl:message name=”testRequest“>
      <wsdl:part name=”in0” type=”soapenc:string”/>
   </wsdl:message>

Because Java2WSDL relies on the compiled class file and not the source file, the class file needs to be compiled with the debug option so it can provide method parameter names. In fact, if you compile Test.java without debug and open it in eclipse, you’ll see that the ’source’ shows a method declaration like this

public void test(String arg0)

Compile it with debug turned on and the method declaration looks like this

public void test(String testParam)

This information is covered by one line in the Axis user’s guide -

Note: If you compile your class with debug information, Java2WSDL will use the debug information to obtain the method parameter names.

Side Note

As a practice, we define a set of services in an interface class and then provide a concrete implementation class. As I was doing testing for this article, I found that *no debug* information is provided when you compile an interface, even if you specify all of the debug flags to javac.

Bottom line - if you want the parameter names for your methods to appear in your WSDL, make sure you reference actual classes and not interfaces when using Java2WSDL.