Tutorial 1

  • December 2019
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Tutorial 1 as PDF for free.

More details

  • Words: 5,722
  • Pages: 21
Asif Akram; [email protected]

1

Converting HelloWorld Web Service into WSRF based HelloWorld Version: 1.2 Date 10/03/06 Web Services are stateless, they can’t differentiate different service calls from same client or different service calls from different clients. This is understandable as most of Web Services using SOAP on http, which is traditionally stateless. It is not necessary to use to http protocol for Web Services at least what the specifications says but nearly all web services are based on http, the reason is to accommodate our existing knowledge of J2EE or .Net. Using Java Servlet, Java Server Pages or Active Server Pages to make stateless Web Services, statefull Web Services is not a rocket science, developers can extend web services in all possible ways by using proven techniques of session handling to make them statefull but this kills the main purpose of Web Services, platform and programming independency. Unique things in Web Services are Standards and in these already recognised standards there is no place for home grown solutions; at least we should give try to standards rather than reinventing the wheel. Web Service Resource Frame Work WSRF is one of the standards, which extends stateless Web Services using existing Web Service extensions such as WS-Addressing, WS-Notification, WS-Policy and WS-Security. You don’t need to know all of them, you are free to use only those standards which meet your requirements and if you know none of them then this series of tutorials will attempt to clear the usefulness of them. This first tutorial is about converting stateless Web Service into WSRF. Following the conventions we start with HelloWorld example. This tutorial assumes that reader has enough knowledge of Web Services, Java Programming and XML. These tutorials are based on Globus Toolkit 4, WS core component, which itself is tightly coupled with Axis, so knowledge of Web Service in general and Axis Web Service in particular is essential. If you are new to Web Services or Axis Web Services than there are enough tutorials available online and many books are available on this topic. I will not spend time in covering Web Services in fact I will refer to different web sites for better understanding. • Web Services:  http://www.phptr.com/content/images/0131428985/samplechapter/0131428985_ch03.pdf  http://today.java.net/today/2003/11/05/ch4SOAP.pdf • Axis Web Services:  http://ws.apache.org/axis/java/user-guide.html  

http://www.sourcebeat.com/docs/Apache%20Axis%20Live/Rev_5/Apache%20Axis%20Live_SampleChapter.pdf

http://www.j2ee-security.net/book/dnlds/Chapter11-WebService_Security.pdf

These tutorials have borrowed ideas from the following Globus and WSRF tutorials.  http://gdp.globus.org/gt4-tutorial/  https://www6.software.ibm.com/developerworks/education/gr-wsrf1/gr-wsrf1-a4.pdf  https://www6.software.ibm.com/developerworks/education/gr-wsrf2/gr-wsrf2-a4.pdf  https://www6.software.ibm.com/developerworks/education/gr-wsrf3/gr-wsrf3-a4.pdf  https://www6.software.ibm.com/developerworks/education/gr-wsrf4/gr-wsrf4-a4.pdf WS-Notification: This tutorial is not Globus Toolkit based but it is very helpful to understand WS-Notification and to write your own WSRF implementation, the ideas represented here can be extended to any WS sepecifications 

http://www-128.ibm.com/developerworks/grid/library/gr-ws-not/

If you find following tutorials helpful then credit goes to writers of above mentioned tutorials and if my tutorials haven’t addressed your requirements then it was due to my limited knowledge.

WSRF Based Hello World Web Service

Asif Akram; [email protected]

2

Simple HelloWorld Web Service We start understanding WSRF by creating very simple Web Service which echoes “Hello ….!”, …. are replaced by the name passed to echo method. This Web Service is very simple java class called HelloWorld.java in the package uk.ac.dl.ws.service. package uk.ac.dl.ws.service; public class HelloWorld { public String echo(String name){ return "Hello " + name + " !"; } } This Web Service is self explanatory and assuming that Tomcat is running on local machine with Axis i.e. SOAP Engine, we have to deploy this Web Service. To deploy Web Service through Axis needs deployment descriptor which is simply xml file with extension wsdd; wsdd stands for Web Service Deployment Descriptor. Deployment descriptor provides all information to Axis engine and can be quite complicated. For simple Web Services such as our Web Service deployment descriptor is very simple. ?xml version="1.0" encoding="UTF-8"?> <deployment name="defaultClientConfig" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java" xmlns:handler="http://xml.apache.org/axis/wsdd/providers/handler" xmlns="http://xml.apache.org/axis/wsdd/"> <service name="HelloWorldService" type="" regenerateElement="true" provider="java:RPC" style="rpc" use="encoded"> <parameter name="scope" value="Request" regenerateElement="false"/> <parameter name="className" value="uk.ac.dl.ws.service.HelloWorld" regenerateElement="false"/> <parameter name="allowedMethods" value="*" regenerateElement="false"/> After deploying our Web Service axis will use its own build in tool java2WSDL to generate WSDL file, which explains how to access the Web Service and where it can be accessed. The WSDL file generated is below: (Note: WSDL below is using RPC/Encoded Web Service which is not recommended way. Generating Document /Literal or even Wrapped Document is just matter of different parameters for Java2WSDL) I will soon upload the article related to WSDL and Web Services styles which will clear everything. <wsdl:definitions targetNamespace="http://service.ws.dl.ac.uk" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://service.ws.dl.ac.uk" xmlns:intf="http://service.ws.dl.ac.uk" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"

