Category Archives: OS X Development

Speaking Cocoa From Java

Java on the Mac recently got a major boost to its profile as a platform for building Mac software when JavaFX ensemble was accepted into the App Store. This was not the first Java app to make it into the app store, but it was the first that used JavaFX. Having recently attended a number of talks on JavaFX at JavaOne, I can tell you that it is really something to get excited about, especially if you are a Java developer. The combination of its fast, rich graphics and media support with a first-rate visual GUI builder (JavaFX Scenebuilder) make for a platform on which you can be both productive and creative.

So let’s get busy writing Mac software in JavaFX. Well….. not so fast. In order to comply with App store guidelines, and to provide a native user-interface experience for Mac users, you still need to be able to talk to some native frameworks.

One major problem is that JFileChooser is not compatible with the Mac App Store because it doesn’t work inside the App Sandbox. The current recommended approach is to use the old java.awt.FileDialog class, but this has some serious limitations. For example, if your user enters a file name with an incorrect extension for your purposes, you are not allowed to programmatically fix it, and the FileDialog doesn’t include any features to force a certain file extension. In cases like this it would be really nice to just be able to use the native NSSavePanel class to show a modal save dialog without having to jump through too many hoops. In a previous post, I described how to use JNI to build a Java wrapper around NSSavePanel, and this is a viable way to go, but this is quite a lot of hassle to just be able to use a simple file dialog.

The NSSavePanel example is only the tip of the iceberg. When you start looking through the Mac OS X frameworks, it becomes clear that there are a lot of fun toys to play with, and a few other essentials that you cannot live without. (E.g. if you want to allow in-app purchase, you’ll need to be able to interact with the StoreKit framework).

Do we really have to battle with JNI, every time we want to make a call to an Objective-C library? Luckily, the answer is no. We do have some easier options. The Rococoa framework is an open source successor to Apple’s discontinued Java-Cocoa bridge. It sits atop JNA and provides access to some core Mac OS X frameworks by way of generated Java class stubs. JDK7 and JDK8 have a little documented library called JObjC included with it, that also provides the core OS X frameworks as generated Java class stubs. Unfortunately, both of these libraries suffer from a serious lack of documentation. In the Rococoa case, there is some documentation, but most of it was written in 2005 and much of it no longer works. JObjC doesn’t seem to have any documentation to speak of aside from the unit tests (It doesn’t even include any javadoc comments).

The biggest pitfall of both of these libraries (in my opinion), is that they rely on you to build class stubs for the frameworks that you require. There are build scripts for this (e.g. JNAerator for Rococoa and JObjC has its own Ruby script that generates class stubs using the OS X bridge support XML files), but they don’t work out of the box. And frankly, after spending 3 days fighting with JNAerator and not getting it to successfully build any stubs, I’m not even sure it the current version even works. The trouble with having to run build scripts is that you need to have your build environment set up just right for them to work. If you reach a point in developing a Java application where you just want to call native method, or access a native framework, you don’t really want to have to go and build an entire mess of class structures from source. Or maybe that’s just me.

So then what? Is there a simpler option? Not that I could find. So I built one myself.

Some background on me: I am primarily a Java developer, but I have read numerous books on Objective-C and Cocoa with the anticipation that, some day, I might actually get around to writing a Cocoa App. I, therefore, prefer to write more code in Java and less in Objective-C, but I’m quite familiar with how the Objective-C runtime works and what the Cocoa frameworks have to offer.

One nice thing about Objective-C is that it has a dynamic runtime that you can easily interact with by way of just a few C functions. It provides a means of passing messages
to objects. This is the entire basis for the “Objective” part of Objective-C. JNA is a fantastic library that allows us to call C functions directly from Java. Therefore, using JNA we can interact with the Objective-C runtime via its C API.

When it comes right down to it, all I really need is a few functions:

  1. objc_msgSend(), to pass messages to objects.
  2. objc_getClass(), to get a pointer to a class.
  3. selector_getUid(), to get the pointer to a selector.

And there are a few other useful functions, but I won’t mention them here. The first thing I needed to find out was how an Objective-C object looked inside of Java (using the JNA API). As it turns out, an Objective-C object can be simply represented by its address as a long variable. JNA provides a useful wrapper class, com.sun.jna.Pointer around an address that can be used interchangeably in your JNA method wrappers.

With just this tiny piece of information, you can start to see what would be required to build a generalized wrapper for Objective-C from Java. By obtaining a pointer to a class via the objc_getClass() function and a selector via the selector_getUid() function, you can create an instance of any class by passing the selector to the class via the objc_msgSend() function.

You can then pass messages to the resulting object using the objc_msgSend() function again.

This is almost enough to form the foundation of a one-way, working bridge. But there are, of course a few caveats.

