Building Synchronous Web Services with .NET and Java EE


The best primer in getting started with Web services in .NET, both from a server perspective (where the service is built in .NET and consumed by Java) and from a client perspective (where the service is built in Java and consumed by .NET) is by example.

The following sections discuss how to build and consume synchronous Web services using both technologies. The example used is a trivial one, passing a simple data type (string) between the services, but it provides the grounding necessary to understand how to build and deploy both the service and the client. Subsequent chapters look into how to handle much more complicated services and clients.

After exploring the Web services technologies provided by Java EE and Microsoft .NET platforms, it is important to talk about how Web services interoperability can be established between the two. This chapter looks into building synchronous Web services communication between Java and .NET applications. WS-I Supply Chain Management Application is used as a sample to implement the interoperability between Java and .NET.

Typically there could be two scenarios where integration is important:

  • The service implementation is provided by Java EE, and the Microsoft .NET components need to access this functionality. In this case, a Microsoft .NET client is needed to access the service. In Web services terminology this implies having a Java EE-based Web service provider and a Microsoft .NET-based service requester that communicates with the service provider.

  • The second scenario is where a Java EE system needs access to a Microsoft .NET Web service. This would require creating a Java EE Web service client that talks to the Microsoft .NET Web service.

There are dos and don'ts for ensuring Web services interoperability between Java EE and Microsoft .NET. It makes the most sense, however, to first focus on establishing simple interoperability between the two platforms using JAX-RPC and then discuss the best practices that will help ensure interoperability. In either of the scenarios just described, there are basic steps that need to be followed to integrate Java EE and Microsoft .NET-based systems using Web services. These are

  • Defining the schema for the Web service.

  • Publishing the WSDL WSDL provides a mechanism to allow the precise structure and data types of the messages to be commonly understood by Web services producers and consumers.

  • Using WSDL to create Web service clients This can be done using tools provided by Java EE and Microsoft .NET frameworks for stub and tie generation. JAX-RPC provides a tool called wscompile that generates the artifacts that are required to link a JAX-RPC client application to a Web service. Similarly, the Microsoft .NET Framework provides a tool called wsdl.exe that generates the proxy classes that are the bridge between the client and the Web service. This book uses these tools for developing clients for Java EE and Microsoft .NET-based Web services.

.NET clients talk to Web services using proxies generated by wsdl.exe as just described. To consume and interoperate with a Java EE-based Web service, the following steps are used:

  1. Build and expose Java EE services as Web service

  2. Discover the Web services

  3. Build proxy classes for communication with them from .NET

  4. Develop a .NET client that uses the proxy classes

  5. Execute the client

In the next section these steps are followed to build a Web service on Java EE and consume it using a .NET Framework-based application (see Figure 4-3). This application is based on the Retailer interaction in the WS-I Supply Chain Management use-case.

Figure 4-3. Java EE service implementation and .NET client


A Java-Based Web Service with a .NET-Based Client

Now that the basic steps for establishing Java EE .NET interoperability have been introduced, following is a look at a real-world example of how to create interoperable Web services with a Java EE-based service provider and a .NET-based service consumer. Figure 4-4 lists the high-level diagram outlining Retailer services:

Figure 4-4. .NET client consuming Java Retailer service


Building the Java Retailer Service

Building this application is very straightforward. The following starts with a simple Java class that implements the Retailer.

First is to develop the interface that represents the store.

package javaretailer; import java.rmi.RemoteException;import java.rmi.Remote; public interface IRetailer extends Remote {   String getProductCatalog () throws RemoteException; } 


The Java class that implements this interface to create the Retailer service is straightforward:

package javaretailer; import java.rmi.RemoteException; import java.rmi.Remote; public class JavaRetailerService implements IRetailer {   public String getProductCatalog() throws RemoteException {     String strReturn = "We would build a list of items here";     return strReturn;   } } 


Typically these can be compiled using ant, a freely available tool that can be used to script compilation processes. The scripting is achieved using an XML configuration file called build.xml. A snippet of build.xml that compiles this Web service looks like

<target name="compile-javaservice" depends=" prepare" >   <echo message="--- Compiling  application ---"/>    <javac srcdir="${src.java}"          includes="**/JavaRetailer*.java"          destdir="${build.classes}" >     <classpath refid = "compile.classpath"/>   </javac> </target> 


ant is invoked and instructed to build the service using the following command:

ant compile-javaservice 


To deploy these as a Web service, the following configuration files are needed.

Config.xmlwhich specifies the names of the interface and its implementation. The wscompile tool reads this configuration to generate a WSDL for the Java Web service. It typically looks something like this:

<?xml version="1.0" encoding="UTF-8" ?> <configuration xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config"> <!-- The wscompile reads the RMI interface to generate WSDL file. -->   <service name="JavaRetailerService"           targetNamespace="http://j2eedotnet.com/javaretailer/wsdl"           typeNamespace="http://j2eedotnet.com/javaretailer/types"           wsdl="http://j2eedotnet.com/javaretailer/WSDL"           packageName="javaretailer">     <interface name="javaretailer.IRetailer"               servantName="javaretailer.JavaRetailerService">   </service> </configuration> 


Web.xml is the standard deployment descriptor for Java servers. For the JavaRetailer service, it looks something like this:

<?xml version="1.0" encoding=" UTF-8" ?> <!DOCTYPE web-app PUBLIC          "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"          "http://java.sun.com/j2ee/dtds/web-app_2_3.dtd"> <web-app>   <display-name>Java Retailer Web Application</display-name>   <description>Java Retailer Web Service</description>   <session-config>     <session-timeout>60</session-timeout>   </session-config> </web-app> 


Finally, jaxrpc-ri.xml, used by the wsdeploy tool to generate the WAR file that holds the Web service, looks like this:

<?xml version="1.0" encoding="UTF-8" ?> <webServices xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/dd"             version="1.0"             targetNamespaceBase=                 "http://j2eedotnet.com/javaretailer/wsdl"             typeNamespaceBase=                 "http://j2eedotnet.com/javaretailer/types"             urlPatternBase="/javadotnet">  <!-- The <endpoint> element contains the Web Service's -->  <!-- interface and implementation classes -->    <endpoint name="IRetailer"             displayName="Retailer Service"             description="Retailer service"             wsdl="/WEB-INF/RetailerService.wsdl"             interface="javaretailer.IRetailer "             implementation="javaretailer.JavaRetailerService"             model="/WEB-INF/model.xml.gz"/>    <endpointMapping endpointName="JavaRetailer"                   urlPattern="/JavaRetailer"/> </webServices> 


The service can now be built, put into a WAR file, and deployed to an applications server such as Tomcat.

Again, this can be achieved using ant. The scripts to build and deploy the application to Tomcat look like this:

<!-- Compiling classes --> <target name="compile-javaservice" depends="prepare">   <echo message="--- Compiling  application ---"/>    <javac srcdir="${src.java}"          includes="**/JavaRetailer*.java"          destdir="${build.classes}" >     <classpath refid = "compile.classpath"/>    </javac> </target> <path >     <path ref/>     <pathelement location="${build.classes}"/> </path> <!-- Generate BookOrder Web Service components --> <target name="generate-server" depends="compile-javaservice">  <wscompile    define="true"    keep="true"    base="${build.classes}"    sourceBase="${build.src}"    model="${build.model}/model.xml.gz"    xPrintStackTrace="true"    verbose="false"    config="${etc.server}/config.xml">    <classpath ref/>  </wscompile> </target> <!-- Archiving BookOrder components into BookOrder-raw.war --> <target name="create-war" depends="generate-server">   <war warfile="${build.home}/JavaRetailer-raw.war"        webxml="${etc.server}/web.xml">       <webinf dir="${build.classes}" includes="*.wsdl"/>       <webinf dir="${etc.server}" includes="jaxrpc-ri.xml"              defaultexcludes="no"/>       <webinf dir="${build.model}" includes="model.xml.gz"              defaultexcludes="no"/>       <classes dir="${build.classes}" includes="**/*.class"              defaultexcludes="no"/>   </war> </target> <!-- Creating the final WAR file --> <target name="build-war" depends="create-war">   <echo message="--- Building war file ---"/>   <wsdeploy       keep="true"       inWarFile="${build.home}/JavaRetailer-raw.war"       outWarFile="${build.home}/JavaRetailer.war"       verbose="false"       tmpDir="${build.temp}">       <classpath ref/>   </wsdeploy> </target> <!-- Deploying the BookOrder Web Service --> <target name="deploy-javaservice" depends="build-war">    <copy file="${build.home}/JavaRetailer.war" todir="${tomcat.root}/webapps"/> </target> 


When using ant it can either be invoked without a parameter, in which case the entire file will be processed, or it can be passed a specific target such as ant compile-javaservice, in which case the commands specified at <target name="compile-javaservice"> are executed.

In the script just listed, the following targets are used:

  • Compile-javaservice: Invokes the javac compiler to compile all the java classes needed to make the Web service.

  • Generate-server: Invokes the wscompile tool that begins the packaging process for the Web service.

  • Create-war: Creates the Web Archive (WAR) file that the Web service will reside in using the war tool.

  • Build-war: Compiles the WAR file for the Web service using the wsdeploy tool.

  • Deploy-javaservice: Copies the WAR file to the web applications directory on Tomcat.

