JaVa
   

JAX-RPC Interoperability

In the context of Web services, interoperability can be summarized as meaning that the functional characteristics of the service should remain immutable across differing app platforms, coding languages, hardware, operating systems, and app data models. By definition, Web services should be interoperable, and the service consumer should not be tied to the service implementation.

However there are bound to be issues when apps use disparate SOAP libraries that generate and manipulate the underlying SOAP message, disparate coding languages, and disparate hardware-software stacks. The following are common causes for interoperability problems between these libraries or toolkits:

Java Start Sidebar

The only real mechanism for ensuring interoperability is to verify compliance with standards:

The JAX-RPC API and SAAJ provide a standard interface for Java developers leveraging these same standards.

Java End Sidebar

In general, architects should keep the following in mind while designing Web services:

  1. Avoid propeietary extensions. Avoid building dependencies into the app that use any vendor-specific extension to the specifications JAX-RPC depends on (SOAP, WSDL, XML schemas, and HTTP).

  2. Test interoperability. Never assume things will work as they should. It is essential to test interoperability of the service implementation across multiple consumers, especially if the consumers are outside the boundaries of the organization. Public interoperability tests are also available from the Web Services Interoperability organization (www.ws-i.org) and White Mesa (www.whitemesa.com).
    Java Start Sidebar

    Testing! To promote SOAP-level interoperability and address issues between implementations, the SOAPBuilders community—with members as diverse as IBM, Microsoft, Oracle, Apache, and even individuals—has come together to develop an interoperability test suite specification and regularly conduct testing of their endpoints against this specification. See http://soapinterop.java.oracle.com/soapbuilders/index.shtml and www.xmethods.net/ilab.

    Java End Sidebar
  3. Analyze disparate data models. When a service is used to integrate apps that have disparate data models, the models may need to be resolved by creating an intermediate model. For example, flutebank.com integrates with brokerage.com to provide customers the ability to view their accounts simultaneously online when in any of the portals. The data model for an account as represented in flutebank.com may be quite different from an account in brokerage.com. In this scenario, the architects will need to reconcile the models by creating an XML schema acceptable to both parties.
  4. Analyze disparate data types. Data types passed as arguments and return types from the service invocation can impact interoperability.
    • JAX-RPC-defined data types. The data types and mappings defined in the specifications are available in all JAX-RPC runtimes. Because they are subsets of the XML schema specifications and map directly to the data types in the SOAP encoding, they are completely interoperable.

    • Custom data types. If the data type is custom defined (e.g., a java.util.HashMap of com.flutebank.accounts.Account objects), an XML schema must be created to describe the representation of the data and the custom serializer and deserializer for that data on the server. Such a schema may not be completely interoperable. In addition, the JAX-RPC client would need to write serializers and deserializers to invoke the service. We looked at handling custom data types earlier in this chapter. In summary, custom data types may not be completely interoperable across all service consumers.
  5. Avoid custom data types. Custom data types that force the use of custom serializers and deserializers can potentially cause interoperability issues with other implementations. For example, a List may be represented differently by implementations from vendors A and B. If vendor A's client runtime is used to invoke a service deployed in vendor B's runtime, serialization errors may occur, because each implementation uses its own XML mapping of that data type. If the mapping is not available, the corresponding serailizers and deserializers will need to be written.

    For collection classes in particular, the SOAPBuilders community plans to pursue interoperability testing across vendor runtime implementations.

  6. Customize data, protocols, and encoding schemes. Architects should be wary of any code that customizes the messages. A good example is the Compress-Secure handlers example in Listing 10.13. The endpoint of that service cannot be invoked by clients that are not aware of the compression and security algorithm used and understood by the service. From a service perspective, there is no standard way to communicate this information (e.g., it cannot be specified in WSDL).
  7. Promote portability of client code between JAX-RPC implementations. J2EE developers would be familiar with the concept of writing an EJB and deploying it transparently in a J2EE server. The EJB client can be written with complete transparency and used in any J2SE environment by simply altering configuration properties. This portability of client code does not translate identically in the JAX-RPC environment, especially when using custom data types. A JAX-RPC client is not guaranteed to be portable if it uses anything beyond the simple data types. This is tied to the way the serializers and deserializers are written, as discussed earlier. In other words, if architects choose vendor A's implementation of JAX-RPC and write client code that uses serializers and deserializers to invoke the service, they should not expect to simply take the client code and use it in vendor B's runtime. apps should be designed to abstract away the specificity, minimizing the changes needed.