For example the objc_msgSend() only works for messages that have simple return types (e.g. Pointers, ints, etc..). If it returns a structure, then you need to use the objc_msgSend_sret() function, and messages that return a double or float value need to be sent with the objc_msgSend_fret() function.

But, for the most part, this understanding is sufficient for creating a one-way bridge.

After a little JNA magic, we have a simple, low-level API for sending messages to the Objective-C runtime. The following snippet is from a unit test that is testing out this low-level API:

However exciting it may be to be able to send messages to Objective-C objects, this level of abstraction is still too low to be “fun”. So I built a little bit of abstraction over top of this layer to, for example, allow sending messages without having to first look up the class and selector.

The following is a snippet from another unit test that is sending messages at a slightly higher level of abstraction:

And this can be improved even more:

At this point, we can quite easily interact with Cocoa without too much pain. But we still aren’t quite at the level of abstraction that we like. The next step would be to build an object-oriented wrapper around the Objective-C objects so that we’re not dealing directly with Pointers and long addresses to objects.

For this, I created the Client and Proxy classes. The Client class is an singleton class that allows you to interact with the Objective-C runtime. It allows you to send messages to objects, and it provides automatic type mapping for both inputs and outputs so that the correct message function is used. E.g. using Objective-C Type codings for messages, it determines the return type and input argument types of the messages so that the correct variant of objc_msgSend() is used and that the output is in a format of our liking.

Objective-C objects are automatically converted to and from Proxy objects
(which are just wrappers around the Objective-C object pointers). NSString objects are automatically converted to and from Java Strings. It also introduces a set of
methods for sending messages that expect a certain return type. E.g. The sendInt() method is for sending messages that return ints, and sendString() method is for sending messages that return Strings.

The Proxy class is a thin wrapper around an objective-C object. It uses a Client instance to actually send the messages, and it provides wrappers around all of the relevant send() methods.

The following is some sample code that interacts with the Objective-C Runtime at this slightly higher level of abstraction:

At this level of abstraction, it is pretty easy to add little bits of Cocoa functionality into our Java application. But there is one Major thing missing: Objective-C to Java communication. This is critical if you want to be able to write delegate classes in Java that can be passed to Objective-C objects to handle some callbacks.

Calling Java From Objective-C

One-way communication will get you only so far. If you need to pass a callback to an Objective-C message, or write a delegate class in Java that can be called from Objective-C, we’ll need full two-way communication.

There are a few ways to accomplish this, but I chose to make use of the NSProxy and a little bit of JNI to create an Objective-C object that acts as a proxy to a Java object. Whereas our Proxy Java class that we defined before contained a one-way link to its native peer object, the NSProxy subclass will provide its own one-way link to its Java peer. Combining these two strategies, we end up with a two-way bridge between Java and Objective-C, such that we can call Java methods from Objective-C, and Objective-C methods from Java.

I’ll go into detail on how this was achieved in a future post, but for now I’ll give an example of how the resulting API looks from the Java side of things.

The following is a sample application that opens the NSOpenPanel dialog and registers itself (a Java class, which is a subclass of the NSObject Java class) as a delegate for the dialog.

We introduced a special annoation @Msg to mark Java methods that should be accessible as Objective-C messages. This allows us to specify the selector and signature for the message in a way that the Objective-C runtime understands. Notice that we can even use the Proxy.send() method to send messages to our Java class. This actually sends the message to the Objective-C runtime, which pipes it back to the Java class to be handled — and if the Java class doesn’t define a method to handle the message, it will pipe it back to Objective-C to be handled by the superclass.

To find out more and download the library…

You can download the source or binaries for this project on Github. I have also posted the Javadocs here.

.NET: The most unlikely savior of Desktop Java on the Mac

When Microsoft first introduced the .NET platform and its flagship programming language C#, I, like many Java developers, looked at it and said “They’re just copying Java”. Why would I want to develop on the .NET platform which is targeted exclusively at Windows, when I could use the more established Java language and deploy across all platforms including Mac and Linux?

When I heard rumblings of the open source version of .NET, called Mono being developed, I was curious but ultimately wrote it off as it was likely that, since .NET was married to Windows in so many ways, probably most of the libraries for .NET would be platform specific and wouldn’t run properly on Mono anyways.

The past 10 years have seen many new trends come and go, and quite a few shifts in mindshare between the different technologies. One stream of trends that I have been quite interested in as a Java developer and a Mac user, is the role of Java on the Mac.

When Apple first unveiled OS X, Java was at the center of it. They promoted Mac as an excellent platform for Java developers to deploy their programs. They pledged to provide a Mac-specific implementation of Java that would blend into the OS and work seamlessly with the slick new look and feel of Mac. Two key pieces of this puzzle were the Swing Aqua look and feel and the Java Cocoa Bindings. The Swing Aqua look and feel allowed all Swing (the default java UI toolkit) programs to look like native programs on the mac. The Java Cocoa bindings allowed even deeper integration by allowing Java programs to use the native Objective-C classes and widgets directly.

