9.4.1 ObjectiveApache Axis is a next -generation SOAP engine. This exercise is meant to have you practice using Apache Axis to expose an existing interface as a Web Service. Apache Axis has a different architecture design from previous versions of Apache SOAP. It can generate SOAP client and server components directly, without using a third-party developer IDE/workbench tool. 9.4.2 ExerciseUsing the Foreign Exchange Spot Rate Quote example in Chapter 8, Web Services in Action Case Study, you are to expose the interface as a Web Service using Apache Axis's utilities java2wsdl and wsdl2java. The source code files FXProviderIF.java and FXProviderImpl.java can be found on the CD-ROM accompanying this book under /labs/ch9. They are also listed here for reference (refer to the following excerpts in Figures 9-6 through 9-16). Figure 9-16. Verifying Web Services Deployment by Checking the WSDL
Procedures to Create a Web Service Using Apache AxisStep 1: Define Web Services InterfacesFirst, define the interfaces (that is, methods or APIs) you want to expose as Web Services. Refer to the excerpt FXProviderIF.java in Figure 9-5. A new procedure, getPrice, is added under the public interface FXProviderIF. The getPrice procedure takes in two input parameters sellCurrency and buyCurrency and returns the price in a string format. Figure 9-5 Start by Defining the Interface First (FXProviderIF.java)package myAxis; import java.rmi.Remote; import java.rmi.RemoteException; public interface FXProviderIF extends Remote { public String getPrice(String sellCurrency, String buyCurrency) throws RemoteException; } Step 2: Define Web Services ImplementationThen, define the business logic for the interface to be exposed as Web Services. This may be implemented by developing custom-built code or invoking remote procedure calls from back-office systems (such as a mainframe). Figure 9-6 shows an example of how to implement the Web Services business logic in the program FXProviderImpl. java. The getPrice procedure is now expanded to incorporate the price quote for the currency pairs HKD-USD, HKD-EUR, HKD-RMB, HKD-SGD, HKD-MYR, and so forth. In this example, the same business logic used in the exercise in Chapter 3, Web Services Technology Overview, is reused for instructional purposes. Figure 9-6 Defining the Business Logic to Implement the Web Service (FXProviderImpl.java)package myAxis; import java.math.BigDecimal; import java.util.*; public class FXProviderImpl implements FXProviderIF { // FX conversion rate public String getPrice(String sellCurrency, String buyCurrency) { if (sellCurrency.equalsIgnoreCase("HKD")) { if (buyCurrency.equalsIgnoreCase("USD")) { return "0.128"; } else if (buyCurrency.equalsIgnoreCase("EUR")) { return "0.123"; } else if (buyCurrency.equalsIgnoreCase("RMB")) { return "1.25"; } else if (buyCurrency.equalsIgnoreCase("SGD")) { return "0.22"; } else if (buyCurrency.equalsIgnoreCase("MYR")) { return "2.85"; } else return "0.00"; } else if (sellCurrency.equalsIgnoreCase("USD")) { if (buyCurrency.equalsIgnoreCase("HKD")) { return "7.78"; } else if (buyCurrency.equalsIgnoreCase("EUR")) { return "0.92"; } else if (buyCurrency.equalsIgnoreCase("RMB")) { return "8.20"; } else if (buyCurrency.equalsIgnoreCase("SGD")) { return "2.5"; } else if (buyCurrency.equalsIgnoreCase("MYR")) { return "3.45"; } else return "0.00"; } else return "0.00"; // end-if } // getPrice } // class Step 3: Prepare for Stub/Skeleton GenerationCompile the source code to Java classes to prepare stub (client module) and skeleton (server module) generation. Figure 9-7 shows the command javac to compile the Java code. Figure 9-7 Prepare for Stub/Skeleton Generation D:\Dev\mydemo\myAxis> javac FX*.java D:\Dev\mydemo\myAxis>dir Volume in drive D is WIN2K Volume Serial Number is 3D2F-1863 Directory of D:\Dev\mydemo\myAxis 09/22/2002 03:16p <DIR> . 09/22/2002 03:16p <DIR> .. 09/22/2002 03:19p 1,761 FXProviderImpl.java 09/22/2002 03:18p 394 FXProviderIF.java 09/24/2002 12:13a 266 FXProviderIF.class 09/24/2002 12:13a 827 FXProviderImpl.class 10 File(s) 12,736 bytes 3 Dir(s) 9,780,002,816 bytes free Step 4: Create WSDLGenerate a Web Services Description Language (WSDL) from the interface files (Java classes are required) created in the previous steps. The utility org.apache. axis.wsdl.Java2WSDL will generate the WSDL called FXProvider.wsdl in the same directory, with the Universal Resource Name (URN, or namespace) FXProvider and the service end-point http://localhost:8080/axis/FXProvider, provided with the implementation file FXProviderImpl.class. In Figure 9-8, the utility Java2WSDL will generate a WSDL FXProvider.wsdl that specifies the service end-point URL http://localhost:8080/axis/FXProvider , the URN FXProvider based on the interface file FXProviderImpl. java. The Java2WSDL utility requires the implementation file to be precompiled first. Figure 9-8 Creating WSDL [View full width] D:\Dev\mydemo\myAxis>java org.apache.axis.wsdl.Java2WSDL -o FXProvider.wsdl -l" http://localhost:8080/axis/FXProvider" -n "urn:FXProvider" -p"myAxis" "urn:FXProvider" myAxis.FXProviderImpl In the WSDL generated (shown in Figure 9-9), the business service ("operation name" or the method exposed), service end-point ("address location"), input parameters ("in0" and "in1" of the incoming message name "getPriceRequest"), and output parameter ("getPriceReturn") are highlighted for easy reference. These are the key elements to be specified in writing a Web Services client. Refer to the exercise in Chapter 3, Web Services Technology Overview, for more details. Figure 9-9 Generating WSDL Using Apache Axis Utility [View full width] <?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions targetNamespace="urn:FXProvider" xmlns="http://schemas.xmlsoap.org/wsdl /" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="urn:FXProvider" xmlns :intf="urn:FXProvider" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns :wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl /soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <wsdl:message name="getPriceResponse"> <wsdl:part name="getPriceReturn" type="xsd:string"/> </wsdl:message> <wsdl:message name="getPriceRequest"> <wsdl:part name="in0" type="xsd:string"/> <wsdl:part name="in1" type="xsd:string"/> </wsdl:message> <wsdl:portType name="FXProviderImpl"> <wsdl:operation name="getPrice" parameterOrder="in0 in1"> <wsdl:input message="impl:getPriceRequest" name="getPriceRequest"/> <wsdl:output message="impl:getPriceResponse" name="getPriceResponse"/> </wsdl:operation> </wsdl:portType> <wsdl:binding name="FXProviderSoapBinding" type="impl:FXProviderImpl"> <wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="getPrice"> <wsdlsoap:operation soapAction=""/> <wsdl:input name="getPriceRequest"> <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:FXProvider" use="encoded"/> </wsdl:input> <wsdl:output name="getPriceResponse"> <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:FXProvider" use="encoded"/> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="FXProviderImplService"> <wsdl:port binding="impl:FXProviderSoapBinding" name="FXProvider"> <wsdlsoap:address location="http://localhost:8080/axis/FXProvider"/> </wsdl:port> </wsdl:service> </wsdl:definitions> Step 5: Generate Stub/SkeletonThe next step is to generate the club stubs and the server skeletons in order to expose the implementation Java classes as Web Services. Figure 9-10 shows the command WSDL2Java that generates both the SOAP stub (client-side component) and skeleton (server-side component). Both the stubs and the skeletons will provide a proxy for the Web Services using SOAP messaging. The following command WSDL2Java in Figure 9-10 will generate the client stubs and the server skeletons under a subdirectory "myAxis" based on the specified WSDL (FXProvider.wsdl) and the namespace ("urn:FXProvider"). This step will also generate the Web Services Deployment Descriptors (WSDD) for deployment and undeployment. These descriptors are similar to J2EE deployment descriptors and contain deployment- related information (such as service end-points and input and output parameters). Refer to Figure 9-11 for an example. Figure 9-10 Generating Client Stubs and Server Skeletons [View full width] D:\Dev\mydemo\myAxis> java org.apache.axis.wsdl.WSDL2Java -s -d Session -Nurn:FXProvider myAxis FXProvider.wsdl D:\Dev\mydemo\myAxis>dir myAxis Volume in drive D is WIN2K Volume Serial Number is 3D2F-1863 Directory of D:\Dev\mydemo\myAxis\myAxis 09/24/2002 12:34a <DIR> . 09/24/2002 12:34a <DIR> .. 09/24/2002 12:34a 485 FXProviderImplService.java 09/24/2002 12:34a 3,640 FXProviderImplServiceLocator.java 09/24/2002 12:34a 321 FXProviderImpl.java 09/24/2002 12:34a 6,607 FXProviderSoapBindingStub.java 09/24/2002 12:34a 379 FXProviderSoapBindingImpl.java 09/24/2002 12:34a 1,644 deploy.wsdd 09/24/2002 12:34a 689 undeploy.wsdd 7 File(s) 13,765 bytes 2 Dir(s) 9,779,838,976 bytes free Figure 9-11 shows a Web Services Deployment Descriptor (WSDD). In the WSDD file, it contains some deployment information, including the namespace, port name, and class name. This is slightly different from a normal deployment descriptor and includes some WSL information. It is proprietary and cannot be used by other SOAP engines. Figure 9-11 Web Services Deployment Descriptor Will Be Created During Stubs/Skeletons Generation [View full width] <deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> <! Services from FXProviderImplService WSDL service > <service name="FXProvider" provider="java:RPC"> <parameter name="wsdlTargetNamespace" value="urn:FXProvider"/> <parameter name="wsdlServiceElement" value="FXProviderImplService"/> <parameter name="wsdlServicePort" value="FXProvider"/> <parameter name="className" value="myAxis.FXProviderSoapBindingImpl"/> <parameter name="wsdlPortType" value="FXProviderImpl"/> <operation name="getPrice" qname="operNS:getPrice" xmlns:operNS="urn:FXProvider" returnQName="getPriceReturn" returnType="rtns:string" xmlns:rtns="http://www.w3.org/2001 /XMLSchema" > <parameter name="in0" type="tns:string" xmlns:tns="http://www.w3.org/2001/XMLSchema"/> <parameter name="in1" type="tns:string" xmlns:tns="http://www.w3.org/2001/XMLSchema"/> </operation> <parameter name="allowedMethods" value="getPrice"/> <parameter name="scope" value="Session"/> </service> </deployment> Step 6: Compile Stub/Skeleton into Java ClassesThe client stubs and the server skeletons need to be compiled into Java classes, as shown in Figure 9-12. Figure 9-12 Compiling the Client Stubs and the Server SkeletonsD:\Dev\mydemo\myAxis>cd myAxis D:\Dev\mydemo\myAxis\myAxis>javac *.java Step 7: Prepare for DeploymentTo prepare for Web Services deployment, copy the compiled classes into the Web Container's Axis class directory (see Figure 9-13). In this demo environment, Apache Axis can be found under the subdirectory myAxis of the Apache Axis class directory %JWSDP_HOME%\axis\ web-inf \classes. Figure 9-13 Preparing for Deployment by Copying the Classes to Web Container D:\Dev\mydemo\myAxis\myAxis> copy *.class d:\dev\wsdp\webapps\axis\web-inf\classes\myAxis\ Step 8: Deploy Web ServicesTo start the implementation, deploy the Web Services Deployment Descriptor (WSDD) generated earlier, as shown in Figure 9-14. The AdminClient will deploy the Web Services and the associated proxy and Java classes to the SOAP server run-time environment. Figure 9-14 Deploying Web Services With WSDD D:\Dev\mydemo\myAxis\myAxis> java org.apache.axis.client.AdminClient deploy.wsdd - Processing file deploy.wsdd - <Admin>Done processing</Admin> Step 9: Verify Web Services DeployedUpon successful deployment, you can verify the Web Services deployment by entering either one of the following URLs. The first URL http://localhost:8080/axis/services/FXProvider should confirm the service is deployed using the Axis engine (see Figure 9-15). The second URL http://localhost:8080/axis/services/FXProvider?WSDL should return a WSDL that is identical to the WSDL generated in earlier steps (see Figure 9-16). This also confirms that the Web Service FX Provider is deployed and appropriate Java classes are deployed under the Axis class directory. Figure 9-15. Verifying Web Services by Checking the Service End-Point URL
Concluding RemarksApache Axis has the capability to generate stubs (client modules) and skeletons (server modules) that is comparable to Java Web Service Developer Pack (JWSDP)'s wscompile . It does, however, have different design objectives and usage than JWSDP. It has a wider range of functionality to be the next generation of SOAP engines. Thus, both products complement each other in developing and implementing Web Services solutions. It is amazing to see how these Open Sources and publicly available tools evolve speedily to support the next frontiers of Web Services technology. 9.4.3 References
|