Binding Java and Web Services to Native Code
The process of metadata generation is shown in Figure 5 and will largely depend on the implementation of tools using the Native Connector Architecture. Examples of metadata sources include:
- Compilers. During the process of compilation, the compiler can emit the metadata that is required by the system.
- Introspection Tools. Certain languages (such as Java, Visual Basic, and languages designed for Microsoft .NET) encode metadata into the generated binaries. Such data can be extracted by introspection tools, which can emit the data required by the system.
- Code Descriptor Databases. While generally not as complete, databases of source data (such as found with source browsers) may be used to generate the metadata. The drawback may be incompleteness because some information needed for correct generation may not be present.
- Other Tools. Other classes of tools that can provide such information, such as interpreters.
Figure 5: Metadata Generation Phase
The process of component specification can be performed automatically or manually and is shown in Figure 6.
Figure 6: Component Design/Specification Phase
The limitations imposed on automated component specification are largely driven by the compatibility between the languages being bridged as well as whether a set of rules can be devised that can automatically handle issues such as naming conflicts, type promotions, or conversions. In contrast, a fully manual implementation requires user interaction to drive the component specification process, including choosing the interfaces, identifiers used, and parameter conversions, as well as the management of unsupported types and methods.
The ideal solution is a hybrid, one in which a tool based on the NCA will handle much of the automated conversion process by the judicious use of established defaults for naming conventions, parameter usage, and conflict resolution. Such a tool will flag elements it cannot handle appropriately and allow the user to interact with the tool to resolve conflicts.
Code generation (Figure 7) is the process of creating the bridge code to map between the two sets of APIs, those present in the target and those specified as part of the client interface.
Figure 7: Code Generation Phase
Since the metadata used to describe both sets of APIs is a specific schema based on XML (PLanML), the architecture defines the use of XSL stylesheets to drive a pattern-based code generation process. Tools based on NCA will consume PLanML and pass this data to an XSL processing engine. In general, this may require multiple passes through the processing engine, once for each type of output desired. This approach may be useful for extensibility, since properly factored XSL stylesheets can be used in alternative bridge generation scenarios.
Build, Assembly, and Deployment
The final process involves taking the generated source, building the result into usable binary components, and packaging the results for deployment, as shown in Figure 8.
Figure 8: Build, Assembly, and Deployment Phase
While building is generally independent of the type of bridge or target environment (the latter may require building on the target platform), packaging and deployment will change depending on the type of bridge being created. For example, when deploying into the J2EETM environment, the location, naming and descriptor information will need to be different than that of a standalone J2SETM application.
Because a bridge generated by a tool such as the Sun ONE Studio Native Connector Tool is fully automated, and the target type is known, the system knows precisely which components were generated and is fully capable of not only generating the build rules (for example, scripts or makefiles), but populating the resulting packages appropriately and emitting descriptor data needed for deployment.
To illustrate the differences between JNI and Native Connector processes, Figure 9 provides a comparison of the steps involved in each.
Figure 9: Process comparison between JNI and a Native Connector implementation.
As can be seen from the above, most of the steps required by JNI are manual in nature, while those required by a Native Connector Architecture implementation are generally automatic:
- Metadata Acquisition. There is no counterpart in JNI. The Native Connector Architecture derives this metadata via implementation-provided tools.
- API Specification. In JNI, this is enabled by the use of the native keyword and then later manual invocations of javac and javah. NCA derives these APIs either manually via some implementation-provided tool or via manual specification.
- Code Generation. JNI code must be manually created as part of the implementation of the bridge. Under NCA, code generation is fully automatic.
- Build. Manual under JNI, automatic under NCA.
- Assembly. Manual under JNI, automatic under NCA.
- Deployment. Manual under JNI, automatic under NCA.
The Native Connector Architecture defines a model for the easy, automatic generation of components in, for instance, the Java language, which are bound to existing legacy implementations written in languages such as C and C++. The architecture and tools provide an extensible model for the addition of new bridge types and support for additional languages and platforms. While at this time tools exist that allow for the generation of J2SE and J2EE Connectors to C and C++, future implementations will likely provide additional capabilities and language/platform support, such as interoperability between Microsoft .NET components and other popular languages, such as Fortran.
About the Author
Robert Brewin is the Architect for Enterprise Development Tools responsible for architectural and engineering issues for Sun ONE Studio products.
Sun, Sun Microsystems, the Sun Logo, Sun ONE Studio, Java, Solaris, J2SE, and J2EE are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries.
Page 3 of 3