Fast forward to 2011. If you try a google search for Desktop Java on the Mac or related terms you’ll notice that there are lots of articles, tutorials, and documents from the period ranging from 1997 to 2005. But very little after that. This is due to a number of trends and developments during that timespan. Some of these include:

  1. Apple deprecating the Cocoa Java bridge. (Turns out that is wasn’t used very much anyways because Java developers could achieve an almost native look and feel using Swing and keep cross-platform compability).
  2. Java mindshare had moved predominantly to server-side technologies.
  3. The emergence of higher-productivity interpreted dynamic languages like Ruby and Python had stolen a lot of mindshare on the desktop.
  4. Objective-C through the introduction of the iPhone and iPod had drastically increased in mindshare – so more developers were familiar with the native tools and would forego trying to work with a language such as java for native applications.
  5. Sun seemed to be confused as to which direction it wanted to go – and years of progress were lost (* more on this later).

Nonetheless, during the period of 2005 to present, there have still been some good options for producing high quality desktop applications for the mac. After all it was the only OS with a large user base that shipped with Java. This meant that you could develop for Java and be certain that the target users would be able to use your software without having to download anything extra. Swing still has the Aqua look and feel, and all of those tools and widgets that were developed pre-2005 still worked nicely (except of course those tools that were built upon the Cocoa-Java bridge).

Unfortunately the writing was on the wall and Apple made it official in October 2010 when it announced that it would be deprecating Java on the mac and that future versions of the operating system would not ship with it. It would be up to the open source community and Java’s owner Oracle to provide a Java for the future of the Mac (and this future is still very much unfolding as I type).

So now, at a time when the future of Java on the Mac is as bleak as ever, an unlikely ally enters the fray: .NET – or rather its open source twin, Mono.

Mono has quietly been picking up a following over the past 10 years. It reached 1.0 status in 2004, and has facilitated the development of 2 separate projects, which, together appear to offer the best hope for the future of Java on the Mac:

  1. IKVM.NET – A Java virtual machine that runs on .NET and Mono. This tool is able to run Java byte code in Mono and use java libraries natively. It also includes tools to statically compile java as a .NET executable which can be used in .NET or Mono applications. This has opened many doors to both C# and Java allowing libraries developed with java to be quickly compiled a distributed for .NET (e.g. Apache’s PDFBox which is developed in Java but available for both .NET and Java).

  2. The Mono Mac project – An objective C binding that allows C# code to directly access the Mac Cocoa classes. The current versions of MonoDevelop (the Open Source Mono IDE) work seamlessly with Apple’s developer tools, especially interface builder so that developing and deploying an application for the Mac using C# is a first class experience.

These two projects together open up a myriad of possibilities for Java on the mac that haven’t been available since the deprecation of the Cocoa-Java bridge. If you have a large existing source base of java code and libraries, you can quite easily now compile them into a Mono library that can be used in a Mono Mac application – and then deploy it natively on the Mac and even distribute your applications in the Mac App store.

And this is how a Windows-Only competitor of Java has evolved into an unlikely ally in staying relevent on the Mac platform.

How to get a Java Application into the Mac App Store

I just received a reply from Apple support confirming that there is nothing in their guidelines that prohibits apps that include an embedded Java virtual machine. Therefore, Apple’s regrettable decision to deprecate Java and disallow apps that depend upon it from entry into their new App store is a mere speed bump and not the road block that I had originally believed it to be. So there are a number of strategies for getting Java into the Mac app store: 1. Embed a java runtime environment as part of the application bundle. Currently there are no Mac JVMs that can be distributed which support Swing with the Quartz UI (i.e. graphical Swing apps won’t look native, if you can even get them to work). However Oracle and Apple’s recent announcement that Apple will be donating source code to the OpenJDK project suggests that this will be resolved with Oracle’s release of JDK7 on the Mac. In the mean time it would be possible to embed third party JVM like Soy Latte or IKVM (a .Net implementation of java) and use Rococoa as the UI. 2.** Use GCJ (The GNU Java Compiler)** which can be installed via Mac Ports, in conjunction with Rococoa for the UI to compile your application into a native binary.

Resources

  • Mono for Mac Resource: This page shows some resources related to Mono support on the Mac. Why is this relevant? Because Mono is the open source, cross-platform implementation of the .Net framework and it supports IKVM, a fully-functional java virtual machine that runs on Mono. IKVM will allow you to convert your java applications into .exe files that will run on Mono, which can be embedded in your application bundle.
  • Example using Rococoa to use Quartz framework from java
  • Rococoa GUI Demo : This tutorial shows a short sample of how to use Interface builder to build an interface for your java application using Rococoa.