JNBridgePro supports the creation of scalable and flexible distributed applications. Developers can access Enterprise JavaBeans, JMS, JNDI, and other services from .NET clients (Enterprise Edition only). JNBridgePro provides support for transactions via thread-true classes. The classes ensure they are managed by the same .NET-Java thread and guarantee data integrity. With JNBridgePro version 1.3.4 EE, developers can employ Java code in the .NET Framework as though Java is a .NET language. Fields, methods, and Java classes can be called from .NET classes without the caller being aware that the accessed classes are actually written in Java.
Microsoft .NET programmers can derive classes from Java. This feature allows the inherited classes to be written in a .NET language of choice, such as Visual Basic .NET, C#, J#, or managed C++ to name a few. The inheritance will be reflected on the Java side. Therefore, method calls overridden by derived .NET classes are redirected back to the .NET assembly. Subsequently, the Java classes can be linked to directly, or accessed over the network. This methodology supports a wide variety of platform architectures and communication mechanisms. An additional JNBridgePro benefit permits .NET classes to be implicitly accessed from Java code through the familiar Java callback listener method. (Java callbacks are discussed later in this chapter.)
In order to work along with this chapter, an evaluation copy of JNBridgePro can be downloaded from the JNBridge web site. Because web site URLs can change quite frequently, simply type JNBridge into a search engine.
Before examining the features that JNBridgePro offers developers, let’s examine the infrastructure. The architectural details for the .NET-side are as follows:
.NET management This is performed by the CLR.
Proxy generator The JNB Proxy Generator creates the class proxies.
.NET classes All .NET classes call the generated proxies. The proxy acts as the intermediary. In fact, this action is mandatory.
Generated proxies The .NET assembly consists of generated proxy binary information.
Runtime component This consists of a set of core proxies and classes to manage Java-.NET communications and references to Java objects. This can be a standalone application, an ASP.NET web application, or web service.
Details of the Java-side are as follows:
JVM A standalone JVM or application server containing a J2EE servlet container
Java runtime component SOAP or Fast Binary Protocol based on .NET remoting
Object reference table Points to individual Java classes
JNBridgePro includes JNBProxy, a graphical user interface and proxy generator, and JNBCore, the interface that manages communications between .NET and the JVM. The JNBridgePro runtime architecture consists of a set of Java binaries (JAR or class files) containing the legacy Java code that runs on a JVM and Java Platform (J2SE) or (J2EE). This is the environment in which the Java code executes.
The JNBCore module manages communications between native-side proxies and the JVM. The JNBCore represents a uniform interface to either the .NET remoting framework that includes SOAP, the XML-based mechanism for invoking methods remotely on objects, or the faster binary protocol.
Residing on top of the JNBCore module is a set of native-side proxy classes that make up a .NET assembly, through which the .NET code accesses Java binaries. There must be one proxy class for each Java class accessed by .NET code. The proxy’s invocation interface matches the corresponding Java class. In order to create a corresponding Java object, the .NET code invokes the appropriate constructors on the proxy class and procures a reference to the new proxy object. To access a member field or method in a Java class, the .NET code invokes the corresponding field accessor or method in its associated proxy class.
Primitive values or references to proxy objects can be passed as parameters or returned as values. Exceptions thrown by Java objects are thrown back to the .NET code that invokes the proxies.
JNBProxy can be instructed to generate proxies for Java classes accessed by .NET code. This includes superclasses, exceptions, interfaces, return values, and parameters, or for that matter, any subset of them in between. Generating proxies for the maximum set of classes provides fine-grained granularity and maximum flexibility.
The key features offered by JNBridgePro include the following:
Cross-platform and cross-language support and portability
Large-scale distributed application support
The ability to integrate Microsoft .NET with Java classes enables Java classes to function as though they are in reality a .NET-supported language. This technology requires no change to the Java code base. In fact, JNBridge LLC suggests developers can even make use of third-party libraries to achieve class integration. Despite Java and .NET class intermingling, the Java code remains cross-platform portable and conforms to existing J2EE standards.
Java code can run on a .NET machine or, for that matter, any machine supporting the JVM or a J2EE-compliant application server. An additional benefit is the ability to call Java classes and methods from any .NET-targeted Framework language.
Class-level interoperability provides access to Java objects and classes from .NET via proxies generated by the proxy generation tool JNBProxy. This tool lets developers explore the interfaces and functionality of the available Java classes, allowing them to determine through a visual interface which classes should be exposed to .NET. Once the decision is made, JNBProxy generates the required proxies and writes them to a .NET assembly DLL file. Therein lies the key to understanding how JNBridge Pro functions.
Once the proxy is generated, .NET invokes all Java classes, methods, and fields on the proxy interface.
As you may recall from Chapter 5, the .NET assembly is made up of two essential components: the manifest and the assembly itself. The manifest contains the metadata about the assembly. The assembly contains version information and the name of the assembly as well as the application binaries.
The first portion of the assembly references all external assemblies required by the current assembly to execute the application successfully. The second segment of the assembly enumerates each module contained within the assembly. It is possible to load the assembly at runtime and procure a list of all types contained within a module. This includes both .NET and Java methods, events, fields, and properties. This is achieved by means of reflection.
Each class whose functionality is exposed causes a proxy of the same name to be generated. Generated proxy members (constructors, methods, and fields) correspond to the members of the Java class underlying the proxy. Microsoft .NET interacts directly with the proxies rather than with the actual underlying Java classes.
Developers can call methods, access fields, create objects, access static and instance members of Java classes, and catch exceptions thrown by Java classes through the proxies.
Beginning with version 1.3, JNBridgePro supports both reference and value objects. Passing by reference is faster than passing by value. A JNBridgePro reference is always smaller than the corresponding object. Moreover, repeated access to members of a reference object requires frequent trips between .NET and Java. In contrast, passing an object by value may take longer because the value object is larger. However, subsequent member accesses are much quicker because the data resides locally. Therefore, round-trips between Java and .NET are avoided. This enhances performance. It is always important to evaluate and determine which method offers increased performance. It always depends on application requirements.
Class-level interoperability allows developers to use Java’s event listener methods. The .NET code can be called from Java via the standard Java callback mechanism, allowing the Java code to remain portable. For example, EJB containers are responsible for managing entity beans. Containers interact with entity beans by calling a bean’s management or life cycle methods as necessary. These methods represent the bean’s callback methods that only the container invokes, not the caller. These methods allow the container to alert a bean when middleware events occur, such as when an entity bean is going to be persisted to storage.
Java primitive types, strings, and arrays are automatically converted to corresponding .NET primitives, strings, and arrays. In contrast, the .NET primitives, strings, and arrays can be passed as parameters to Java classes and are subsequently converted to their Java counterparts.
With version 1.3, JNBridgePro automatically maps between native Java and .NET collection objects. Java ArrayLists, LinkedLists, Vectors, and HashSets are converted to .NET ArrayLists when they are returned from a .NET call to a specified Java method. Conversely, ArrayLists are converted from .NET to Java when they are passed as parameters in a call from .NET to a Java method. JNBridgePro maps between Java Hashtables, HashMaps, and .Net Hashtables as well.
.NET classes can inherit from Java classes by inheriting from the Java classes’ proxies. Calls to any methods that the new class does not override are directed to the underlying Java class. Additionally, .NET classes may implement Java interfaces by implementing their proxies.
Once a proxy DLL is generated, the developer adds it to the current project. This allows the developer to access Java classes from .NET, a technique of considerable significance. Remember, the proxy DLL is written to the .NET assembly, the place where all information about Java classes, methods, and fields reside.
How is it possible to construct a Java object from .NET code? Simply call a constructor that corresponds to the Java constructor bearing the same name signature of the associated proxy class. In order to invoke an instance method on a Java object, the .NET code invokes the appropriate method or accesses the specified field on the corresponding proxy object.
All .NET interaction with Java occurs through the generated proxy for a specified Java class. Every Java class contains a corresponding proxy.
Invoking a static method or field on a Java class calls the corresponding proxy class. Finally, if a Java method throws an exception, the .NET method catches the exception. Additionally, if the proxy method is no longer referenced, it is garbage collected, providing there are no further references to the object.