WSRF Based Hello World Web Service

Asif Akram; [email protected]

3

xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <wsdl:message name="echoRequest"> <wsdl:part name="name" type="xsd:string"/> <wsdl:message name="echoResponse"> <wsdl:part name="echoReturn" type="xsd:string"/> <wsdl:portType name="HelloWorld"> <wsdl:operation name="echo" parameterOrder="name"> <wsdl:input message="impl:echoRequest" name="echoRequest"/> <wsdl:output message="impl:echoResponse" name="echoResponse"/> <wsdl:binding name="HelloWorldSoapBinding" type="impl:HelloWorld"> <wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="echo"> <wsdlsoap:operation soapAction=""/> <wsdl:input name="echoRequest"> <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://service.ws.dl.ac.uk" use="encoded"/> <wsdl:output name="echoResponse"> <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://service.ws.dl.ac.uk" use="encoded"/> <wsdl:service name="HelloWorldService"> <wsdl:port binding="impl:HelloWorldSoapBinding" name="HelloWorld"> <wsdlsoap:address location="http://localhost:8080/HelloWS130606/services/HelloWorld"/> This WSDL for our Web Service is very simple and needs no explanation but if you are new to WSDL or you have only used different tools to generate WSDL rather than working with WSDL directly than better to have look on the following link: 

http://www.oreilly.com/catalog/webservess/chapter/ch06.html

This link is from book Web Services Essentials, Distributed Applications with XML-RPC, SOAP, UDDI & WSDL by Ethan Cerami.

WSDL for WSRF HelloWorld

WSRF Based Hello World Web Service

Asif Akram; [email protected]

4

To convert this simple Web Service from stateless to statefull we have to make few changes. Changes will start from WSDL file and then changing the implementation of our HelloWorld.java class. Before making any changes it is important to understand that how we will store the state of our Web Service. We need one variable called “name” which will store the value passed to the echo method of our Web Service. This variable is Resource Property of our Web Service, this concept is very clearly and in detail explained by Borja Sotomayor in “The Globus Toolkit 4 Programmer’s Tutorial” under the section Getting Started. Remember your WSRF Web Service can have many Resource Properties and all of them are placed in ResourcePropertySet for later retrieval, modification and deletion. It is always nice to follow good naming conventions which are self explanatory, data type which will encapsulate all Resources of our WSRF Web Services will ends with “ResourcePropertiesSet” to indicate that it is ResourcePropertySet, all individual resources will ends with RP (Resource Property) to keep things clear and simple. Let starts with our WSDL file, our final WSDL file for our Web Service will be something similar to the WSDL file shown below. I have used the word final WSDL file which is too some extent wrong, this WSDL file is not complete and Globus WSRF Implementation will add “binding” and “service” information to this WSDL file but it is final from developers point of view as later he has nothing more to do with this file. This WSDL is bit different from above WSDL as WSRF used Document Literal style Web Services. <definitions name="HelloWorld" targetNamespace="http://tutorial1.wsrf.dl.ac.uk/helloworld" xmlns:tns="http://tutorial1.wsrf.dl.ac.uk/helloworld" xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd" xmlns:wsrlw="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.wsdl" xmlns:wsdlpp="http://www.globus.org/namespaces/2004/10/WSDLPreprocessor" xmlns:gtwsdl1="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ServiceGroup-1.2-draft-01.wsdl" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing" xmlns:wsntw="http://docs.oasis-open.org/wsn/2004/06/wsn-WS-BaseNotification-1.2-draft-01.wsdl" xmlns:wsrpw="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.wsdl" xmlns="http://schemas.xmlsoap.org/wsdl/"> <schema targetNamespace="http://tutorial1.wsrf.dl.ac.uk/helloworld" xmlns:tns="http://tutorial1.wsrf.dl.ac.uk/helloworld" xmlns="http://www.w3.org/2001/XMLSchema"

WSRF Based Hello World Web Service

Asif Akram; [email protected] xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <element name="name" type="xsd:string"/> <element name="getNameRPRequest" > <element name="getNameRPResponse" type="xsd:string"/> <element name="HelloWorldResourcePropertiesSet"> <sequence> <element ref="tns:name"/> <element name="echoRequest" type="xsd:string" /> <element name="echoResponse" type="xsd:string" />
<message name="EchoRequest"> <part name="EchoRequest" element="tns:echoRequest" /> <message name="EchoResponse"> <part name="EchoResponse" element="tns:echoResponse" /> <message name="GetNameRPRequest"> <part name="GetNameRPRequest" element="tns: getNameRPRequest " /> <message name="GetNameRPResponse"> <part name="GetNameRPResponse" element="tns:getNameRPResponse" /> <portType name="HelloWorldPortType" wsrp:ResourceProperties="HelloWorldResourcePropertiesSet">


WSRF Based Hello World Web Service

5

Asif Akram; [email protected]

6

wsa:Action="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties/GetResourcePropertyResponse"/>