Let us now look at an example of interoperability in action. We will write a Microsoft C#.NET client to demonstrate how a JAX-RPC Web service can be consumed from a Microsoft.NET environment. We will use the BillPay service developed and deployed previously in this chapter. As in most practical service consumer scenarios, we will invoke a service based on the WSDL describing it. During service deployment, xrpcc was used to generate the WSDL. This WSDL file can now be passed to the Microsoft.NET wsdl compiler, to generate the client-side stubs:

wsdl /l:CS /protocol:SOAP http://127.0.0.1:9090/billpayservice/billpayservice.wsdl


The above generates the C# source file Billpayservice.cs, which contains the structures and serialization rules based on the schema and bindings defined in WSDL. Next, we build a Windows DLL out of the generated proxy code using the C# compiler, passing it the referenced dlls from the .NET framework:

csc /t:library /r:System.Web.Services.dll /r:System.Xml.dll Billpayservice.cs


The next step is to write a client and invoke the three methods exposed by the JAX-RPC Web service. Listing 10.17 shows the C# client code for this purpose.

Listing 10.17: C# client for JAX-RPC
BillPay service using System;
namespace BillpayClient{
 /// <summary>
 /// This is a simple C# client to invoke the flutebank.com Web service.
 /// @Author Sameer Tyagi
 /// </summary>
 class JAX-RPCClient{
 /// <summary>
 /// The main entry point for the app.
 /// </summary>
 [STAThread]
 static void Main(string[] args) {
 // Instantiate the stub/proxy
 Billpayservice serv = new Billpayservice();
 // Set the endpoint URL
 if(args.Length ==1)
 serv.Url=args[0];
 else
 serv.Url= "http://127.0.0.1:9090/billpayservice/jaxrpc/BillPay";
// Invoke the schedule payment method
 PaymentConfirmation conf = serv.schedulePayment(DateTime.Today," my
 account at sprint",190);
 Console.WriteLine("Payment was scheduled "+ conf.confirmationNum);
// Invoke the listSchedulePayment method
 PaymentDetail[] detail= serv.listScheduledPayments();
 for(int i=0;i< detail.Length;i++){
 Console.WriteLine("Payee name "+ detail[i].payeeName);
 Console.WriteLine("Payee name "+ detail[i].account);
 Console.WriteLine("Payee name "+ detail[i].amt);
 Console.WriteLine("Payee name "+ detail[i].date);
 }
// Invoke the getLastPayment method
 Double lastpaid= serv.getLastPayment("my cable tv provider");
 Console.WriteLine("Last payment was "+ lastpaid);
 }
 }
}



Java End example

The C# client code is remarkably similar to the JAX-RPC stub client written earlier, because of the syntactic and semantic similarities between the two programming languages. The client code can now be compiled and executed. The output will be similar to the following:

C:\Dotnetclient>billpayClient Payment was scheduled 81263767
Payee name Digital Credit Union Payee name Credit Payee name 2000
Payee name 8/1/2002 11:27:33 PM Last payment was 829


Java Start Sidebar

The complete C# project and Microsoft .NET runtime distributable can be found on the CD. Java developers can think of the runtime distributable as the JRE. It allows developers to execute the compiled code. To build the source, however, Microsoft.NET Visual Studio is needed.

Java End Sidebar

We have just developed a Web service in Java, deployed it in a JAX-RPC runtime, and exposed the service with only a WSDL interface. WSDL was used to develop a client in a completely different language and platform, C# and .NET, yet produced identical behavior.


JaVa
Comments