By George Lawton [posted by Jack Vaughan]
Usually when developers think about interoperability, they are looking at connecting different servers together, or integrating clients built using one technology with servers built on top of another technology. But in some cases, developers need to integrate Java and .NET desktop application components together.
In a talk at the JavaOne Conference entitled “Java Technology and .NET UI Interoperability: How to Mix and Match UI Components,” Wayne Citrin, chief technical officer at JNBridge, and Robert Bell, senior engineer at Microsoft, discussed how this process can be simplified.
Bell said that most companies have to support both technologies. By developing a process of integrating components of the various technologies together, “the service can be reused in a technology-agnostic way. Interoperability is more than just the wire-level interoperability that most people think of with WCF, JAX, and other low-level stuff. A lot of interoperability is more at the applications stack level.”
.JNBridge develops a Java to .NET interop product that abstracts away some of the complexity in incorporating these two technologies into a single application interface. Citrin said there are a lot of different ways that people like to mix and match Microsoft and Java UI technology. On the Microsoft side, developers are using Windows Forms, WPF, MFC, Win32 APIs, and WPF/E. On the Java side, they are using Swing, AWT (Abstract Windowing Toolkit), and SWT (Standard Widget Toolkit).
Most of the ways of integrating components together can be done in both directions, enabling developers to integrate Microsoft components into Java applications and vice-versa. Citrin said that at the moment, they have identified ways of integrating AWT and SWT components with Windows components, but more work needs to be done to support the integration of Swing components.
One way of integrating the pieces together is through JNI (Java Native Interfaces) and peering. Managed and unmanaged code can be integrated together using the Invocation Interface. The programmer needs to run Java code, which outputs a header file, which is put into C++, and writes a C++ function that will get called from Java. Citrin said this could be a little intimidating. He noted that .NET allows a programmer to create a hybrid DLL containing managed and unmanaged code. The catch is that the hybrid code has to be written in C++.
A peer is an underlying data function that mimics a Java control or a .NET window. For example, in a .NET application, the underlying operating system is controlling the .NET item that mimics the Java control. The problem is that with Swing, lightweight controls don’t have peers. They write directly to the interface.
The next issue is the idea of handles and the related issue of pointers. The problem with pointers is that most underlying operating systems will relocate objects through garbage collection and various compacting technologies. If you have a pointer, which has the address of that object, it might not be there when it moves. Windows uses handles which point to a handle table to get to the object itself.
There are a few things to do to get the handle of a peer of a Java object. First surround the component with an AWT frame. Once you have the frame, you need to get that frame’s handle or the handle of the peers of that frame. Citrin said, “The way we do this is through this strange little dance. From Java you are going to ask the AWT control, ‘What is your handle?’ The AWT control has to call a native routine. We have to step outside of Java into C++ to call a native routine that can then call back into Java through the Invocating Interface. Java cannot get the handle of the peer natively in Java. It has to step out to C++, and C++ has to step around the back of Java and get it through the Invocating Interface.”
Once you have the handle, there is a method underneath in Windows called SetParent, which is declared. You assign the parent its surrounding .NET form, assign a WPF window and embed it in a Java control.
But this whole process is a little complicated, and rife with opportunities for errors. Citrin said it is much easier to use bridging instead of programming interaction within the JNI using a third-party tool like JNBridge Component. He noted, “You can use JNI, but I am not sure a lot of people would want it.”
With bridging, the .NET and Java code each run in their own environment. There is another layer on top that hides all of the detail. JNBridge provides a runtime on the .NET side and a runtime on the Java side. All of the details are hidden from the programmer.
The other advantage of bridging is that JNBridge Component provides a number of wrappers. If you want to embed a Java component in Windows you can wrap it once, and it cause it to look like a Windows Form component. The same thing works in the other direction.
Using this kind of approach, one can more quickly create faster more reliable code than in refactoring the code for different platforms. It also makes the code less susceptible to problems that could occur as updates are made to the underlying Java and .NET platforms.
Citrin said that translation in some sense involves creating new code, and there can be translation errors.
When you do bridging, you work under the assumption that both components will work in their specified and conforming fashion.
A second issue is evolvability.
It is easier to maintain interoperability using bridging as the platforms evolve. When you go from .NET 1.1 to .NET 2.0 or from Java 1.4 to Java 1.5, that might involve changes to the cross compilation of the program.
Companies can also use this approach to increase their market share. Citrin noted that one maker of a Java-base molecular visualizing component was able to double their sales by wrapping the Java control into a .NET control.
One concern that emerged from the JavaOne audience had was the issue of overhead. Citrin said there is some memory overhead in using both environments running in one process, but not a big performance overhead problem.