This 2 page long WSDL file, which is still incomplete, is bit scary but in fact everything added in this file is very logical and has its own significance. Immediately after the starting tag <definitions> there are 5 import statement which are importing different WSDL files. We don’t need to import all these WSDL files for such a simple basic example but for ease and convenience I have imported all of them and put comments when they are required, in the following section I will discuss in detail the significance of each WSDL file and when it should be imported. In the schema element of types we are once again importing 2 files but this time they are not WSDL files in fact they are XMLSchema for different data types used in different WSDL files already imported. Thus in total, we have imported 7 different files. These files are available on internet and also come with Globus WS Core implementation; if you are interested to check these files than they are available in directory “GTInstall\share\schema\wsrf” (GTInstall is directory where you have installed Globus Toolkit). There are few changes in the WSDL file and we will discuss all these changes one by one: 1. Adding variable called “name” to store the value passed to echo (String name) method. Variable “name” and parameter “name” passed to echo method can be called anything and there is no need to have them same.  <element name="name" type="xsd:string"/> 2. Two data types added to WSDL file related to the one additional method which will be added later. These two complex data types are the following:  <element name="getNameRPRequest" >  <element name="getNameRPResponse" type="xsd:string"/> 3. Data Type “getNameRPRequest” seems to be bit odd; in reality it is empty, equivalent to void, or method call without any parameter. This is requirement of Document Literal style Web Services that each complex or simple type should be wrapped in elements. 4. Data Type “getNameRPResponse” is of type String as our method will return String, it can be of any built in or composite data type as required by business logic. 5. The most important part is to add data Type “HelloWorldResourcePropertiesSet”. This element wraps all variables (each WSRF related Resource Properties) in our service to be implemented as Resource Properties. Web Service can have many variables and few of them can be only utility variable required for the proper functionality of the Web Service and there is no need to store the state of these variables. Only those variables which have to do with the state of Web Service are wrapped in the composite variable, which is recommended to have ResourcePropertiesSet at the end of its name. Only convention, nothing to

WSRF Based Hello World Web Service

Asif Akram; [email protected]

7

do with actual implementation. In our case there is only one variable “name” which should be wrapped as resource property, therefore “HelloWorldResourcePropertiesSet” refers to variable “name”. 6. We have added new operation called “getNameRP” at the end of the WSDL file in the <portType> element. This is custom element which will return the current value of variable “name”. This operation takes no parameter that’s why “getNameRPRequest” is empty and returns String as indicated by "getNameRPResponse". 7. Related to the operation “getNameRP” we have corresponding messages i.e. GetNameRPRequest, GetNameRPResponse, it is important to mention operation works on messages and message wraps different elements defined in types. 8. The most important change which is must and to some extent the same for all WSRF implementations is to add operation "GetResourceProperty", the messages involved in this operation are already defined in the “wsrf-WS-ResourceProperties-1.2-draft-01.wsdl” so we don’t have to do anything special and even the implementation of this operation is very simple, we have to provide implementation to this operation. 9. We have related “GetResourceProperty" operation with our custom resource property and in this Web Service it is "HelloWorldResourcePropertiesSet". These two are linked in the element “<portType>” with the attribute “wsrp:ResourceProperties”. <portType name="HelloWorldPortType wsrp:ResourceProperties="HelloWorldResourceProperties"> For its inner details refer to Borja Sotomayor’s tutorial section WSRF and Globus-specific features of WSDL. 10. The last few changes are to delete the details of “binding” and “service” from existing WSDL file. These are the all changes we need to make to our WSDL files. My preferred style is to write Web Service and generate WSDL file using jave2WSDL and then modify the WSDL file to make it WSRF WSDL file. I am currently working on tool to create WSRF WSDL file from existing WSDL file based on user input for my own work. When I will finish it depends on how much desperate I am from any such tool, and how many other programmers are interested in such a tool. If you are interested in any such tool and feel that it will be helpful for whole community then do mail me. It will speed up the process.

HelloWorld WSRF Implementation Now we have to change our HelloWorld.java class. Initially we are going to change our implementation without any additional java class, which is not recommended way and kills the purpose of OO, but for convenience we will follow this path, later we will separate them in different classes as done in the “StickyNote” example which comes with Globus Toolkit or can be downloaded separately. 1. First of all we have to import couple of classes which are part of Globus WSRF implementation and few classes which don’t exist. Classes which don’t exist ..? Yes! these are classed generated by Globus WSRF implementation when we will parse our WSDL file, compile HelloWorld.java and deploy it to the server. These additional classes are very similar to stubs and skeletons created by Axis Engine and in fact are tightly coupled to Axis.  import java.rmi.RemoteException;  import javax.xml.namespace.QName;  import org.globus.wsrf.Resource;  import org.globus.wsrf.ResourceProperties;  import org.globus.wsrf.ResourceProperty;  import org.globus.wsrf.ResourcePropertySet;  import org.globus.wsrf.impl.ReflectionResourceProperty;  import org.globus.wsrf.impl.SimpleResourcePropertySet;  import uk.ac.dl.wsrf.tutorial1.helloworld.*; Be sure about the last import statement, these are classes in the new package which matches the target namespace mentioned in our WSDL file. targetNamespace="http://tutorial1.wsrf.dl.ac.uk/helloworld"

WSRF Based Hello World Web Service

Asif Akram; [email protected]

8

We can change this mapping from this “targetNamespace” to any required package by providing a simple text file called NStoPkg.properties, which, I have avoided in this simple tutorial.

2. 3.

4. 5.