Once deployed, the application can be run by hitting the context root that is specified in the configuration files. For example it can be run with the following URL if it is deployed to Tomcat (as in this ant script).

http://localhost:8080/JavaRetailer 


To get the WSDL associated with this Web service, ?WSDL is simply applied to the end of the URL, like this:

http://localhost:8080/JavaRetailer?WSDL 


Now that the Java Web Service is established, the next thing to do is to create a client in .NET that consumes this, which is a very straightforward matter.

The first thing to do is to generate a .NET proxy to the Web service using the .NET wsdl tool like this

wsdl.exe/out:Retailer.cs http://localhost:8080/JavaRetailer?WSDL 


This generates a proxy module called Retailer.cs, based on the WSDL found at the specified URL. This proxy module can then be used in an application, as follows:

using System; public class DotNetClient {   public static void Main() {     RetailerService srv = new RetailerService();     String result = srv.getProductCatalog();     Console.WriteLine(result);   } } 


This gives a basic, synchronous .NET-based client that consumes a Java-based Web service.

A .NET-Based Web Service with a Java-Based Client

In this section the Retailer Web service is created using .NET technology and a Java client is built that synchronously consumes this service. The high-level diagram for this is shown in Figure 4-5.

Figure 4-5. Java client consuming .NET Retailer service


The JAX-RPC reference implementation provides a number of tools that simplify building and deploying Java-based Web services. These include the wscompile and wsdeploy tools. These utilities can generate the Java code necessary to link both the client and server implementations to the underlying JAX-RPC infrastructure that ultimately creates or consumes SOAP messages. Application server vendors also provide similar tools.

Using the wscompile tool, it is possible to generate the client side stubs for a .NET-based Web service. These stubs can be used to write a JAX-RPC client for the Web service.

The Java EE model for Web service consumption in Figure 4-6 requires the following steps:

Figure 4-6. .NET service implementation and Java EE client


  1. Develop and expose a .NET Web service

  2. Discover the .NET Web service

  3. Build the client side stubs for the Web service

  4. Develop a JAX-RPC client using the stubs

  5. Run the JAX-RPC client

The easiest way to develop a Web service with .NET is to use the Visual Studio.NET tool from Microsoft. From here, File>New>Web Service is selected to generate a basic skeleton Web service. One called DotNetRetailer.asmx can be created.

Then underlying C# code for this Web service should then be changed to the following:

using System; using System.Web.Services; namespace dotnetretailer {   public class DotNetRetailService : System.Web.Services.WebService {     [WebMethod(Description = "BookOrder Web Service")]     public string getProductCatalog() {       string strReturn = "The Product Catalog would go here.";       return strReturn;     }    } } 


This can then be compiled and deployed to IIS using the IDE, and the Web service can be accessed with this URL:

http://localhost/DotNetRetailer/DotNetRetailer.asmx 


As mentioned earlier, the WSDL for the service is accessible using ?WSDL at the end of the URL, like this

http://localhost/DotNetRetailer/DotNetRetailer.asmx?WSDL 


To create a client to this Web service in Java, the wscompile tool can be used. This requires a configuration file containing the settings that drive it to create Java stubs for a proxy to this service. The configuration file will look like this

<configuration xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config" > <wsdl   location="http://localhost/DotNetRetailer/DotNetRetailer.asmx?WSDL"   packageName="dotnetretailer"/> </configuration> 


Point wsconfig at this configuration file and it will generate the stubs for talking to this Web service in the package dotnetretailer. These stubs can then be used to talk to the .NET Web service in a Java client like this

package dotnetretailer; import javax.xml.rpc.Stub; public class JavaClient {   public static void main (String[] args) {   try {      DotNetRetailService_Stub stub =      (DotNetRetailServiceSoap_Stub)      (new DotNetRetailService_Impl().getDotNetRetailService Soap());       stub._setProperty(          javax.xml.rpc.Stub.ENDPOINT_ADDRESS_PROPERTY,          System.getProperty("endpoint"));       System.out.println(stub.getProductCatalog());     }     catch (Exception ex) {       ex.printStackTrace();     }   } } 


This client will now consume the .NET-based Retailer service.




Java EE and. Net Interoperability(c) Integration Strategies, Patterns, and Best Practices
Java EE and .NET Interoperability: Integration Strategies, Patterns, and Best Practices
ISBN: 0131472232
EAN: 2147483647
Year: N/A
Pages: 170

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net