.png)
Microsoft Corporation
December 2003
Summary: Concentrates on the point to point communication methods of XML Web services and .NET Remoting. Topics include binary communication and routing, together with the use of third party runtime bridges for integrating Java and .NET.Contents.
Contents
Using .NET Remoting for Connectivity
Implementing Runtime Bridges
Connecting with Web Services
Summary
References
Designing an effective interoperability solution requires a detailed understanding of the techniques used to connect Java and .NET Framework systems. This chapter looks at the means you can employ to link the two platforms in point to point scenarios, where one application interoperates synchronously with another.
The technologies that allow .NET Framework and Java to interoperate on a point to point basis fall into two main categories:
- .NET Remoting
- XML Web services
.NET Remoting is the first technology covered; it provides advantages such as greater performance and easy implementation in a pure .NET Framework environment. However, Java applications cannot connect using .NET Remoting directly; they require the implementation of a runtime bridge. This chapter investigates two of the most popular runtime bridge offerings, Ja.NET and JNBridgePro.
Web services are increasingly fashionable whenever developers and system architects start discussing interoperability. Web services certainly promise ubiquity and the freedom from having to describe methods explicitly, but they are not always the best interoperability solution.
Using .NET Remoting for Connectivity
In Chapter 2, "Understanding Enterprise Platforms," you learned that .NET Remoting is Microsoft's communication and data transfer mechanism for distributed applications built on the .NET Framework. While primarily designed for communication between .NET Framework applications, .NET Remoting provides an extensible communication framework that you can build on and customize to enable connectivity with Java applications.
To use .NET Remoting for interoperability with Java applications, you must implement a runtime bridge, and you look at two of these, Ja.NET from Intrinsyc and JNBridgePro from JNBridge, Inc. later in this chapter. Before you learn about runtime bridges, you need to have a solid understanding of .NET Remoting.
Understanding .NET Remoting
At its fundamental level, .NET Remoting allows two processes within the same or different application domains to communicate with each other in a client-server relationship. In this basic scenario, the server component is a remotable object.
.NET Remoting implements interprocess communication by separating the remotable object from a specific client, server application domain, or particular communication mechanism. As a result, .NET Remoting is flexible and easily customizable.
This abstraction works through the use of two main concepts:
- Channels Channels provide the transport between remote components. The default channels are TCP and HTTP.
- Formatters Formatters convert (serialize) objects into a common format the other process (or, in the case of interoperability, platform) can understand. The default formatters are binary and SOAP.
Note Later sections in this chapter discuss SOAP.
In Chapter 3, "Interoperability Fundamentals," you learned about binary serialization and XML serialization. The binary formatter performs binary serialization on data objects; the SOAP formatter performs XML serialization on data objects. However, the SOAP formatter wraps the serialized XML document with extra SOAP-related XML tags.
By specifying a channel and a formatter, you can define how you establish communications between a remotable object and its client. The channels specify the communication protocol. The formatters then act as serializers, serializing and de-serializing the data objects that pass between the remotable object and the client. The ability to customize these channels and formatters is what allows you to use .NET Remoting for connectivity between .NET Framework applications and Java applications.
.NET Remoting provides more than just communication between processes; you can also use it for links between two or more application components that are in different application domains. To do this, just change the configuration of .NET Remoting to exchange data between the separate application domains. This gives you flexibility to build an application that runs on just one computer but that you can then extend to run in a distributed environment with minimal adjustment to the code.
.NET Remoting also supports two ways for passing data between application components. These are:
- Pass by value (PBV)
- Pass by reference (PBR)
Pass by value involves returning of the data from a remote system call to the client. Pass by reference returns a pointer or reference to the data and the remote server maintains the data's state.
Each method has advantages and disadvantages. The method you choose depends on the type of application you are developing, the data that you want to pass, and the network environment the application must function in.
Passing by reference can offer performance benefits when exchanging large data objects or with distributed systems where network latency slows down pass by value communication. However, if you pass a data object by reference, this makes a remote call to the referenced data object on the server each time the client accesses another field on the object.
For example, if you pass a CustomerData object, named custData, to a client by reference, each time the client accesses a field, such as custData.Name or custData.Address, this makes a remote call to the server. This can result a tightly coupled and chatty application.
Note In service oriented applications, loose coupling between application components is more desirable, and you should use pass by value.
Implementing .NET Remoting
A typical .NET Remoting implementation, in which two components communicate directly, consists of the following items:
- A remotable application object or server component.
- A host application that listens for client requests to the remotable application component.
- A client application component that makes requests to the remotable application component.
Figure 4.1 shows an example of a .NET Remoting framework connection between a client and server.
.gif)
Figure 4.1: A typical .NET Remoting implementation
Implementing .NET Remoting involves the following phases:
- Determining the host application or environment.
- Creating the server component.
- Creating the client.
- Editing the configuration files.
The following sections provide an overview of the steps necessary to implement .NET Remoting. For more information about .NET Remoting, see the References section at the end of this chapter. For coding examples in the XBikes sample application, see Chapters 7 to 9.
Determining the Host Application or Environment
.NET Remoting server components require hosting in an application domain that can listen for incoming requests for that object. You have four choices for hosting a remoting server component:
- ASP.NET on IIS
- Component Services (COM+)
- A Windows system service
- A Windows application (console or Windows forms based)
You can host .NET Remoting objects as ASP.NET components running on IIS. This brings many advantages, including built-in support for security and easy scalability. With this configuration, you can use either the binary or SOAP formatter but you can only use the HTTP channel, which is slower than TCP.
You can host a remoting object in Component Services as a COM+ Serviced Component on either Windows XP Professional SP1 or Windows Server 2003. This configuration provides the enterprise features of Component Services such as integrated security, transactions, pooling, and activation.
You can host remoting objects in any managed Windows service. Hosting a remoting object in a Windows service provides the flexibility to use any channel or formatter configuration you choose, including the highest performing combination of binary over TCP. However, .NET Remoting does not have a built-in security model. Hence if you host a remotable object in a Windows service, you need to build your own authentication and authorization mechanisms.
Finally, you can host a remoting server component in a Windows application. However, applications run in the context of the logged on user, and therefore require user logon to execute. They also run in the security context of that user, which might not be appropriate for your environment. It is preferable to host the remote server component in a Windows service.
Note When hosting a component in a Windows Forms application, a Windows Service or some other application type, it is up to the programmer to specify the port. For non-ASP.NET hosts, remoting can listen on any unused port.
In general, you should use IIS to host your remoting objects because of the security and performance advantages it provides. For more information about hosting a remotable object in IIS, see the References section at the end of this chapter. For examples of using Ja.NET in conjunction with .NET Remoting in the XBikes sample application, see Chapters 7 and 8.
Creating the Server Component
The server component is the service provider, providing methods that client applications call by reference or data that clients send and receive by value. Server component classes need to inherit from the MarshalByRefObject class to communicate over .NET Remoting. Any data that the server component passes by value must be serializable.
Creating the Client Component
To enable .NET Remoting on the client, you do not need to implement any additional interfaces. However, the client must have a reference to the server component or interface. The client uses this reference to interrogate the server component for any methods or data types that the server component exposes. The client also needs to load the remoting configuration, either from its own code or from a configuration file.
Editing the Configuration Files
The following .NET Remoting items are configurable:
- References to remote systems
- Channels
- Formatters
You can configure each of these items through settings that you can either store in the application code or access them at run time from a configuration file. It is recommended that you store your configuration settings in a configuration file so that you can change them without having to recompile the application. This method is much more flexible in production systems, allowing you to implement changes without recompiling and redeploying the application.
Both the server component and the client component in a .NET Remoting scenario must have access to configuration information. Assuming you have stored the configuration settings a file, the contents and locations of these files differ for the server and client.
.NET Remoting configuration files are XML formatted text files. You can edit these in Notepad or the text editor of your choice.
Server Component Configuration
On the server side, you must register all remote objects with the .NET Remoting environment before clients can access them. During this registration process, you must provide the .NET Remoting framework with all the information required to activate and manage the lifetime of the object. The most important pieces of information required for registration are:
- Object type
- Object location (URL)
- Activation requirements for managing the object lifetime
- Channels for connecting to the object
The location of the remoting configuration file for the server depends on the host application you use. For example:
- For IIS-hosted applications, you store the remoting configuration in the Web.config file located in the application virtual root.
- For Component Services hosted applications, the remoting configuration would be in a file that you create named Dllhost.exe.config file in the \System32 directory. This is because the server component runs as part of the COM+ process, Dllhost.exe.
- For a Windows service, the remoting configuration information is in the application configuration file of the Windows service. For example, if the Windows service is named Myservice.exe, the remoting configuration is in the file Myservice.exe.config.
Client Component Configuration
The client side must also have the same configuration settings loaded as the server. You store client configuration settings in a file that you create named, for example, Remoting.config. The client application loads this file by calling RemotingConfiguration.Configure with the configuration file name as a parameter. The location of the Remoting.config file depends on the type of application the client component belongs to. For example:
- For ASP.NET-based clients, the Remoting.config file lives in the application's virtual root. These configuration settings must load in the Application_Start method of the Global.asax file.
- For COM+ Serviced Components clients, the Remoting.config file lives in the \system32 directory.
- With any other client, the Remoting.config file should be in the same directory as the client executable file.
Now that you understand the basics of .NET Remoting, the next section looks at how you can use this technology to connect to Java applications.
Implementing Runtime Bridges
There are several vendors that enable interoperability between .NET Framework applications and Java applications with .NET Remoting as the underlying connecting protocol. Runtime bridges expose Java objects and methods in a way that enables you to address them with .NET Remoting and vice versa. Two of the main products in this category are Ja.NET from Intrinsyc and JNBridgePro from JNBridge, Inc.
Note Ja.NET and JNBridgePro differ in that JNBridgePro allows calls from a .NET Remoting client to Java objects and classes whereas Ja.NET also works in the opposite direction. This difference does not affect the scenarios that this book covers.
Evaluating Ja.NET
Ja.NET provides a two-way implementation of the .NET Remoting stack for Java. Using Ja.NET, you can generate Java proxies that expose or consume components using the .NET Remoting protocol.
Because Ja.NET is a bi-directional bridge, accessing Java from .NET generates a set of C# proxies. Similarly, accessing .NET from Java generates a set of Java proxies.
If you examine the generated proxies, you should notice how the by value class contains all its fields, and the remote by reference class only a shell that defines the class definitions. Ja.NET needs these for compile definitions, and then again at run time for the _TransparentProxy class to mimic the remote server. If you attempt to create a local copy of this class, this generates an exception. You can only have a remote instance of this class. The proxies use no custom code, just pure .NET Remoting.
If you look at the Java proxies generated when analyzing a .NET assembly, you should see a lot of code for marshalling and un-marshalling the call parameters to the Ja.NET runtime. When accessing .NET from Java, you need custom code to initialize the Ja.NET runtime, as well as any remote send or receive classes. However, the .NET side still does not require any special code, as Ja.NET follows the .NET rules for remotable objects.
Ja.NET enables Java components to appear as CLR components, and CLR components appear as Java components. In addition, the Ja.NET Janetor tool expands upon this functionality by generating the Java proxies within a WAR file. You can then host this WAR file on a Web server, enabling access to EJBs from .NET Framework again with all of the communication based on .NET Remoting.
Accessing a .NET Framework Server from Java
The simplest implementation is when the Ja.NET runtime lets a Java client access a .NET Framework server, in this case, implemented in Visual Basic .NET. Figure 4.2 shows how to do this.
.gif)
Figure 4.2: Connecting Ja.NET to a VB.NET Server component
Figure 4.2 shows the Java platform hosting the Ja.NET runtime component.
Accessing IIS Components from Java
Java clients can also use the Ja.NET runtime to access a remote CLR component as if it is a local Java component. Figure 4.3 illustrates this method.
.gif)
Figure 4.3: Connecting Ja.NET to a .NET component hosted on IIS
Figure 4.3 shows the Ja.NET proxies that handle communication between the Java client and the Ja.NET runtime. In this example, IIS is hosting the .NET Framework application.
Accessing an EJB from .NET Framework
The third method deploys a WAR file containing the Ja.NET runtime onto any Web server that supports servlets. The CLR client (written in any supported .NET Framework language) can access the EJBs as if accessing local CLR components. Figure 4.4 shows an example of this arrangement.
.gif)
Figure 4.4: Connecting .NET Clients to an EJB using Ja.NET
In addition, the Ja.NET runtime lets you:
- Write clients for EJBs in any language supported by .NET.
- Access .NET Framework components from any Java object or EJB.
- Reuse components from either platform with the other environment.
Note Because .NET Remoting is an extensible protocol from both the transport and data formatting perspective, Ja.NET supports HTTP and TCP/IP transport protocols together with SOAP and binary data formatting and can support future transports and formatters.
Ja.NET Toolset
There are six main parts that make up the Ja.NET toolset. These are:
- GenService The GenJava and GenNet tools use GenService to provide access to .NET Framework assemblies for development. You require only GenService to generate the proxies, so you do not have to install it in the production environment.
- GenNet GenNet generates the .NET Framework proxies that access the Java classes through the Ja.NET runtime.
- GenJava GetJava generates Java proxies that access .NET Framework assemblies through the Ja.NET runtime.
- Janetor The Janetor tool allows you to view and modify the Ja.NET runtime configuration settings. You can also use the Janetor to generate WAR files to assist with deploying the Ja.NET runtime onto a Web server. Janetor includes licensing for the Ja.NET product, locally shared and remotely accessed objects.
- Ja.NET TCP server Ja.NET TCP server provides standalone hosting for Java classes through the Ja.NET runtime where the classes are not hosted on a J2EE server. The Ja.NET runtime includes this component.
- Ja.NET runtime Ja.NET runtime is the main collection of classes that hosts the tools. The Janet.jar file contains the runtime components.
Linking Types between .NET Framework and Java
When linking .NET Framework to Java using Ja.NET, you need to understand the links between data types in the .NET Framework and data types in Java. Table 4.1 shows this information.
Table 4.1: .NET Framework to Java data type mappings
| .NET Framework Data Type | Java Data Type |
| System.Boolean | boolean |
| System.Char | char |
| System.String | java.lang.String |
| System.Single | float |
| System.Double | double |
| System.Int8 | byte |
| System.Int16 | short |
| System.Int32 | int |
| System.Int64 | long |
| System.Byte | byte |
| System.UInt16 | short |
| System.UInt32 | int |
| System.UInt64 | Long |
| System.Object | java.lang.Object |
| System.DateTime | Java.util.Date |
Table 4.2 shows how you can use Ja.NET to map collections between Java and the .NET Framework.
Table 4.2: Ja.NET Collection Mappings between Java and the .NET Framework
| Java Collection Class | .NET Framework Collection Class |
| java.util.ArrayList | System.Collections.IList |
| Java.util.LinkedList | System.Collections.IList |
| Java.util.Vector | System.Collections.IList |
Table 4.3 shows the opposite mapping from the .NET Framework to Java.
Table 4.3: Ja.NET Collection Mappings between the .NET Framework and Java
| .NET Framework Collection Class | Java Collection Class |
| System.Collections.ArrayList | java.util.List |
For more information about type and collection mappings, see the Ja.NET documentation.
Understanding Ja.NET Events and Exceptions
There are a few more concepts that you need to understand to appreciate the complete range of .NET Remoting options. These include the following:
- Events Ja.NET provides event support through the ability to extend java.util.EventListener to system events in the .NET Framework. This provides a major advantage in that the server component can now implement a callback to the client through this event model. Events are particularly useful where you want to implement asynchronous operations or transactions with long run times.
- Exception handling Ja.NET provides exception handling facilities, reporting back exceptions on one platform to the alternative platform. Java server exceptions map back to the System.Runtime.Remoting.RemotingException function in .NET Framework and exceptions on .NET Framework map back to com.instrinsyc.janet.RemoteException.
Usually, these derived exceptions contain the text from the original. To deal with these exceptions, trap the resultant exception and then search the text within the embedded exception to obtain more information.
- Support for strong naming Ja.NET supports the use and creation of strong-named assemblies. You can then register these assemblies in the global assembly cache for use with serviced components (COM+).
- Ease of configuration Because Ja.NET is a pure Java implementation of the .NET Remoting protocol, the .NET Framework side requires no special runtime libraries. Configuration on the .NET Framework side is the same as with a normal implementation of .NET Remoting, requiring only a simple DLL that contains class and interface definitions. Anything that you can make remotable in the .NET Framework (derived from MarshallByRefObject), you can also make remotable in Ja.NET. You can also send serialized classes by value, as in .NET Framework-only implementation.
Implementing Ja.NET Best Practices
There are several best practices that you should implement when using Ja.NET. These issues include performance, design, and deployment factors. For example:
- Upgrade to version 1.5.
- Use binary protocol for .NET Remoting.
- Deploy WAR packages on the application server to access EJBs and JMS.
- Understand .NET Remoting to facilitate good design practice.
- Comprehend the differences between pass by reference (PBR) and pass by value (PBV).
Upgrade to Version 1.5
You are strongly recommended to upgrade to Ja.NET version 1.5, which is free for users of earlier versions of Ja.NET. Version 1.5 contains many important new features, including some that are necessary to run the examples in this book. Some of the new features include the following:
- Support for strong-named assemblies.
- Improved type mappings between .NET Framework and Java types.
- Significant performance increases.
- Improved serialization capabilities for pass by value classes for both platforms.
- Integral Web server for non-enterprise level remoting access with HTTP.
- Improved SDK.
- Runtime support for .NET Framework versions 1.0 and 1.1.
- Integral .NET Framework proxy for JMS.
- Stability and performance enhancements.
Use Binary Protocol for .NET Remoting
This chapter describes the benefits of using .NET Remoting rather than SOAP. Although Ja.NET also supports SOAP connections, .NET Remoting provides better performance, with TCP/binary providing the fastest connection. However, if you need to traverse firewalls, want to use the security infrastructure of IIS, or easily deploy components inside an application server, HTTP/binary is the preferred protocol.
Note HTTP/binary is still significantly faster than HTTP/SOAP.
Deploy WAR Packages on the Application Server to Access EJBs and JMS
The fastest way to access an EJB is from within the application server itself. The easiest deployment scenario is to create a WAR file that contains the Ja.NET runtime JAR, the EJB client JARs, and a configuration file. You can use the Ja.NET Janetor tool to create the WAR file easily, which you can then immediately deploy to the application server. Because the WAR file resides in the same process space as the application, access to the EJBs is much faster than accessing it from an external process with RMI.
Understand .NET Remoting to Facilitate Good Design Practice
Because Ja.NET is a pure Java implementation of the .NET Remoting protocol, the same rules for .NET Remoting best practice apply to Ja.NET. Make sure you read the current literature about .NET Remoting to understand how best to employ it in conjunction with Ja.NET.
Comprehend the Differences between PBR and PBV
In a PBR class, every method call results in a request for data. However, if you send a PBV class, this serializes the entire class, including fields of the super class or classes. If you PBV a very large object with numerous fields that contain significant amounts of data, this may generate a sizeable about of network traffic. In this case, it may be better to use PBR. Similarly, if you have a small class, consider using PBV to send a copy of the class, rather than making a call to the network to access each field. Understanding the differences between PBR and PBV reduces network traffic and improves performance.
Evaluating JNBridgePro
JNBridgePro is a point-to-point bridging solution that links Java components to .NET Framework. The Java code runs in an ordinary Java Virtual Machine (JVM) or J2EE application server and the .NET Framework code runs in a normal .NET Framework CLR. JNBridgePro then manages the communication between the two sides.
Proxies make Java classes and objects appear as ordinary .NET Framework classes and objects. .NET Framework components interact with those proxies just like normal local .NET Framework function calls, but the proxy objects transparently redirect the calls to the Java side. The Java components process the method calls and field accesses and return the values or data to the proxies. The proxies then present the results back to the .NET Framework components.
An application using JNBridgePro to perform Java/.NET Framework interoperation contains JNBridgePro's .NET Framework-side and Java-side runtime components, which manage inter-platform communication and object lifecycles, and a .NET Framework assembly (a DLL) containing the proxies for the Java classes exposed to the .NET Framework. Developers generate the proxies using the JNBridgePro toolkit.
Figure 4.5 shows the architecture of JNBridgePro.
.gif)
Figure 4.5: Internal architecture of JNBridgePro Runtime Bridge
Figure 4.5 shows the runtime component and proxies on the .NET Framework side. Compare this with Figure 4.3.
Integrating JNBridgePro with .NET Remoting
JNBridgePro employs .NET Remoting to implement the communication between the .NET Framework and Java sides. Because .NET Remoting is an extensible architecture, you can change communications channels as required. JNBridgePro uses this extensible architecture to support both SOAP and binary communications.
.NET Remoting also includes concepts alien to conventional "local" object-oriented development, such as leasing, well-known objects, and client-activated and server-activated objects. JNBridgePro can encapsulate these concepts and conceal them from the user. Hence JNBridgePro interoperation between Java and .NET Framework code appears to the developer as local development.
JNBridgePro builds additional capabilities on top of .NET Remoting. For example, basic .NET Remoting can access members of actual objects, but it cannot access static members of classes that are not members of actual instances of the class. JNBridgePro provides the ability to access those static class members.
Understanding JNBridgePro Features
JNBridgePro allows access to Java classes and objects through calls to the corresponding JNBridgePro proxies. JNBridgePro supports access to both static and instance members, in addition to supporting access requests to fields and calls to methods. You can make explicit calls from .NET Framework to Java by having the .NET Framework code call .NET Framework proxies for Java classes and objects, and you can make implicit calls from Java to .NET Framework by having the .NET Framework code register a callback object and having the Java code access the callback object through its implemented listener interface.
The Java side components can reside in a standalone JVM or in a J2EE application server. Communication between the .NET Framework and Java sides can use either SOAP or the faster binary protocol.
JNBridgePro supports transactions, giving you the ability to make a sequence of calls from .NET Framework to Java as part of the same transaction. If the transaction fails, the entire sequence rolls back to the start point. This prevents application calls from hanging between the .NET Framework and the Java side. JNBridgePro can also create .NET Framework proxies for dynamically generated Java classes at execution time. Such dynamically generated classes frequently appear in J2EE applications, particularly when linking to JNDI and EJB components.
JNBridgePro also supports the following:
- Mapping between .NET Framework and Java primitives.
- Strings.
- Collections.
- Support for pass by value (PBV) and pass by reference (PBR).
- Connections to Java-based messaging servers.
Selecting JNBridgePro
Choose JNBridgePro for J2EE and .NET Framework interoperability if your application requires synchronous, point-to-point communication between .NET Framework and Java objects, and has one or more of the following requirements:
- High performance Your application requires a high performance interoperability mechanism with a very low overhead, where the Java platform and the .NET Framework are located on the same local area network or intranet, or on the same machine.
- Expose a rich object-oriented Java API to .NET Framework interface Your application requires that Java exposes a large number of Java class APIs to .NET Framework applications, or the Java API returns custom Java objects or requires custom Java objects as parameters.
- "Chatty" interaction Your application performs frequent fine-grained calls between Java and the .NET Framework. Web services work better with less frequent and more coarse-grained "chunky" interaction.
- Desire to stay with "local," object-oriented development model Your application architects decide that they will not implement a service-oriented model that exposes the APIs of a few classes as services. Instead, they want the .NET Framework code to construct new Java objects using the new operator, employ cross-platform garbage collection, and provide a conventional "local" object-oriented model.
Implementing JNBridgePro Best Practices
There are a number of best practices that you should implement with JNBridgePro, regardless of the interoperability scenario. Performance-related best practices include increasing the speed of the communications channel, or reducing the number of inter-platform round trips, thereby improving the apparent execution speed of the application.
Upgrade to Version 1.3
If you are using JNBridgePro version 1.2 or earlier, you should consider upgrading to version 1.3, particularly if your .NET Framework and Java components reside on different computers. Version 1.3 or later provides a significant performance enhancement when using binary communications to connect over a network. Some implementations demonstrate a reduction in the time to access an EJB from 200 milliseconds to 2.3 milliseconds.
In addition to the network communications performance improvement, version 1.3 supports value objects and directly mapped collections, both of which can improve performance.
To take advantage of this improvement, download and install version 1.3, and then regenerate your proxies using the version 1.3 proxy generation tool. Replace the old copies of Jnbshare.dll and Jnbcore.jar in your application with the version 1.3 files.
Use the Binary Communications Protocol
Binary/TCP communication is over an order of magnitude faster than SOAP/HTTP. Use SOAP/HTTP only when using the Internet to link the .NET Framework and Java sides and the communication path traverses firewalls.
To use the binary/TCP communications channel, make sure that the setting in the Jnbproxy.config remoting configuration file uses the JTCP: protocol instead of the HTTP: protocol. Also, set the servertype property in the Java-side configuration file Jnbcore.properties to TCP, not HTTP.
Place the Java-side Component inside the J2EE Application Server
If you are using JNBridgePro to access EJBs running inside a J2EE application server, deploy the JNBridgePro Java side inside the application server. These components comprise the WAR file containing Jnbcore.jar, the JAR files containing the EJB stubs, and the associated configuration files. Figure 4.6 shows this in place.
.gif)
Figure 4.6: Java-side component in J2EE application server
This arrangement ensures that Jnbcore.jar, which performs the EJB calls, bypasses RMI and makes direct calls to the EJBs.
Place Java-side and .NET Framework-side Components on the Same Computer
If a single .NET Framework client accesses the Java classes, place the Java-side component, including the Java classes, on the same computer as the .NET Framework-side component, if possible. This minimizes the communication overhead. Figure 4.7 shows this in operation.
.gif)
Figure 4.7: Java-side component on the computer running the .NET Framework component
Any increase in round trip time and latency for the communication link affects the overall responsiveness of the platform interface.
Reduce Round Trips
One of the best ways to improve JNBridgePro performance is to reduce the number of round trips from the .NET Framework side to the Java side and back by reducing the number of calls to proxies. One example of how to do this is when a number of proxy calls are necessary to obtain information from which another value is calculated. To reduce the number of proxy calls, create a Java facade class that performs the calls, does the calculation, and returns the value. Then, create a proxy for this class. The value can now be obtained through a single proxy call.
Implement Return Arrays
JNBridgePro offers full access to Java APIs, so there is a great temptation to use the full API functionality. For example, if you have a Java-side Vector object, you should extract an array from the vector and return that array by value. .NET Framework then represents that array natively, removing the need for iterations to extract further values from the original Vector object.
Some Java APIs support stateful objects that you may want to call repeatedly to obtain additional information. The JDBC class ResultSet, for example, represents the results of a query and can contain multiple rows through which you have to scroll. Again, this can result in multiple round trip calls to ResultSet.
To improve performance, create a Java wrapper class that returns an array of objects with each containing one row of results. If there is a chance that the results array is very large, and that returning its entire contents will take a long time, modify the wrapper class to return a limited number of results at a time (for example, no more than 50).
Use Value Objects
The default setting for object calls from .NET Framework to Java are as pass by reference (PBR) results. The called object remains on the Java side, and only the reference to that object returns to .NET Framework. References are much smaller than the actual object, helping performance, but they involve a trip back to the Java side to extract any useful information. Even getting a field value requires a round trip to obtain the data. If you are performing multiple queries on an the object's fields for data or using accessor methods to look up data on an EJB, you would be better to designate objects of that class as value objects.
A value object is a snapshot of an object from the Java side then copied back to the .NET Framework side. Depending on the kind of value object it is, this copies either the values of its public fields, or in the case of a Java Bean value object, the values of its accessor (get) methods. This process does not copy the object's methods other than get methods for a Java Bean value object, because it is problematic to translate the meanings of Java methods to .NET Framework automatically.
Consider using value objects when the object is really just a large package of data that you want to access in many different ways. For example, an object representing a customer's bank account might have fields for the customer's account number, first name, last name, address, current balance, previous balances, and the date the owner opened the account.
The default setting is that the account object userAcct passes by reference, resulting in each field access in userAcct generating a round trip. However, if you set up Account to pass by value, this copies the data in userAcct from the Java side to the .NET Framework side and each subsequent field access is a local call.
Whether it is advisable to pass an object by value or by reference depends on the size of the object and how much of its data you want to access. For example, in the bank account example, if the only data you access in the account is the current balance, it is probably not worthwhile to pass this object by value. In this case, the time taken to copy all the data to the .NET Framework side outweighs the time savings that result by making all field accesses local to .NET Framework.
The code is the same regardless of whether the object is passed by reference or by value; the only difference is whether the object's class is designated as a value object or a reference object. Ideally, the decision on whether to pass the object by value or by reference depends on observed measurements within the pilot environment rather than the developer's judgment.
Note Individual objects cannot be designated as pass by reference or pass by value; all objects of a given class have the designation.
For more information about value objects and reference objects in JNBridgePro, see the JNBridgePro Users' Guide.
Use Directly Mapped Collections
Directly mapped collections return certain object collections from the Java side and automatically convert them to native .NET Framework collections on the Java side. You can then access these elements quickly after conversion without a round trip.
JNBridgePro supports a variety of directly mapped collections. Java Vectors, array lists, linked lists, and hash sets map directly to .NET Framework array lists. Java hash tables and hash maps map to .NET Framework hash tables. You can also use directly mapped collections to pass parameters from .NET Framework to Java. For more information, see the JNBridge Users' Guide.
As with value objects, directly mapped collections take longer to pass between Java and .NET Framework than reference objects, but you can then access their elements faster. Deciding whether to use a directly mapped collection depends on the size of the collections being transferred, the number and frequency of accesses, and tests in the pilot environment.
Each exposed class results in the generation of a proxy of the same name. The generated proxy's members (including constructors, methods, and fields) correspond to the members of the Java class underlying the proxy.
Generate All Supporting Proxies
When generating proxies, generate all the supporting proxies for each specifically requested proxy class. It is often possible to omit generating supporting proxies (such as proxies for the classes of all parameters, return values, thrown exceptions, implemented interfaces, and superclasses); however, it is never harmful to generate such supporting classes and it may be harmful to leave them out. In addition, creating proxies for supporting classes ensures that you can call methods and access fields requiring proxies for those additional classes without having to regenerate the proxy assemblies.
Note An additional problem with not generating all supporting proxies is that in some situations, applications throw an exception if you do not do so.
Depending on the side of the original set of seed proxies, generating all supporting proxies adds about 200300 additional proxy classes to the original set. Typically this takes no more than five minutes to generate the additional proxies.
With care, it is possible, in many cases, to avoid generating supporting classes. However, it is never harmful to generate such classes, and doing so may avoid various issues in the future, even when the lack of supporting classes does not represent a problem now.
Connecting with Web Services
In the previous section, you saw how you can use .NET Remoting to connect the Java platform and .NET Framework with runtime bridges. However, .NET Remoting is closely linked to the .NET Framework and you may need an interoperability solution that is platform neutral.
There is currently a lot of interest in the computer industry around Web services, and Web services offer you additional choices as part of an interoperability solution. It is worth looking at what Web services are and what they offer.
A high-level definition of a Web service would be a programmable application component accessible through standard Internet protocols. Many more detailed definitions of Web services exist, and they all seem to contain the following elements in the description:
- Web services expose useful functionality through standard Internet protocols. In most cases, this protocol is SOAP over HTTP.
- Web services describe their interfaces in enough detail to allow a user to build a client application to talk to them. An XML document named a Web Services Description Language (WSDL) document contains this description.
- Users can search for available Web services in some form of registration database. Universal Description, Discovery and Integration (UDDI) is the most common way to implement this.
Because Web services are standards-based and platform independent, they provide a natural fit when it comes to getting applications in different platforms to interoperate with each other. This partially explains the alacrity with which so many vendors have endorsed the Web services standards. From this book's perspective, Web services can provide a useful mechanism for connecting the .NET Framework and J2EE. Specifically, Web services address three main interoperability issues:
- Protocol standards HTTP and HTTPS are the most common implementations, but Web services have the flexibility to use any transport protocol.
- Type definitions Web services always expose strongly typed data, so if a Web service exposes a type, another Web service can understand and consume that type regardless of the underlying language or platform.
- Multiple levels of support The ability to implement Web services in any language on any platform and using any vendor's toolkit, hence a consumer does not need to be aware of the platform that a particular service runs on.
Both .NET Framework and Java offer implementations of Web services, with varying degrees of integration into the underlying platform. In fact, one of the central tenets of the .NET Framework is its high degree of integration with Web services. Web services are well-suited to providing a wide variety of services over the Internet, and they are a promising technology for enterprise application integration.
However, while Web services provide a very powerful technology, they are not suitable for all applications and interoperability scenarios. Because SOAP is text-based, Web service calls may be too slow for applications that require frequent, fast, and fine-grained communications.
Service-oriented interfaces such as Web services are also unsuited for conventional object-oriented models. Although you can think of a service as a single persistent server activated object, client-activated objects such as ones that the new operator constructs, and access requests to static methods are not generally supported. Similarly, if your application needs to access a wide variety of objects and classes, a Web service is not generally suitable. Again, if you need to link to a rich object-oriented set of Java APIs from .NET Framework, Web services are probably not the solution.
In addition to the preceding issues, Web services do not support callbacks in the same manner as local object-oriented architectures. Finally, there may be problems returning rich custom Java objects to .NET Framework through a Web service. In such cases, look at alternatives to Web services such as JNBridgePro and Ja.NET.
Understanding Web Services
In a typical Web services scenario, a client application can learn about what functionality a Web service provides and how to call this functionality by querying the service's WSDL file. Next, the client sends a request to the service at its given URL using the SOAP protocol over HTTP. The service receives the request, processes it, and returns a response. The request and the response are XML formatted using the SOAP protocol.
It is worth examining the protocols and specifications (or stack) that make Web services possible. The Web services stack consists of five layers, as Figure 4.8 illustrates.
.gif)
Figure 4.8: The five-layer model of the Web services stack
These layers consist of the following elements:
- Transport (HTTP)
- Encoding (XML)
- Standard structure (SOAP)
- Description (WSDL)
- Discovery (UDDI)
The next sections describe each of these elements.
Transport (HTTP)
At the lowest level, two components in a distributed architecture must agree on a common transport mechanism. Because of the near universal acceptance of port 80 as a less risky route through a firewall, HTTP became the standard for the transport layer. However, Web services implementations can run on other transport protocols such as FTP and SMTP, or even other network stacks, such as Sequenced Packet Exchange (SPX) or non-routable protocols such as NetBEUI. Changing from the dependence on HTTP or HTTPS (for encrypted connections) is possible within the bounds of the current specification.
Encoding (XML)
After agreeing on the transport, components must deliver messages as correctly formatted XML documents. This XML dependence ensures the success of the transfer, because both provider and consumer know to parse and interpret the XML standard.
Standard Structure (SOAP)
Although XML defines message encoding, it does not cover the structure and format of the document itself. To guarantee interoperability, both provider and consumer must know what to send and what to expect. SOAP is a lightweight, message-based protocol built on XML (XSD version 2) and standard Internet protocols, such as HTTP and SMTP. The SOAP protocol specification defines an XML structure for messages (the SOAP envelope), data type definitions, and a set of conventions that implement remote procedure calls and the format of any returned data (the SOAP body).
Description (WSDL)
The description layer provides a mechanism for informing interested parties of the particular bill of fare that a Web service offers. Web Services Description Language (WSDL) provides this contract, setting out for each exposed component:
- Component name
- Data types
- Methods
- Parameters
This WDSL description enables a developer for a remote component to query your Web service and find out what the service can do and how to get it to do it. The WSDL file is an XSD-based XML document that defines the details of your Web service. It also stores your Web service contract. The WSDL file is usually the first point of entry for any client attaching to your Web service so that the client knows how to use it.
Discovery (UDDI)
Discovery attempts to answer the question "Where." If you want to connect to a Web service at an Internet location (for example, www.nwtraders.msft/services/WeatherService.aspx), you can enter the URL manually. However, URLs are somewhat unwieldy and not very user friendly, so it would be better if you could just request the NWTraders Weather Web Service. To do this, NWTraders could publish their weather service on a Universal Description, Discovery and Integration (UDDI) server. Finding their weather service is now just a question of connecting to the UDDI server using an agreed message format to locate the URL for the service.
Figure 4.9 shows the how the basic architectural elements of a typical Web service work together.
.gif)
Figure 4.9: Typical architectural elements from a Web service
Now that you understand the individual parts of a Web service, it is easier to create a more precise definition. Hence a Web service is an application component that does the following:
- Communicates using open protocols (such as HTTP and SMTP).
- Processes SOAP framed XML messages.
- Describes its messages through the XML Schema.
- Uses WSDL to provide a service description.
- Enables discovery through UDDI.
Web Services Interoperability Organization
The protocols Web services depend on are platform independent. This suggests that interoperability between Web services on different application platforms should be automatic. Unfortunately, this is not necessarily the case.
While most of these protocols are generally accepted specifications, many of the Web services draft standards have not received full ratification from any of the common Web standards bodies, such as the World Wide Web Consortium (W3C) or Organization for the Advancement of Structured Information Standards (OASIS). Not surprisingly, many vendors have their own implementations of these specifications. As a result, interoperability between different vendors' Web services is not guaranteed.
Because many vendors were so enthusiastic about Web services, it became imperative to start an independent organization dedicated to maintaining standards and providing direction. Without this body, it would be impossible to ensure that Web services implementations were truly interoperable. From this requirement arose the Web Services Interoperability Organization (WS-I). The initial membership was 170, consisting of vendors, enterprise customers, system integrators and independents all working together to define the implementation of Web services.
Any organization or individual who wants to contribute to supporting and furthering the cause of Web services interoperability can join the WS-I. The WS-I targets developers and provides a framework and guidelines for the following areas:
- Profiles These are specifications that define technology standards.
- Samples These highlight interoperability concepts and demonstrate the features of the profiles.
- Implementation guidelines These show a best practices approach to design solutions that require interoperability with Web services.
- Tools These include a sniffer and analyzer to monitor and log interactions with Web services, including identifying errors and warnings for implementations that do not meet the profile guidelines.
For more information about the WS-I, see the Web Services Interoperability Organization Web site (http://www.ws-i.org/).
Implementing the Web Services Basic Profile
The most important publication to date from the WS-I is the Basic Profile 1.0. This profile provides a group of named Web services specifications, together with a series of recommendations for implementing each standard. Basic Profile 1.0 covers four areas:
- Messaging (HTTP, XML 1.0, XSD 1.0, SOAP 1.1)
- Description (WSDL 1.1)
- Discovery (UDDI 2.0)
- Security (HTTPS)
Note WS-I does not control the individual specifications within Basic Profile 1.0, so it acts as a unifying intermediary for Web services. The XBikes sample application does not fully support the WS-I Basic Profile 1.0.
Implementing Web Services
Implementing Web services in .NET Framework and on the J2EE platform are different processes, due to the levels of support that each provides. Because .NET Framework includes built-in support for Web services, you do not require any additional components. Visual Studio .NET lets you create Web services implementations from a project template. With J2EE, you currently need to add a third-party Web services implementation.
Whether you implement your Web service in .NET Framework or in Java, there are certain common architectural elements, as Figure 4.9 shows.
There are two main stages to implementing Web services:
- Creating the Web service.
- Creating the Web service client.
The following two sections look at how you do this on the two platforms.
Creating Web Services in .NET Framework
Web services are tightly integrated into the .NET Framework. This makes it very easy to use the Visual Studio .NET IDE to design and create a Web service in .NET Framework. The .NET Web services implementation uses the same page framework as ASP.NET, consisting of the following:
- An addressable Web service entry point (.asmx file).
- The code that implements the Web service's functionality (typically kept in a .asmx.cs code-behind file).
To create Web services using Visual Studio .NET, your developer workstation needs access to a Web server configured for ASP.NET applications. If your server is running a version of Windows Server 2003, you must install IIS from the Application Server options and include support for ASP.NET applications.
Note The Windows Server 2003 family does not include IIS in a default installation. This is a change from Windows 2000.
Visual Studio .NET lets you create an ASP.NET Web service project in any of the supported Visual Studio languages using the Web service project templates. After you create the Web service project in Visual Studio, the Component Designer appears. The Component Designer is the design surface for your Web service. You can use the Design view to add components to your Web service, and the Code view to view and edit the associated code.
When you create an ASP.NET Web service project in Visual Studio, it constructs a Web application project structure on the Web server and a Visual Studio solution file on your local computer. The solution file (.sln) contains the configuration and build settings and keeps a list of files associated with the project. In addition, Visual Studio automatically creates the necessary files and references to support a Web service. When completed, Visual Studio displays the .asmx file in Design view.
By default, Visual Studio uses code-behind files, such as Service1.asmx.vb (for Visual Basic) or Service1.asmx.cs (for C#), when you create a Web service using one of the ASP.NET Web service project templates. The code-behind file contains the code that implements the functionality of the Web service. In this file, you implement the methods you want your Web service to expose.
Note By default, Solution Explorer hides the code-behind file. When you look at the .asmx file in Code view, you see the contents of this code-behind file. The .asmx file itself contains a processing directive, WebService, which indicates where to find the implementation of the XML Web service.
You implement the Web service's functionality the same as you would with any other class in the .NET Framework. To make a method available through the Web service, you mark the method with a [WebMethod] attribute before its public declaration. Private methods cannot serve as the entry point for a Web service, although they can be in the same class and the Web service code can call them.
When you build a Web service, ASP.NET automatically provides the infrastructure and handles the processing of Web service requests and responses, including the parsing and creation of SOAP messages. The compiled output is a .dll file in the project's Bin folder.
Chapters 7 and 8 of this book show detailed examples of how to implement Web services in the .NET Framework as part of the XBikes sample application. For additional reading on Web services, see the References section at the end of this chapter.
Exposing an Existing Class as a Web Service
A common scenario is where you want to expose the functionality of an existing .NET Framework class as a Web service so that other applications (such as Java applications) can access it. To do this, you can create a new Web service that acts as a service interface to the existing class. The new Web service should implement the same interface as the existing class, with each of its methods simply calling the methods of the existing class. This solution is known as the Service Interface pattern.
For more information about the Service Interface pattern, see the References section at the end of this chapter.
Component Services for Windows Server 2003 can use the built-in SOAP activation feature to expose a ServicedComponent through a SOAP endpoint which you can then access through a WSDL document. SOAP activation involves the automatic generation and hosting of a SOAP endpoint through IIS. This SOAP endpoint can then accept SOAP requests over HTTP.
It could be argued that because you can access this SOAP endpoint through a WSDL document, it is a Web service. Unfortunately, this may not always be the case because although you used SOAP, HTTP, and WSDL to build the endpoint, the WSDL document generated from the SOAP activation is not XSD compliant and contains .NET Remoting-specific data types.
Only clients that understand .NET Remoting can access SOAP-activated ServicedComponents. Therefore, by default, non-.NET Framework Web service clients cannot connect. To overcome this, you can do the following:
- Use a Java client with a runtime bridge installed to consume any exposed methods from the ServicedComponent's SOAP endpoint. This works because the runtime bridges understand .NET Remoting.
- Create a new Web service to accept incoming Web service requests and pass them on to the ServicedComponent as in the Service Interface pattern described earlier in this chapter.
Whichever technique you chose, you should now have a functioning Web service and can look at creating a client application.
Creating the Web Services Client
After you create your Web service, you then need to have client applications to access it. There are several ways of doing this, depending on the protocols that your Web service supports.
If your Web service supports the HTTP-GET protocol, you can access it from a Web browser. By default, Web services that you create in Visual Studio using the ASP.NET Web service project template support HTTP-GET, HTTP-POST, and HTTP-SOAP commands.
Note The WS-I Basic Profile 1.0 does not support the HTTP-GET and HTTP-POST protocols. It is recommended that you disable the use of HTTP-GET and HTTP-POST to make your Web service WS-I Basic Profile 1.0 compliant.
.NET Framework provides two Help techniques for when you do not know how to address a Web service. Calling the Web service's .asmx file directly from a browser without parameters generates a Help page, as shown in the following example.
http://localhost/WebService1/Service1.asmx
The other way to discover information about the Web service is to query its WSDL properties. You can do this by calling the Web service's .asmx file directly from a browser with "?WSDL" appended as a parameter.
http://localhost/WebService1/Service1.asmx?WSDL
These built-in Help systems can assist you both in the design and debugging phases of creating a Web services client.
Implementing a .NET Framework Web Service Client
A Web service client is any component or application that references and uses a Web service. This does not necessarily need to be a client-based application in many cases your Web service clients might be other Web applications, such as Web Forms or even other Web services.
When accessing Web services in managed code, a proxy class and the .NET Framework handle all of the infrastructure coding. The proxy class implements the interface Web service's interface and handles all communication between the Web service client and the Web service. Figure 4.10 shows the relationship of the proxy class to the Web service client and the Web service itself.
.gif)
Figure 4.10: Web service client using a proxy class to communicate with a Web service
Note You can create and manage proxy classes manually, or you can let Visual Studio .NET manage them for you through the automated Web References feature. The recommended approach is to use Web References.
To access a Web service from managed code in Visual Studio .NET
- Add a Web reference to your project for the Web service you want to access. The Web reference creates a proxy class with methods that serve as proxies for each exposed method of the Web service.
- Add the namespace for the Web reference.
- Create an instance of the proxy class, and then access the methods of that class like you access the methods of any other class.
After you build the project, you should then be able to access the referenced Web service.
Locating an XML Web Service and Adding a Web Reference
Sometimes you may be both the provider and consumer of a Web service. In this case, you probably know the location and function of the Web service. At other times, you may be accessing a Web service provided by someone else. When this occurs, you may not even know if a Web service that suits your purposes in fact exists.
To simplify the coding model, applications written in managed code use a Web reference to represent each Web service locally. You add a Web reference to your project by using the Add Web Reference dialog box. To access the Add Web Reference dialog box, right-click the Web References folder in Visual Studio .NET's Solution Explorer, and then click Add Web Reference. This dialog box makes it possible for you to browse your local server, the Microsoft UDDI Directory, and the Internet for Web services.
The Add Web Reference dialog box uses the process of Web service discovery to locate eligible Web services on Web sites that you navigate to in the dialog box. For a particular address, it interrogates the Web site using an algorithm designed to locate Discovery of Web service (DISCO) documents and ultimately, Web service description documents that adhere to the grammar of the Web Services Description Language (WSDL).
Generating a Proxy Class
After you locate a Web service for your application to access by using the Add Web Reference dialog box, clicking the Add Reference button instructs Visual Studio to download a copy of the service description to the local computer and then generate a proxy class for accessing the chosen Web service. The proxy class contains methods for calling each exposed Web service method both synchronously and asynchronously.
Note This technique works only when the computer running Visual Studio has access to the Web service.
Alternatively, you can manually generate a proxy class using the same tool (Web services Description Language Tool, WSDL.exe) that Visual Studio uses to create a proxy class when adding a Web reference. This is necessary when you cannot access the Web service from the computer that Visual Studio is installed on, such as when the Web service is located on a network that the client is unable to access until run time. To generate a proxy file manually, run WSDL.exe from the command prompt with the URL of the target Web service's WSDL file as a parameter. You then manually add the file that the tool generates to your application project.
Using the Proxy Class
The generated proxy class has its own namespace associated with it, and you must add that namespace to your client application before you can create an instance of the proxy class. As with any other class, you must first create an instance of it before you can call any of its methods. This process does not differ at all from creating an instance of any other class.
When using a proxy class that Visual Studio generated directly from the service description of a Web service, accessing a Web service in managed code is a relatively simple process. To access a Web service method, your client application invokes either the corresponding synchronous method or asynchronous methods of the proxy object. These methods do the necessary work to remote the call over the wire to call the desired Web service method. By default, the proxy class uses SOAP to access the Web service method because SOAP supports the richest set of data types of the three supported protocols (HTTP-GET, HTTP-POST, and HTTP-SOAP).
The proxy class that the Add Web Reference process generates derives from the System.Web.Service.Protocols.SoapHttpClientProtocol class, which contains several properties that you can use to control or customize the behavior of how this class accesses a Web service. For more information about the properties available in the SoapHttpClientProtocol class, see the .NET Framework SDK.
Note When you update a Web reference, Visual Studio .NET automatically generates a new proxy file. The new file overwrites the old one, removing any customization you may have added to the original proxy file. Keep a backup copy of any customized proxy files to guard against this possibility. This does not happen if you manually generate a proxy file with the WSDL.exe tool.
Referencing with Dynamic and Static URLs
A Web reference can use either a static URL or a dynamic URL. The Web Reference URL property specifies the location of the Web service. By default, this property is the URL of the Web service you selected, which is a static URL.
If you leave the URL Behavior property set to the default value of Static, a hard-coded URL sets the proxy class's URL property when you create an instance of that class. If you set the URL Behavior property of the Web reference to Dynamic, the application obtains the URL at run time from the <appSettings> section of your application's configuration file.
<appSettings>
<add key="myApplication.myServer.Service1"
value="http://myServer/myXmlWebService/Service1.asmx"/>
</appSettings>
When you create an instance of a proxy object, you can also programmatically set the URL property of the object in your application. Regardless of which URL the proxy uses, it must be for a Web service that conforms to a WSDL that matches the one you used when adding the Web reference. Otherwise, the proxy class that you generated earlier will not work with it.
Calling Web Service Methods
After adding a Web reference to a Web service, you can invoke the exposed methods of that Web service and access the results just as you would any other method of a component.
For examples of how to implement these techniques in the XBikes sample application, see Chapters 7 and 8.
Creating Web Services in J2EE
Implementing Web services in Java is currently not as straightforward as with Microsoft .NET Framework. At the time of this writing, the latest released version of the J2EE specification is version 1.3, and version 1.4 is currently in beta. In version 1.3 there is no native implementation of Web services. For example, there is no java.webservices package that you can import and use with the Java syntax.
However, there is considerable drive within the Java community to define and implement Web services. The Java Community Process defines the following Java Specification Requests (JSRs) that cover Web services:
- JSR 109 Implementing Enterprise Web Services
- JSR 93 Java API for XML Registries 1.0 (JAXR)
- JSR 67 Java APIs for XML Messaging
- JSR 101 Java APIs for XML based RPC
JSR 109 defines the Web services for J2EE architecture. It uses the J2EE component architecture to provide a familiar, portable, scalable and interoperable client and server programming model. JSR 109 builds upon JSR 67, JSR 93 and JSR 101.
Note If a Java vendor's Web services implementation complies with JSR-109, other JSR-109 compliant implementations should be able to interoperate with it.
JSR 93 defines how Java applications connect to XML registries, such as JNDI, ebXML and UDDI. This JSR provides mechanisms so that Web services can publish their interfaces and client applications can then discover these interfaces.
JSR 101 concentrates on XML RPC and the Java language. These include the following:
- Representing XML based interface definitions in Java.
- Defining interfaces with XML based interface definition languages such as SOAP.
- Implementing marshalling.
JSR 67 provides similar definitions for XML messaging.
Java Web Services Stacks
Currently, Web services support on the Java platform requires a Web services stack, of which there are several from which to choose. The most popular implementations are the following:
- Apache Axis is an open source implementation of Web services from the Apache Software Foundation.
- IBM has several Web service stacks available, such as WebSphere Application Server, Web Services Developer Kit (WSDK), and the Emerging Technologies Toolkit (ETTK). IBM also offers a UDDI Registry and Server product.
- WASP from Systinet provides a Web services stack for both C/C++ and Java Environments. Systinet also provide a separate UDDI Server.
- GLUE from The Mind Electric is a popular Web services stack. The Mind Electric (recently aquired by webMethods, Inc.) also provides a UDDI Server.
- WebLogic application server from BEA also has a Web service stack.
The decision on which Web stack you select is likely to reflect organizational preferences as well as technical requirements.
Creating a Web Service in Java
Creating a Web service in Java differs depending on which Web services stack you choose, and to some degree, which Java IDE you use. All vendors provide tutorials on how to build Web services in their documentation. However, the main steps for building a Web service are the same.
First, you need to identify which functionality you want to expose. With that information, you either need to create a new class exposing this functionality or identify an existing class that already does the job. Many Web service stacks allow you to expose an existing class or EJB as a Web service. From an architectural point of view, you should create a new class, even if it simply calls an existing one. This provides some protection against changes in the application.
After you decide the class you want to expose, you have to configure your Web service stack to expose this class. Most Java Web service implementations run as a servlet inside an application server.
Note Some stacks, such as GLUE and WASP, provide their own container if an application server is not available.
You configure these servlets using various configuration files. To deploy a Web service, you need only modify these configuration files. Many vendors also supply a way of exposing Web services dynamically using an API, but this hard coding should be avoided.
For example, GLUE requires that you create an XML configuration file for your Web service. To expose this Web service, you just add your class to the configuration file. The GLUE servlet parses this file when it loads and creates the appropriate WSDL and schema documents based on the class.
For more information about how to create a Web service using GLUE, see the GLUE documentation. The XBikes sample application provides an example of implementing Web services for interoperability in Chapter 7, "Integrating .NET in the Presentation Tier."
Consuming a Web Service in Java
Despite there being many different Java Web services vendors, consuming a Web service is a fairly simple task in nearly all vendor implementations. You can use a tool named WSDL2Java against a local or remote WSDL document, which then creates a Java proxy implementation. This is similar to the way in which .NET Framework consumes Web services, except the Java tools simply create an interface rather than an actual class. WSDL2Java usually creates a helper class, which creates an object based upon the URL endpoint. This object implements the interface that the WSDL2Java creates, which you can then use in your client application.
Chapters 7 and 8 provide examples of consuming a Web service on the Java platform.
Securing Web Services
Applications running in production environments usually require some form of authentication and authorization. This enables tracking of the users of a service and keeps their data separate from others.
The easiest way to implement authentication is to use the infrastructure built into HTTP to provide user names, passwords, and domains to the Web service. Web services published from .NET Framework can use HTTP authentication. Although this identifies a user, it is not secure, because HTTP packets are not safe from interception. Basic authentication sends user names and passwords in clear text, making it possible for an electronic eavesdropper to identify user names and passwords.
More advanced authentication methods such as Kerberos, NTLM, or Digest provide for encrypted authentication methods but these methods provide encryption for only the authentication process itself. Your Web service implementation may require a completely secure process with encryption applied to all client to server transactions. To do this, you have a choice of approaches:
- Transport level security.
- Application level security.
- Web Services Security (WS-Security).
Transport level security such as Secure Sockets Layer (SSL) encryption over HTTPS works at the protocol level and encrypts all the packets between the start point and endpoint of an individual Web service call. This works fine from the client (for example, an ASP.NET application in the Presentation tier) to a Web service in the Business tier. After the packets arrive at the Business tier, this is the SSL endpoint and the Business tier Web service decrypts the packets.
There is a problem when you want to keep the packets encrypted until they reach the Database tier, which stores the user names and passwords. Because SSL is a point to point encryption method, it is not suitable for keeping your data encrypted across multiple Web service calls in multi-tier environments.
Application level security involves developing some sort of custom security implementation. Although this technique can avoid the point to point issues with SSL by providing end to end encryption, it requires coding that would work only with clients that implement that custom security implementation. In Web services, this is counter to the idea of promoting accessibility.
The third option, WS-Security, provides application level security using a published specification. As long as the clients understand WS-Security, they can connect securely to the Web service.
WS-Security defines XML structures for security tokens, and clients use these security tokens as proof of identity. WS-Security tokens would typically include a user name, binary, and security token reference. WS-Security uses standard components, such as X.509 certificates, to endorse the identity of the client. WS-Security also provides encryption, either for the body of a SOAP message, the header, or both.
You control WS-Security settings through policy files, which are XML files with a .wsse file name extension. Implementing WS-Security involves creating the policy file and associating the file with your Web service. The Web service then checks both incoming and outgoing messages against the policy to ensure that they comply with the settings in force.
To access a secured Web service, you create a security policy file and associate it with the Web service control. The client policy settings must match those on the server.
Although the WS-Security standard is not fully ratified, a number of vendors have produced their own implementations, including the following:
- WSE (Web Services Enhancements) from Microsoft.
- IBM Web Services Toolkit from IBM.
- Weblogic Workshop from BEA Systems.
For more information about implementing WS-Security and WSE, see the References section at the end of this chapter.
Using Universal Description, Discovery, and Integration
UDDI is a standard specification for publishing and locating Web services. To implement UDDI, set up a UDDI server, and then register Web services URLs and descriptions with the service. You can think of UDDI as similar to Internet Locator Services (ILS), but dealing in Web services rather than people. Like ILS, UDDI servers can be public (a UDDI Business Registry or UBR), private (intranet based), or semi-private, for use between business partners. You can also compare UBR servers to telephone directories, with white pages listing businesses by name, yellow pages organizing them by function, and green pages describing the services they provide.
UDDI overcomes the issue that a simple URL is rarely very revealing. For example, it does not tell you very much about the service offering. Also, URLs have a habit of morphing into other URLs, preventing clients from connecting. UDDI uses a publish and subscribe model to enable consistency in connecting to Web services, independent of the vagaries of URL strings.
The UDDI directory database stores URLs or access points, associating them with the service offerings and the businesses involved. Business information can include contact details and the market sector in which the business operates, enabling flexible and efficient searches.
Major IT vendors such as Microsoft, IBM, SAP, Veritas, and NTT UDDI are part of the UDDI initiative, which is now at release 3.0. These five vendors also maintain the public UBR registries. For more information about UDDI, including details on white papers and best practices, see the UDDI Web site (http://uddi.xml.org/uddi-org).
Interoperability Benefits Using UDDI
UDDI provides major benefits for interoperability projects that involve Web services. Any Java or .NET Framework client that needs to make dynamic lookups for service offerings can make good use of UDDI. Other benefits include the following:
- Common Web service publication UDDI provides a platform-independent view of Web services.
- Dynamic configuration Any client application can use UDDI to configure a Web service proxy dynamically, removing the need for a hard coded URL. Additionally, dynamic rebinding allows multiple URL instances for a Web service. Similar to round-robin DNS, if one link fails to respond, applications can request another service instance from the same provider through UDDI.
- Web service re-use Large organizations may have multiple departments working on development projects, often resulting in duplicated Web service offerings. UDDI lets development teams browse through a list of already published Web services, preventing departments from wasting time and money on providing a service that is already available.
- Location specific Web services Improves performance and reduces network traffic by allocating a location to a Web service, enabling clients to bind to the closest service instance.
UDDI Registries
The central component of UDDI is the registry, which enables organizations to publish location information on available services. However, you do not have produce Web services for public consumption to benefit from UDDI.
Note Microsoft, IBM, and SAP host test public registries that allow developers to test registration and publication processes.
Several vendors have implemented UDDI services on the latest operating systems:
- Microsoft includes UDDI as a core service in Windows 2003
- IBM have added a UDDI registry to WebSphere
- The Mind Electric package a UDDI server with GLUE
Note If implementing UDDI internally, check for support of the 3.0 standard.
UDDI promises to be a major growth area in the future and offers significant benefits when implementing Web services. This next section considers a number of best practice recommendations to assist Web services and interoperability.
Implementing Web Services Interoperability Best Practices
Web services is still an emerging technology. The protocol specifications that Web services are based on are not yet officially ratified standards, so different vendors' implementations may not be interoperable with each other. The WS-I Basic Profile should help improve Web services interoperability in the future. However, to give yourself the best chance of implementing Web services when interoperating between .NET Framework and Java, follow these best practice guidelines:
- Define data types first If you plan to use complex data types over Web services, design your data types from a common XML schema using some of the strategies outlined in Chapter 3, "Interoperability Fundamentals."
- Test your data types Before you start to code your main application, use test applications that simply pass your data types back and forth in a proof of concept pilot that show your interoperability solution working.
- Use simple data types whenever possible If you can implement a simpler data type, do so. Implement complex data types only for sound business reasons, rather than because you enjoy the challenge.
- Base all data types on XSD data types This is especially important if you implement complex data types. As described in Chapter 3, "Interoperability Fundamentals," this ensures that the data types in your complex data objects map to types in .NET Framework and Java.
- Store all data types centrally Separating out the data types from the proxy file and storing them in a separate location is particularly useful when the .NET and Java assemblies require a single XML namespace for all types.
- Comply with WS-I Basic Profile 1.0 This is an overriding factor if making your service publicly available. Make sure you keep up to date with revisions and new releases of the WS-I profile.
- Standardize on document/literal style rather than combinations involving SOAP or RPC encoding Implementing SOAP encoding prevents validation against a schema and RPC encoding tends to be tightly coupled into the service and interface-driven.
Note WS-I Basic Profile 1.0 actively promotes document/literal style.
- Use the latest Java Web services distribution In the fast-moving world of Java distributions and associated tools, using the most recent distribution keeps you working with the latest specifications, improves reliability, and provides consistent interoperability.
- Use UDDI to discover Web services UDDI is a powerful and effective way of discovering Web services either within an organization or as part of a public service offering.
- Apply abstraction through Interoperability Adapter/Service Interface patterns This lets you add functionality to a Web service call without modifying the caller logic. The abstraction layer might be between the business logic and the ASP.NET Presentation tier making the call. Implementing an Interoperability Adapter/Service Interface pattern keeps the ASP.NET code clean of additional overhead, such as working out a URL from the UDDI registry. For more information about Interoperability Adapter/Service Interface patterns and example implementations, see Chapter 6, "Implementing Interoperability Design Elements."
As with all best practice recommendations, there may be occasions when you need to implement a different solution. However, keeping to these guidelines should assist you to enable your applications to work together with the minimum of fuss.
Comparing .NET Remoting to Web Services
.NET Remoting with runtime bridges and Web services provide different approaches to application platform interoperability that provide flexibility in specifying the communication method between application components. Although sharing some similarities, .NET Remoting and Web services differ in a number of details. Table 4.4 summarizes the similarities and differences.
Table 4.4: Feature comparison between .NET Remoting and Web services
| Feature | .NET Remoting | Web services |
| HTTP Channel | .gif) | .gif) |
| SOAP over HTTP | .gif) | .gif) |
| TCP Channel | .gif) | .gif) |
| XML Formatter | .gif) | .gif) |
| Binary Formatter | .gif) | .gif) |
| Pass by Value | .gif) | .gif) |
| Pass by Reference | .gif) | Difficult to implement |
| Storing Session State | Easy | More complicated |
| Invoke single method on a stateless object | .gif) | .gif) |
| Invoke multiple methods on a stateful object | .gif) | .gif) |
| All clients can invoke methods on same server side object | .gif) | .gif) |
| Traverse Firewalls | .gif) | .gif) |
| Use IIS as host | .gif) | .gif) |
| Use custom host | .gif) | .gif) |
| Retrieve complete copy of complex object | .gif) | .gif) |
Because there is considerable industry momentum behind Web services at present, you might be inclined to implement Web services as a matter of course. However, Table 4.4 shows that there are several areas where .NET Remoting shows notable advantages.
Because .NET Remoting incorporates a TCP channel, this removes the need for HTML headers. Combining this with a binary formatter usually provides a significant performance boost for large traffic volumes.
Implementing pass by value and pass by reference are possible for both methods, but they are significantly more difficult to implement in Web services. Also, session state management in .NET Remoting is less complicated than with Web services.
Other advantages of .NET Remoting over Web services include the following:
- Guaranteed interoperability.
- Support for client activation and lifetime control of remote objects (similar to DCOM).
- Support for callbacks and events.
- Support for additional context information specific to .NET Framework. In the future, such information will enable additional features such as distributed transactions and additional security levels.
- Support for type system fidelity, which means that there is a one-to-one mapping between the class and type hierarchy. Web services and SOAP do not support such an object-oriented mechanism for accessing remote objects.
Implement .NET Remoting within a tightly coupled intranet environment where you expect high transaction volumes and you control both sides of the communication. Use Web services for more loosely coupled systems, particularly those connecting across the Internet, or where you do not have control of both ends of the conversation.
Web services have advantages over .NET Remoting, mainly in the following areas:
- Platform independence Web services use open and ubiquitous standards such as XML, SOAP, HTTP, and WSDL. Consequently, Web services offer genuine platform independence; you can invoke a Web service from any client platform, irrespective of the server platform or implementation technology of the Web service.
- Security IIS is the standard host of choice for ASP.NET components, so Web services applications created using ASP.NET can automatically take advantage of the security features in IIS, such as support for Windows authentication, Secure Sockets Layer (SSL) encryption and logging. You can use IIS to host .NET Remoting components, in which case they can make use of the same security mechanisms. However, if you do not host your .NET Remoting components in IIS, you must implement authentication, authorization, and privacy mechanisms yourself.
- Caching Hosting ASP.NET components in IIS also adds IIS caching support for Web services. Effective caching can significantly reduce the performance advantages of .NET Remoting, depending on the type of data that you want to cache. Caching is most effective for repeatedly requested public data, and decreases in effectiveness when caching private data or with dynamic data. .NET Remoting has no built in support for caching, even when IIS hosts the remoting components. Hence, like security, you have to build caching support manually.
- Ease of creation Visual Studio .NET makes it easy to create and consume Web services. To create a Web service, create an ASP.NET Web service project and implement methods decorated with the [WebMethod] attribute. To consume a Web service, create any kind of project in Visual Studio .NET and add a Web reference to a Web service of your choice; Visual Studio .NET generates a client-side proxy that simplifies access to the Web service.
If these factors are important to you, Web services might be a better choice than .NET Remoting to achieve point-to-point interoperability.
Summary
This chapter described the methods for providing point to point interoperability between .NET Framework and Java. It covered .NET Remoting and how you can use runtime bridges such as JNBridgePro and Ja.NET to link .NET Framework and Java. It then investigated the rapidly evolving world of Web services and described how emerging standards such as UDDI and XML can simplify the process of linking Java and .NET Framework components. In the next chapter, you examine interoperability techniques based on message queuing.
References
For more information about XML Web Services, see:
Chapters 5 and 6 of Simon Guest's book, Microsoft .NET and J2EE Interoperability Toolkit, Microsoft Press, ISBN 0-7356-1922-0
Scott Short's book, Building XML Web Services for the Microsoft .NET Platform, Microsoft Press, ISBN 0-7356-1406-7
For more information on JNBridgePro from JNBridge, see http://www.jnbridge.com
For more information about the JSR specifications See the Java Community Process Web site http://www.jcp.org/en/jsr/all
For more information about Apache Axis http://ws.apache.org/axis/
For information about IBM's Web services implementations see the developerWorks Web site http://www.ibm.com/developerworks/webservices/
For more information about Systinet's Web services implementation http://www.systinet.com/products/wasp_jserver/overview [Content link no longer available, original URL:http://www.systinet.com/products/wasp_jserver/overview]
For more information about GLUE from The Mind Electric http://www.softwareag.com/corporate/default.asp
For more information about Web services on the .NET Framework http://msdn.microsoft.com/en-us/netframework/aa663324.aspx
For more information about how to implement Web services on the .NET Framework "Creating XML Web Services in Managed Code" http://msdn.microsoft.com/en-us/library/3x5e7527(VS.71).aspx
For more information about .NET Remoting "Microsoft .NET Remoting: A Technical Overview" http://msdn.microsoft.com/en-us/library/ms973857.aspx
For more information about .NET Remoting configuration files "Format for .NET Remoting Configuration Files" http://msdn.microsoft.com/en-us/library/ms973907.aspx
For more information about hosting remotable objects in IIS "Hosting Remote Objects in Internet Information Services (IIS)" http://msdn.microsoft.com/en-us/library/y0hedwet(VS.85).aspx
For more information about security in Web services "Security" in the Web Services Developer Center http://msdn.microsoft.com/en-us/netframework/aa663324.aspx
For more information about implementing service interfaces "Enterprise Solution Patterns: Implementing Service Interface in .NET" http://msdn.microsoft.com/en-us/library/ms998554.aspx
For more information about implementing WSE, see the following articles on MSDN: "Web Service Enhancements 1.0 and Java Interoperability, Part 1" http://msdn.microsoft.com/en-us/library/ms996946.aspx
- and -
"Web Service Enhancements 1.0 and Java Interoperability, Part 2" http://msdn.microsoft.com/en-us/library/ms996947.aspx
For more information about UDDI services on the IBM platform "Understanding UDDI" on the IBM Web site http://www.ibm.com/developerworks/webservices/library/ws-featuddi/#What%20is%20UDDI?
For equivalent information about GLUE See the GLUE UDDI Web site http://www.themindelectric.com/docs/glue/guide/uddi/index.html [Content link no longer available, original URL:http://www.themindelectric.com/docs/glue/guide/uddi/index.html]
To install UDDI on Windows Server 2003, see the topic "Using UDDI Services" in Windows Server 2003 Family Help.
Start | Previous | Next
.png)