How to use JNBridgePro with new and emerging languages
Over the last few months, we’ve given examples of how to use JNBridgePro to bridge between various “emerging languages” (for example, Python – here and here, Groovy, and Clojure) and “legacy” Java or .NET code. But what if you encounter a brand new language that you want to integrate with your Java or .NET code? How would you approach this problem? Here are some guidelines.
The “new” language must have an implementation on the Java or .NET platforms. Since JNBridgePro bridges between Java and .NET (or, more precisely, between the Java Runtime and the .NET Common Language Runtime), the new language must be implemented on one of these platforms.
If you want to call from the new language to your Java or .NET, the “new” language must allow for calls to other binaries that run on the same platform. If the language has been implemented on the Java platform (like Jython or Clojure) it needs to have a mechanism for calling other Java binaries. If programs in this language can call Java classes, then they can call proxied .NET classes generated by JNBridgePro, thereby supporting cross-platform calls. Similarly, if a .NET-based language (such as Iron Python) can call other .NET assemblies, then it can call proxied Java classes. In either case, just call the proxied classes and methods in the same way as you would call the Java or .NET classes that the language/environment was designed to support calling.
If you want to call from your Java or .NET code to code written in the new language, the new language, when compiled, must expose an API that can be proxied and called. This is a little trickier. If the new language compiles to object-oriented Java or .NET binaries, then proxying those APIs should be trivial. However, if the new language runs in its own runtime (albeit .NET- or Java-based), then a different approach is necessary. Generally, such languages provide a .NET- or Java-based invocation API that allows outside callers to access the runtime and invoke specified methods. If such an API exists, you can simply proxy it, and use it to invoke the desired methods cross-platform.
For example, if you want to call a Groovy method myMethod from Groovy file myFile.groovy from .NET, you can proxy the Java-based Groovy runtime class groovy.lang.GroovyShell
and java.io.File
(along with supporting classes). Once that’s done, you can write the following C# code to call the method:
using groovy.lang; using java.io; … new GroovyShell().parse( new File( "myFile.groovy") ).invokeMethod( "myMethod", args );
Similar APIs exist for calling Clojure and Jython from Java, and can be proxied and used from .NET.
In some cases the language in question may not offer an obvious invocation API. A number of years ago, we had a customer who wanted to call Fujitsu NetCOBOL code (admittedly not a “new” or “emerging” language) from Java. The compiled DLLs exposed an API that looked like gibberish. In such cases, look for instructions on calling the language in question from other .NET languages; here are instructions for NetCOBOL. If the API that’s used is a managed interface, it can be proxied and called cross-platform.
Make sure you configure JNBridgePro before you make the first proxy call. Once you’ve determined your proxying strategy, and have included proxy calls in your application, you’ll need to make sure that JNBridgePro has been properly configured. If you’re calling from a .NET-based application (in whatever language) you can place configuration information in the application configuration file in the usual way, or you can call the JNBRemotingConfiguration.specifyRemotingConfiguration()
API using whatever mechanism your language allows to call methods in external .NET DLLs. Similarly, if your calling language is JVM-based, configure JNBridgePro through a call to DotNetSide.init()
as you would if you were starting in Java, again using whatever mechanism the language uses to call external Java binaries.
Beware of implicit static initialization. In some languages, explicitly referencing a class can cause the class to be loaded and its static initializers to be executed. This can lead to problems, particularly if the class being loaded and initialized is a proxy class, and the JNBridgePro configuration code has not yet been executed. Recall that this happened in our Jython-calling-.NET example. Like Java, Jython allows you to import a specific class name or a package name (that is, it imports the names of all the classes in the package). However, unlike Java, where the import
statement simply makes names visible the Jython class name import statement (from-import
) actually loads the class and executes its static initializers. This presents a problem when the class is a proxy class; its initializer will be executed at the very beginning of the code, before the configuration code can execute. As we saw in that blog post, the problem can be avoided by using package import
statements, which don’t cause classes to be loaded.
In general, you will need to be aware of your language’s behavior when it comes to loading classes and executing initializers. If this happens before JNBridgePro can be configured, this can cause errors.
There are lots of new languages out there, and many are based on the .NET and Java platforms. Over the past few months, as a way to help alleviate developer fatigue, we’ve provided examples of how JNBridgePro can be used to support interoperability between some of these new languages and Java or .NET. Based on what we’ve discovered when putting together those posts, we’ve put together this framework, so you can approach any novel interoperability scenario involving a new JVM- or CLR-based language. We will be posting new language interoperability scenarios in the coming months, but in the meantime, we hope this framework will be useful for any new interoperability situations you might encounter.
Are you planning any integrations using new JVM- or CLR-based languages? If so, let us know.