Package uk.ac.dl.wsrf.tutorial.helloworld.* has few classes which are used by client and service both, If you remember when we were changing the WSDL file, I talked about wrapper to represent void and empty parameter to method call. Our both methods echo() and getNameRP() return String but getNameRP() doesn’t take any parameter and this is wrapped in the empty dataType "getNameRPRequest". Stub will be created representing this data type and the name of stub generated is GetNameRPRequest.java. It is important to understand as you have to import the related classes which are still not available and you should know the location and name of these classes by analysing the modified WSDL file at the time when Web Service is implemented. HelloWorld.java implements Resource, ResourceProperties, which is requirement. public class HelloWorld implements Resource, ResourceProperties { …} We need one set which will manage all related resource properties of our Web Service. In this example we have only one resource property but still we need ResourcePropertySet and we need it for all of our WSRF Web Services. /* Resource Property set */ private ResourcePropertySet propSet; Now we have to declare the variable “name” of type String which represents Resource Property of our Web Service. It is not necessary to have this name as it is in the WSDL file. In the constructor of our Web Service we will initialize the ResourcePropertySet and our Resource Property “name”. public HelloWorld() throws RemoteException { /* Create RP set */ this.propSet = new SimpleResourcePropertySet( new QName("http://tutorial1.wsrf.dl.ac.uk/helloworld", "HelloWorldResourcePropertiesSet")); /* Initialize the RP's */ try { ResourceProperty nameRP = new ReflectionResourceProperty( new QName("http://tutorial1.wsrf.dl.ac.uk/helloworld", "name"), "name", this); this.propSet.add(nameRP); setName("Asif"); // this is set method for private variable name } catch (Exception e) { throw new RuntimeException(e.getMessage()); } } Let see what is happening in the constructor. This is the ugliest way to implement WSRF, but I want to keep my words of doing everything in single java class. I am sure it will hurt OO purist very badly, but trust me it is also hurting me a lot, but my main purpose is to clear the concept of WSRF as easily as possible, soon we will start working on WSRF with OO techniques, best of both world. We have initialized the “propSet” as object of SimpleResourcePropertySet, you may have figured out that ResourcePropertySet is interface and SimpleResourcePropertySet is concrete implementation of ResourcePropertySet. Constructor of SimpleResourcePropertySet takes QName i.e. the qualified name of our resource property as declared in the WSDL file. Similarly ResourceProperty is an interface and ReflectionResourceProperty is one of its implementation used to declare and create variable nameRP (name Resource Property). ReflectionResourceProperty has three different constructors and the constructor used in the above example is: ReflectionResourceProperty(QName name, String propertyName, Object obj), QName should match the qualified name in the WSDL and

WSRF Based Hello World Web Service

Asif Akram; [email protected]

9

String propertyName is the name of variable in our implementation. It can be called anything like myName. Now we have to add this newly created ResourceProperty into our ResourcePropertySet, this.propSet.add(nameRP) and then assign initial value by calling utility set method for private variable name. 6. If you remember we have three operations in our WSDL file two declared by us for custom business logic and one from imported WSDL file. It means along with different get/set methods for our different private variables we have to provide public implementation of these three operations, which is trivial task. Below is the implementation of our all three operations: public String echo(String name) { setName(name); // this is important. return "Hello " + name + " !"; } public String getNameRP(uk.ac.dl.wsrf.tutorial1.helloworld .GetNameRP params) throws RemoteException {

return name; } /* Required by interface ResourceProperties */ public ResourcePropertySet getResourcePropertySet() { return this.propSet; } All three methods are self-explanatory, the most important thing is to implement getResourcePropertySet() which is declared in the interface ResourceProperties implemented by our Web Service.

WSRF Based Hello World Web Service

Asif Akram; [email protected] Complete implementation of HelloWorld.java is shown below: import java.rmi.RemoteException; import javax.xml.namespace.QName; import org.globus.wsrf.Resource; import org.globus.wsrf.ResourceProperties; import org.globus.wsrf.ResourceProperty; import org.globus.wsrf.ResourcePropertySet; import org.globus.wsrf.impl.ReflectionResourceProperty; import org.globus.wsrf.impl.SimpleResourcePropertySet; import uk.ac.dl.wsrf.tutorial1.helloworld.*; public class HelloWorld implements Resource, ResourceProperties { /* Resource Property set */ private ResourcePropertySet propSet; /* Resource properties */ private String name; public HelloWorld() throws RemoteException { /* Create RP set */ this.propSet = new SimpleResourcePropertySet( new QName("http://tutorial.wsrf.dl.ac.uk/helloworld", "HelloWorldResourceProperties")); /* Initialize the RP's */ try { ResourceProperty nameRP = new ReflectionResourceProperty( new QName("http://tutorial.wsrf.dl.ac.uk/helloworld", "name"), "name", this); this.propSet.add(nameRP); setName("Asif"); // this is set method for private variable name } catch (Exception e) { throw new RuntimeException(e.getMessage()); } } public String getName() { return name; } public void setName(String name) { this.name = name; } public String echo(String name) { setName(name); return "Hello " + name + " !"; } public String getNameRP(uk.ac.dl.wsrf.tutorial1.helloworld .GetNameRP params) throws RemoteException {

return name; } /* Required by interface ResourceProperties */

WSRF Based Hello World Web Service

10

Asif Akram; [email protected]

11

public ResourcePropertySet getResourcePropertySet() { return this.propSet; } }

WSDD for HelloWorld WSRF Have we finished our first WSRF Web Service? Not yet … Don’t forget we need Axis Engine dependent Deployment Descriptor to deploy our Web Service. There are not too many changes in the initial WSDD and the modified WSDD. <deployment name="defaultServerConfig" xmlns="http://xml.apache.org/axis/wsdd/" xmlns:aggr="http://mds.globus.org/aggregator/types" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <service name="HelloWorldService" provider="Handler" use="literal" style="document"> <parameter name="providers" value="GetRPProvider"/> <parameter name="handlerClass" value="org.globus.axis.providers.RPCProvider"/> <parameter name="scope" value="Application"/> <parameter name="allowedMethods" value="*"/> <parameter name="activateOnStartup" value="true"/> <parameter name="className" value=" uk.ac.dl.ws.service.HelloWorld "/> <wsdlFile>share/schema/tutorial/HelloWorld_service.wsdl Important <wsdlFile>…. stops Axis to replacing WS-Core generated WSDL with its own WSDL file which is collection of problems uses its own encoding style which has interoperability problems . Main difference is that we are using Globus Toolkit provided handler. Handlers are java classes which are involved in pre and post handling of request and response from Web Service. If you are new to idea of Handlers in Axis then best to read the sample chapter “Custom Handlers in AXIS” from one of great Axis Web Service book “AXIS: Next Generation Java SOAP“ by Romin Irani, S Jeelani Basha. 

http://archive.devx.com/java/wrox/7159_chap04.pdf

Second change is to make it clear that we are using default implementation of GetRPProvider, provided by Globus implementation. <parameter name="providers" value="GetRPProvider"/>

deploy-jndi for HelloWorld WSRF The last thing we need is “deploy-jndi-config.xml”. This file is related to Tomcat Server and tells the server about the services and the class which provides the detail of services. This file is very simple as we are using custom implementation provided by Globus to wrap our WSRF Web Service. This may be bit confusing but it will be clear in the later tutorials. <jndiConfig xmlns="http://wsrf.globus.org/jndi/config"> <service name="HelloWorldService"> <parameter> factory org.globus.wsrf.jndi.BeanFactory

WSRF Based Hello World Web Service

Asif Akram; [email protected]

12

If you are confused about role of this file then you can read about this on official web site of Tomcat Server.

WSRF HelloWorld Client Last thing to do is to write Client to test our WSRF Web Service. Below is the complete code of Client.java followed by discussion of important parts, notice that Client.java is in package “uk.ac.dl.ws.service.client” and our service HelloWorld.java is in package “package uk.ac.dl.ws.service”. This is not the requirement of WSRF or Globus implementation of WSRF, in fact it is restriction due to the Ant “build.xml” file which will be used later to generate stubs, compile service and deploy to the container. You can change “build.xml” to adjust changes made in your package structure. We have to put all java classes and additional files like WSDL and “deploy-jndiconfig.xml” in specific directories as required by Ant “build.xml”. Ant “build.xml” is so handy and useful that following few restrictions is still worthy, as it hides all dirty work of setting class path, copying files from different locations and above all making all imported files in our WSDL available to our WSDL file. package uk.ac.dl.ws.service.client; import org.apache.axis.message.MessageElement; import org.apache.axis.message.Text; import org.apache.axis.types.URI; import org.apache.commons.cli.ParseException; import org.apache.commons.cli.CommandLine; import org.oasis.wsrf.properties.WSResourcePropertiesServiceAddressingLocator; import org.oasis.wsrf.properties.GetResourceProperty; import org.oasis.wsrf.properties.GetResourcePropertyResponse; import org.oasis.wsrf.properties.QueryResourceProperties_Element; import org.oasis.wsrf.properties.QueryResourcePropertiesResponse; import org.oasis.wsrf.properties.QueryResourceProperties_PortType; import org.oasis.wsrf.properties.QueryExpressionType; import org.globus.wsrf.WSRFConstants; import org.globus.wsrf.client.BaseClient; import org.globus.wsrf.utils.AnyHelper; import org.globus.wsrf.utils.FaultHelper; import javax.xml.namespace.QName; import javax.xml.rpc.Stub; import uk.ac.dl.wsrf.tutorial1.helloworld.service.*; import uk.ac.dl.wsrf.tutoria1l.helloworld.*; public class Client1 extends BaseClient { final static WSResourcePropertiesServiceAddressingLocator locator =

WSRF Based Hello World Web Service

Asif Akram; [email protected]

13

new WSResourcePropertiesServiceAddressingLocator(); public static void main(String[] args) { Client1 client = new Client1 (); // first, parse the commandline try { CommandLine line = client.parse(args); } catch (ParseException e) { System.err.println("Parsing failed: " + e.getMessage()); System.exit(1); } catch (Exception e) { System.err.println("Error: " + e.getMessage()); System.exit(1); } try { GetResourceProperty port = locator.getGetResourcePropertyPort(client.getEPR()); client.setOptions( (Stub) port); GetResourcePropertyResponse response = port.getResourceProperty(new QName("http://tutorial.wsrf.dl.ac.uk/helloworld", "name")); System.out.println(AnyHelper.toSingleString(response)); uk.ac.dl.wsrf.tutorial1.helloworld.service.HelloWorldServiceAddressingLocator mylocator = new uk.ac.dl.wsrf.tutorial1.helloworld.service.HelloWorldServiceAddressingLocator(); uk.ac.dl.wsrf.tutoria1l.helloworld.HelloWorldPortType myPort = mylocator.getHelloWorldPortTypePort (client.getEPR()); String result = myPort.echo("Rob Allan"); response = port.getResourceProperty new QName("http://tutorial.wsrf.dl.ac.uk/helloworld", "name")); System.out.println(AnyHelper.toSingleString(response)); } catch (Exception e) { if (client.isDebugMode()) { FaultHelper.printStackTrace(e); } else { System.err.println("Error: " + FaultHelper.getMessage(e)); } } } } Implementation once again starts with importing couple of Globus dependent java classes along with importing few classes which are not yet available and will created by Ant build file. One of them is to locate the our Web

WSRF Based Hello World Web Service

Asif Akram; [email protected]

14

Service ”HelloWorldServiceAddressingLocator” which is in package “uk.ac.dl.wsrf.tutorial.helloworld.service” and the “HelloWorldPortType” which is the interface with all three methods available in our main Web Service. “HelloWorldPortType” is available in the package “import uk.ac.dl.wsrf.tutorial.helloworld”. Our client implementation is using two different approaches to get hold of stub to communicate with Web Service i.e. first we are using Globus provided class WSResourcePropertiesServiceAddressingLocator through which we obtain generic stub GetResourceProperty, limitation of this approach is that we can only access one method which must be implemented by the Web Service that’s is getResourceProperty() as shown in following code fragment; WSResourcePropertiesServiceAddressingLocator locator= new WSResourcePropertiesServiceAddressingLocator(); GetResourceProperty port = locator.getGetResourcePropertyPort(client.getEPR()); port.getResourceProperty(……….); Second approach is to use HelloWorldServiceAddressingLocator to create custom stub HelloWorldPortType, through this stub we have access to all operations exposed by WSDL as shown in following code fragment; HelloWorldServiceAddressingLocator mylocator = new HelloWorldServiceAddressingLocator(); HelloWorldPortType myPort = mylocator.getHelloWorldPortTypePort (client.getEPR()); String result = myPort.echo("Rob Allan"); Now everything is available and we have to build the WSRF Web Service. For build purposes we will use build tool “ANT” and the build.xml provided by the Globus. To make life easy to test web service we need last file “post-deploy.xml“ which will create script to run the client, without setting class path, without worrying about the generated stubs and location of compiled stubs. This xml file is generated when everything goes well, below are the contents of file “post-deploy.xml”. <project default="all" basedir="."> <property environment="env"/> <property file="build.properties"/> <property file="${user.home}/build.properties"/> <property name="env.GLOBUS_LOCATION" value="."/> <property name="deploy.dir" location="${env.GLOBUS_LOCATION}"/> <property name="abs.deploy.dir" location="${deploy.dir}"/> <property name="build.launcher" location="${abs.deploy.dir}/share/globus_wsrf_common/build-launcher.xml"/> <property name="launcher-name" value="helloworld"/> <property name="class.name" value="uk.ac.dl.ws.service.client.Client"/> This file is quite simple, and most of time remains same for most of clients. There are two adjustments to be made for each client and location of those adjustments is shown in bold. Name of the generated script: <property name="launcher-name" value="helloworld"/> and location and name of java client of WSRF Web Service. In our case client is “Client1.java” in package “uk.ac.dl.ws.service.client”. Now we have to use Ant build file, but that Ant file also needs few changes related to our Web Service. These changes are very small and are the last step required to finish the whole implementation.

WSRF Based Hello World Web Service

Asif Akram; [email protected] I have copied the complete build file and highlighted the changes: <project basedir="." default="all" name="globus_tutorial_helloworld"> <property environment="env"/> <property file="build.properties"/> <property file="${user.home}/build.properties"/> --> <property location="${env.GLOBUS_LOCATION}" name="deploy.dir"/> <property name="base.name" value="tutorial_helloworld"/> <property name="package.name" value="globus_${base.name}"/> <property name="jar.name" value="${package.name}.jar"/> <property name="gar.name" value="${package.name}.gar"/> <property location="build" name="build.dir"/> <property location="build/classes" name="build.dest"/> <property location="build/lib" name="build.lib.dir"/> <property location="build/stubs" name="stubs.dir"/> <property location="build/stubs/src" name="stubs.src"/> <property location="build/stubs/classes" name="stubs.dest"/> <property name="stubs.jar.name" value="${package.name}_stubs.jar"/> <property location="${deploy.dir}/share/globus_wsrf_common/build-packages.xml" name="build.packages"/> <property location="${deploy.dir}/share/globus_wsrf_tools/build-stubs.xml" name="build.stubs"/> <property name="java.debug" value="on"/> <property name="test-reports.dir" value="test-reports"/> <property name="junit.haltonfailure" value="true"/> <property location="${deploy.dir}/share/schema" name="schema.src"/> <property location="${build.dir}/schema" name="schema.dest"/> <property name="garjars.id" value="garjars"/> <property name="garschema.id" value="garschema"/> <property name="garetc.id" value="garetc"/>

<mkdir dir="${build.dir}"/> <mkdir dir="${build.dest}"/> <mkdir dir="${build.lib.dir}"/>

WSRF Based Hello World Web Service

15

Asif Akram; [email protected] <mkdir dir="${stubs.dir}"/> <mkdir dir="${stubs.src}"/> <mkdir dir="${stubs.dest}"/> <mkdir dir="${schema.dest}"/>
<property name="source.binding.dir" value="${schema.dest}/tutorial"/> <property name="target.binding.dir" value="${schema.dest}/tutorial"/> <property name="binding.root" value="HelloWorld"/> <property name="porttype.wsdl" value="helloworld_port_type.wsdl"/> <property location="${schema.dest}/tutorial" name="source.stubs.dir"/> <property name="wsdl.file" value="HelloWorld_service.wsdl"/> <property location="${stubs.src}" name="target.stubs.dir"/>

<delete dir="${stubs.src}/org/apache"/> <javac debug="${java.debug}" destdir="${stubs.dest}" srcdir="${stubs.src}">

WSRF Based Hello World Web Service

16

Asif Akram; [email protected]
<javac debug="${java.debug}" destdir="${build.dest}" srcdir="src"> <pathelement location="${stubs.dest}"/> <jar basedir="${stubs.dest}" destfile="${build.lib.dir}/${stubs.jar.name}"/>

<jar basedir="${build.dest}" destfile="${build.lib.dir}/${jar.name}"/> <property name="gar.name" value="${build.lib.dir}/${gar.name}"/> <delete dir="tmp"/> <delete dir="${build.dir}"/> <delete file="${gar.name}"/> <delete dir="${test-reports.dir}"/> <property name="gar.name" value="${build.lib.dir}/${gar.name}"/> <property name="gar.id" value="${package.name}"/> <property name="gar.id" value="${package.name}"/>

WSRF Based Hello World Web Service

17

Asif Akram; [email protected]

18

<mkdir dir="${test-reports.dir}"/> <junit fork="yes" haltonfailure="${junit.haltonfailure}" printsummary="yes" timeout="600000"> <pathelement location="${build.dest}"/> <pathelement location="${deploy.dir}"/> <pathelement location="${deploy.dir}/etc/wsrf-bundles.properties"/> Important: Few important things about this the ant script. Project name is used to create the jar and gar files. Value for property binding.root in target bindings i.e. <property name="binding.root" value="HelloWorld"/> is used as value for property wsdl.file in target stubs i..e. <property name="wsdl.file" value="HelloWorld_service.wsdl"/> with suffix “_service.wsdl”.

Now we have all required java files and configuration files, but before we can run Ant script we have to put them at proper location where Ant build can locate them. HelloWorld140605/source is the main directory containing all files under one umbrella: 1. Web Service implementation HelloWorld.java will be in the directory structure according to package statement i.e. “HelloWorld140605\source\src\uk\ac\dl\ws\service” (1) 2. Client1.java will be the directory “HelloWorld140605\source\src\uk\ac\dl\ws\service\client” (2). 3. WSDL file “helloworld_port_type.wsdl” is located at “HelloWorld140605\source\schema\tutorial” indicated by (3) 4. Source directory (4) contains “deploy-server.wsdd”, “deploy-jndi-config.xml” and “build.xml”. 5. File “post-deploy.xml”, which; is used for creating client script is in directory “HelloWorld140605\source\etc” (5). 6. “build” directory will be created on successful stub generation and stores compiled classes and jar files for the WSRF project

WSRF Based Hello World Web Service

Asif Akram; [email protected]

19

4 5 3

1 2 I am using Windows Operating System and have installed only WS-Core component of Globus Toolkit. You have to set an environment variable called GLOBUS_LOCATION referencing the installation of Globus Toolkit. In my case it is: set GLOBUS_LOCATION= E:\GlobusWeek\gt-install Open two Command Prompt one for starting Globus Tomcat Server and other for deploying Web Service and testing client. In one Window go to directory “E:\GlobusWeek\gt-install” and run command, bin\globus-start-container –nosec which will start the container. On second window go to directory E:\GlobusWeek\HelloWorld140605\source and run build file to create stubs, compile all java files, and deploy Web Service. ant clean ant deploy If everything goes fine then after 10 seconds you will see the final outcome similar to: generateWindows: [echo] Creating Windows launcher script helloworld [copy] Copying 1 file to E:\GlobusWeek\gt-install\bin [delete] Deleting: E:\GlobusWeek\HelloWorld140605\source\tmp\gar\etc\post-deploy.xml [delete] Deleting directory E:\GlobusWeek\HelloWorld140605\source\tmp\gar BUILD SUCCESSFUL Total time: 8 seconds

If you remember in the file “post-deploy.xml” we have mentioned helloworld as name of script to be generated to run the client, which is confirmed by the final outcome of the Ant build file. Now it is time to run the client: %GLOBUS_LOCATION%\bin\helloworld -s http://localhost:8080/wsrf/services/HelloWorldService <ns1:name xmlns:ns1="http://tutorial1.wsrf.dl.ac.uk/helloworld">Asif <ns1:name xmlns:ns1="http://tutorial1.wsrf.dl.ac.uk/helloworld">Rob Allan “Asif “ is the initial value assigned to our variable “name” and “Rob Allan” is the value assigned to variable “name” from “Client1.java”. If you will run the script again then the out come will be: %GLOBUS_LOCATION%\bin\helloworld -s http://localhost:8080/wsrf/services/HelloWorldService <ns1:name xmlns:ns1="http://tutorial1.wsrf.dl.ac.uk/helloworld"> Rob Allan <ns1:name xmlns:ns1="http://tutorial1.wsrf.dl.ac.uk/helloworld">Rob Allan

When we are running the client script for second time, our name variable has already value “Rob Allan” and we are assigning the same value again, due to which it has printed “Rob Allan” both times. “helloworld” script is calling the service 3 times, and if you see the SOAP messages then there are 3 calls, twice we are calling “getResourceProperty(..)” and once we are calling “echo()” method. Call to “echo()” method is simple SOAP call, below is the SOAP request and SOAP response from “getResourceProperty(..)” and “echo()” method. There is nothing too much complicated happening here. Most important thing to remember is that each resource in WSRP has unique ID which along with the URL of Web Service is called End Point Reference. In this

WSRF Based Hello World Web Service

Asif Akram; [email protected]

20

simple example, for all clients there is only one copy of the resource. In other words clients are sharing the resource but if multiple copies of the resource are possible then each copy will have unique ID which we will see in the later examples. When clients make a request, it sends its URL or location where Web Service can send the response. “http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymous” is special instruction to Web Service indicating that there is no real endpoint available for this address and to keep the “http” connection open and use the same connection to send the response, which means we can have synchronously or asynchronously web services. Client sends the SOAP Request and SOAP Response can be sent to the URL provided, therefore client doesn’t have to wait for the response, which is non-blocking call. Even the request can be sent to any other URL provided by the client. Requester and Receiver can be different. More on this later, when, we will see the WS-Addressing Specification in more detail. To understand the purpose and reason behind this new specification WS-Addressing there is a tutorial by Doug Davis on IBM website. 

http://www-106.ibm.com/developerworks/library/ws-address.html

Below is the table showing SOAP Request and SOAP Response to both methods in tabular form. I have done little editing to fit them in single table and two columns. SOAP Request <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"> <soapenv:Header> <wsa:MessageID soapenv:mustUnderstand="0"> uuid:881ab1f0-dcc1-11d9-ae7c-b8ea2ebe6b67 <wsa:To soapenv:mustUnderstand="0"> http://localhost:8082/wsrf/services/HelloWorldService <wsa:Action soapenv:mustUnderstand="0"> http://docs.oasis-open.org/wsrf/2004/06/wsrf-WSResourceProperties/GetResourceProperty <wsa:From soapenv:mustUnderstand="0"> <wsa:Address> http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymous <soapenv:Body> ns1:name <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"> <soapenv:Header> <wsa:MessageID soapenv:mustUnderstand="0"> uuid:88c65b40-dcc1-11d9-ae7c-b8ea2ebe6b67 <wsa:To soapenv:mustUnderstand="0">

Soap Response <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"> <soapenv:Header> <wsa:MessageID soapenv:mustUnderstand="0"> uuid:88709a20-dcc1-11d9-b359-f53ae5575587 <wsa:To soapenv:mustUnderstand="0"> http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymous

<wsa:Action soapenv:mustUnderstand="0"> http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-Resource Properties/GetResourcePropertyResponse <wsa:From soapenv:mustUnderstand="0"> <wsa:Address> http://localhost:8082/wsrf/services/HelloWorldService <wsa:RelatesTo RelationshipType="wsa:Reply" soapenv:mustUnderstand="0"> uuid:881ab1f0-dcc1-11d9-ae7c-b8ea2ebe6b67 <soapenv:Body> <ns1:name xmlns:ns1="http://tutorial1.wsrf.dl.ac.uk/helloworld"> Asif <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"> <soapenv:Header> <wsa:MessageID soapenv:mustUnderstand="0"> uuid:88c8cc40-dcc1-11d9-b359-f53ae5575587 <wsa:To soapenv:mustUnderstand="0">

WSRF Based Hello World Web Service

Asif Akram; [email protected] http://localhost:8082/wsrf/services/HelloWorldService <wsa:Action soapenv:mustUnderstand="0">

21 http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymous <wsa:Action soapenv:mustUnderstand="0"> http://tutorial1.wsrf.dl.ac.uk/helloworld/HelloWorldPortType/EchoResponse

http://tutorial1.wsrf.dl.ac.uk/helloworld/HelloWorldPortType/EchoRequest <wsa:From soapenv:mustUnderstand="0"> <wsa:Address> http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymous <soapenv:Body> <echoRequest xmlns="http://tutorial1.wsrf.dl.ac.uk/helloworld"> Rob Allan

<wsa:From soapenv:mustUnderstand="0"> <wsa:Address> http://localhost:8082/wsrf/services/HelloWorldService <wsa:RelatesTo RelationshipType="wsa:Reply" soapenv:mustUnderstand="0"> uuid:88c65b40-dcc1-11d9-ae7c-b8ea2ebe6b67 <soapenv:Body> <echoResponse xmlns="http://tutorial1.wsrf.dl.ac.uk/helloworld"> Hello Rob Allan !

Note: QName in HelloWorld.java and Client1.java should be same, otherwise it will be error, surprisingly if QName in HelloWorld.java and WSDL are different, client still works. My understanding is all three should be exactly same, better to test again before conclusion.

WSRF Based Hello World Web Service

Related Documents

Tutorial 1
October 2019 23
Tutorial 1
October 2019 28
Tutorial 1
December 2019 18
Tutorial 1
June 2020 9
Tutorial 1
June 2020 12
Tutorial 1
April 2020 10