skip to main content

developerWorks  >  Grid computing | SOA and Web services  >

Resource Sharing among multiple Web Services, Part 1: Resource Sharing using Implied Resource Pattern

developerWorks
Page 1 of 11Go to the next page

Document options
PDF format - A4

PDF - A4
45KB (9 pages)

PDF format - letter

PDF - Letter
45KB (10 pages)

Get Adobe® Reader®

Sample code


Rate this tutorial

Help us improve this content


Level: Intermediate

Asif Akram (a.akram@dl.ac.uk), Software Developer, CCLRC Daresbury Laboratory, United Kingdom

24 Oct 2005

Different Web Services can work on same resource to expose different operations according to the business logic. For example in any typical Grid Application, Administrator uses different Web Services to manage the "User Accounts" where he can modify different parameters related to any user account, add new user accounts or delete existing user accounts; whereas Users use different Web Services to manage limited set of properties related to their own accounts only. There can be another general purpose Web Services to query the user accounts with read only privileges. Each Web Services exposes different operations related to same Resource/s rather than each Web Services working on their own set of Resources which can lead to update anomalies or synchronization issues.

Before you start

This tutorial explains the implementation details of sharing stateful resource utilizing implied resource pattern. Readers should have basic understanding of WSRF specifications and thorough understanding of Web Services and Web Service Definition Language (WSDL). It is recommended that readers must have gone through the tutorials mentioned in the "Resources Section". This tutorial assumes conceptual familiarity of reader with WS-Addressing specification. If you are new to the field of Web Services and Grid Services, then please do read 4-Part Series on Understanding WSRF on IBM Developerworks by Babu Sundaram.

About this series

In this two part series we will discuss the conceptual requirement of Resource sharing followed by implementation details along with various configuration files and deployment descriptors specific to WS-Core and Axis. The concepts presented in this series are applicable to all other WSRF implementations.

The implementation details are based on the implied resource pattern; where the client invokes Factory Service to create the instance of the stateful resource, which returns the Endpoint Reference (EPR) of the resource along with the Uniform Resource Locator (URL) of the Instance Service which manages stateful Resource. The EPR returned by the Factory Service is according to the WS-Addressing specifications.



Back to top


About this tutorial

In this tutorial two Instance Services (i.e. Services with the business logic) are implemented which share the same resource. Each of the Instance Service exposes different methods related to the common stateful resource. One Factory Service is deployed twice to instantiate single resource to be managed by each of the Instance Service. It lays the groundwork for Part 2 , which presents more elegant solution for the resource sharing by re-using the single Factory Service.



Back to top


Objectives

In this tutorial, you will learn about different configuration files and deployment descriptors involved in the development of stateful Web Services specific to WS-Core and Axis. The tutorial starts with the WSDL associated with both Instance Services and only Factory Service; understanding of the WSDL is the core requirement of the WSRF based Web Services. During the WSDL development, best practices for Web Services development will also discussed to address interoperability issues across different WSRF implementations.



Back to top


Prerequisites

This tutorial is written for developers who wants to develop stateful Web Services. Intermediate skills of Web Services development and Java Programming are essential. WS-Core is based on Axis platform, therefore Web Services developement experience for Axis will be helpful. Web Services heavily rely on XML and basic understanding of XML is required for manual modification of WSDL files.



Back to top


System requirements

The esample source code can be run on Windows and UNIX platform, although examples are developed on Windows XP.

To compile and deploy examples, Java 2 Standard Edition Software Development Kit (J2SESDK) or above and Ant build tool 1.6 or above is required.

To run the source code in this tutorial, you can download complete Globus Toolkit only for Linux/Unix systems or WS-Core both for UNIX and Windows System.

WS-Core comes with embedded standalone Web Container but optionally any Java Web Container e.g. Tomcat can also be used.



Back to top



Page 1 of 11Go to the next page

skip to main content

developerWorks  >  Grid computing | SOA and Web services  >

Resource Sharing among multiple Web Services, Part 1: Resource Sharing using Implied Resource Pattern

developerWorks
Go to the previous pagePage 2 of 11Go to the next page

Document options
PDF format - A4

PDF - A4
45KB (9 pages)

PDF format - letter

PDF - Letter
45KB (10 pages)

Get Adobe® Reader®

Sample code


Rate this tutorial

Help us improve this content


Overview

Web Services architecture lacked the notion of state, stateful interactions, resource lifecycle management, notification of state changes, and support for sharing and coordinated use of diverse resources in dynamic 'virtual organizations'. Different vendors and "Web Services" toolkits provide customised solution to address the limitation of vanilla Web Services, which has resulted in compatibility and interoperability issues. To resolve these issues, there has been some recent collaboration between Web Services and the Grid computing community to develop consensus for standardised mechanism to preserve states aligned with already accepted Web Services architecture. This effort has produced two important sets of specifications: WS-Resource Framework and WS-Notification, which essentially provides all the missing functional capabilities demanded by the developers, and are compliance to broadly adopted Web Services concepts.

WS-RF is a set of specifications define conventions for representing, abstracting and manipulating state in a Web Services architecture. These specifications are based on the Extensible Markup Language (XML) schemas, and Web Services Definition Language (WSDL) interfaces for the properties and ports common to all WS-RF resources. The Web Services Resource Framework and related specifications are gaining momentum, however programmers want to extend the concept of stateful interactions to the next level.

In most of the literature and accompanying source code, each WSRF based service has its own resource and each client interaction with Factory Service results in the instantiation of new resource object. Is it impressive? No..! I can't imagine too much usability and benefits of these state-full resources if we can't share these resources among multiple "Web Services". There are many scenarios where different Web Services are working on the single resource and exposing different operations corresponding to different ResourceProperty in single ResourcePropertySet; for example in any typical Grid Application, Administrator uses different Web Services to manage the "User Accounts" where he can modify different parameters related to any user account, add new user accounts or delete existing user accounts; whereas Users use different Web Services to manage limited set of properties related to their own accounts only. There can be another general purpose Web Services to query the user information with read only privileges. Each Web Services exposes different operations related to same resource/s according to its WSDL rather than each "Web Services" working on its own set of resources which can lead to update anomalies or synchronization issues.

Web Services Resource Framework

WS-RF comprises four inter-related specifications; which define how to represent, access, manage, and group WS-Resources:

  • WS-ResourceProperties defines how WS-Resources are described by XML documents that can be queried and modified; this document is a view or projection of the state of the WS-Resource and is typically not equivalent to the state;
  • WS-ResourceLifetime defines mechanisms for destroying WS-Resources ("Create" is not defined but use of the Factory Design pattern is recommended.);
  • WS-ServiceGroup describes how collections of Web Services and/or WS-Resources can be represented and managed;
  • WS-BaseFaults defines a standard exception reporting format.

WS-RF specifications are compliant with the WS-Interoperability Basic Profile and any WS-I compliant Web Services client can interact with any service that supports WS-RF specifications. For a client, WS-RF defines conventions for the message exchanges used to interact with state - the goal of which is to make services that follow these conventions easier to use and manage.



Back to top


Resources

Resources model the state of a Web Service. wrapping atomic/composite data types called Resource Properties. A Resource Property is a piece of information defined as part of the state model, reflecting a part of the Resource state, such as its meta-data, manageability information and lifetime. A Resource contains different Resource Properties and any Resource Property can be repeated multiple times; the cardinality of Resource and Resource Properties is one-to-many.

The WS-RF specification supports dynamic insertion and deletion of the Resource Properties of a Resource at run time. Customer details in a Trading System are a single Resource with multiple Resource Properties like name, address, card details and trading history. The address Resource Property can have multiple entries such as billing address and shipping address. Trading history is a dynamic Resource Property, which is added for every new order and may automatically deleted after a given period. Resource itself is a distributed object, expressed as an association of an XML document with a defined type attached with the Web Service portType in the WSDL. Each Resource can be serialized in XML format to embed it in the SOAP Message before sending across the network. Resource has a unique identity and distinguishable handler. Although Resource itself is not attached to any Uniform Resource Locator (URL), it does provide the URL of the Web Service that manages it. The unique identity of the Resource and the URL of the managing Web Service is called an Endpoint Reference (EPR), which adheres to Web Services Addressing (WSA). WS-RF avoids the need to describe the identifier explicitly in the WSDL description by instead encapsulating the identifier within its EPR and implicitly including it in all messages addressed through it.


Listing 1. Endpoint Reference containing its Resource identity

<user:userReference>   
	<wsa:Address>
		http://domain.co.uk/UserService
	</wsa:Address>
	<wsa:ReferenceProperty>
		<user:userID>xyz< /user:userID>
	</wsa:ReferenceProperty>
	<wsa:ReferenceParameters/>
</user:userReference>
        



Back to top


Resource Sharing

Resources are not bound to a single Web Service; in fact multiple Web Services can manage and monitor the same Resource instance with different business logic and from a different perspective. Similarly, Resources are not confined to a single organization and multiple organizations may work together on the same Resource which leads to the concept of collaboration. A typical Grid/Enterprise Application spans different departments and multiple domains within the organization, information being shared among different processes; sharing a single Resource means working on the same Resource through its unique identity. Passing a unique identity of the Resource instance between partner processes and organizations results in minimum network overhead and avoids issues of stale information. In scientific and visual modelling applications, there can be large volumes of data (gigabytes) and moving such data between different processes is neither practical nor an optimized solution. In these data-centric applications standard Web Services can't cope with the requirement of these applications due to their stateless nature and passing the hard-coded URL related to the data is infeasible due to the lack of security and access control. The Resource EPRs are generated dynamically and can be discovered, inspected and monitored dynamically via dedicated Web Services. Single "Resource" can be shared between two different Web Services each of them exposing possibly different sets of operations on the same Resource, for instance to provide both an administrators' and users' perspective (where an administrator can modify the data and a user can only query the data).



Back to top



Go to the previous pagePage 2 of 11Go to the next page

skip to main content

developerWorks  >  Grid computing | SOA and Web services  >

Resource Sharing among multiple Web Services, Part 1: Resource Sharing using Implied Resource Pattern

developerWorks
Go to the previous pagePage 3 of 11Go to the next page

Document options
PDF format - A4

PDF - A4
45KB (9 pages)

PDF format - letter

PDF - Letter
45KB (10 pages)

Get Adobe® Reader®

Sample code


Rate this tutorial

Help us improve this content


Web Services Description Language (WSDL)

It is good practice to write WSDL files before implementing the relevant Web Services. WSDL is the client facing interface and contract of the Web Services, declaring different public methods and their signatures. WSDL provides enough information to the client for successful interaction with the Web Services. In this tutorial there are three Web Services PersonFactory Service, PersonName Service and PersonAddress Service. PersonFactory service is only required to instantiate the resource shared among two instance services using Factory/Instance design pattern. PersonName and PersonAddress services have similar type of Resource which is implemented as PersonResource and is initialized through PersonResourceHome. The isntance services i.e. PersonName and PersonAddress are using similar type of Resource (PersonResource), thus it is better to have "complex data type" implemented in separate schema rather than in the WSDL for each Instance Service, which helps in re-usability of schema across various Web Services. Separation of xml schema from WSDL is single source of change (which can also be single source of error .. joking) and helps is achieving uniformity across the various Web Services within the application. Below is our simple schema for Person:


Listing 2. XML Schema for the Person Resource

<xs:schema targetNamespace="http://test.wsrf.resource.sharing" 
  elementFormDefault="qualified" 
  xmlns="http://test.wsrf.resource.sharing" 
  xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:complexType name="name">
    <xs:sequence>
	  <xs:element name="title" type="xs:string" /> 
	  <xs:element name="firstName" type="xs:string" /> 
	  <xs:element name="lastName" type="xs:string" /> 
	  <xs:element name="middleName" type="xs:string" /> 
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="address">
    <xs:sequence>
	  <xs:element name="houseNumber" type="xs:string" /> 
	  <xs:element name="streetName" type="xs:string" /> 
	  <xs:element name="city" type="xs:string" /> 
	  <xs:element name="county" type="xs:string" /> 
	  <xs:element name="country" type="xs:string" /> 
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="person">
    <xs:sequence>
	  <xs:element name="name" ref="myName" /> 
	  <xs:element name="address" ref="myAddress" /> 
    </xs:sequence>
  </xs:complexType>

  <xs:element name="myName" type="name" /> 

  <xs:element name="myAddress" type="address" /> 

  <xs:element name="myPerson" type="person" /> 
</xs:schema>
		

The most important thing in the Listing2, is the use of namespace. Namespaces in the XML Schema are translated into Java packages at the time of creating Java classes equivalent of XML schema and are used to embed external XML schemas in the WSDL files. In this example namespace of "http://test.wsrf.resource.sharing" by default will be mapped to the package sharing.resource.wsrf.test. In the listing each complex data type is wrapped in the "element tag" which is requirement of Document/Literal style Web Services as recommended by WS-I Basic Profile, which is another standard to regulate the standards of Web Services. Please even for standard Web Services avoid RPC/encoded style implementation. RPC/encoded Web Services are not compliant to WS-I Basic profile. Luckily WS-RF engines only support Document/Literal style Web Services.

WSDL for the Factory Service

WSDL for our Factory Service is very simple and has only one operation createResource() to create the instance of the Person Resource for our Instance Services. Factory Service is not related to the WS-RF and doesn't import different WSDL's and XML Schemas declared in the WS-RF specifications. The createResource() returns the EPR of newly created resource to the calling client and therefore requires to know the XML Schema of Web Services Addressing (WSA), which is the only schema imported in the WSDL. Below is the complete WSDL for FactoryService.


Listing 3. WSDL for the Factory Service

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="PersonFactoryService"
    targetNamespace="http://sharing.wsrf.dl.ac.uk/name/person"    
    xmlns:tns="http://sharing.wsrf.dl.ac.uk/name/person"
    xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing" 
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns="http://schemas.xmlsoap.org/wsdl/">

<types>
<xsd:schema targetNamespace="http://sharing.wsrf.dl.ac.uk/name/person"
    xmlns:tns="http://sharing.wsrf.dl.ac.uk/name/person"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">

	<import namespace="http://schemas.xmlsoap.org/ws/2004/03/addressing"
        schemaLocation="../ws/addressing/WS-Addressing.xsd"/>

	<xsd:element name="createResource">
		<xsd:complexType/>
	</xsd:element>
	<xsd:element name="createResourceResponse">
	<xsd:complexType>
		<xsd:sequence>
			<xsd:element ref="wsa:EndpointReference"/>
		</xsd:sequence>
	</xsd:complexType>
	</xsd:element>
        
</xsd:schema>
</types>

<message name="CreateResourceRequest">
	<part name="request" element="tns:createResource"/>
</message>
<message name="CreateResourceResponse">
	<part name="response" element="tns:createResourceResponse"/>
</message>

<portType name="PersonNameFactoryPortType">
	<operation name="createResource">
		<input message="tns:CreateResourceRequest"/>
		<output message="tns:CreateResourceResponse"/>
	</operation>
</portType>

</definitions>
        

The most important thing in the Listing2, is the use of namespace. Namespaces in the XML Schema are translated into Java packages at the time of creating Java classes equivalent of XML schema and are used to embed external XML schemas in the WSDL files. In this example namespace of "http://test.wsrf.resource.sharing" by default will be mapped to the package sharing.resource.wsrf.test. In the listing each complex data type is wrapped in the "element tag" which is requirement of Document/Literal style Web Services as recommended by WS-I Basic Profile, which is another standard to regulate the standards of Web Services. Please even for standard Web Services avoid RPC/encoded style implementation. RPC/encoded Web Services are not compliant to WS-I Basic profile. Luckily WS-RF engines only support Document/Literal style Web Services.

WSDL for the Factory Service

WSDL for our Factory Service is very simple and has only one operation createResource() to create the instance of the Person Resource for our Instance Services. Factory Service is not related to the WS-RF and doesn't import different WSDL's and XML Schemas declared in the WS-RF specifications. The createResource() returns the EPR of newly created resource to the calling client and therefore requires to know the XML Schema of Web Services Addressing (WSA), which is the only schema imported in the WSDL. Below is the complete WSDL for FactoryService.


Listing 3. WSDL for the Factory Service

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="PersonFactoryService"
    targetNamespace="http://sharing.wsrf.dl.ac.uk/name/person"    
    xmlns:tns="http://sharing.wsrf.dl.ac.uk/name/person"
    xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing" 
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns="http://schemas.xmlsoap.org/wsdl/">

<types>
<xsd:schema targetNamespace="http://sharing.wsrf.dl.ac.uk/name/person"
    xmlns:tns="http://sharing.wsrf.dl.ac.uk/name/person"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">

	<import namespace="http://schemas.xmlsoap.org/ws/2004/03/addressing"
        schemaLocation="../ws/addressing/WS-Addressing.xsd"/>

	<xsd:element name="createResource">
		<xsd:complexType/>
	</xsd:element>
	<xsd:element name="createResourceResponse">
	<xsd:complexType>
		<xsd:sequence>
			<xsd:element ref="wsa:EndpointReference"/>
		</xsd:sequence>
	</xsd:complexType>
	</xsd:element>
        
</xsd:schema>
</types>

<message name="CreateResourceRequest">
	<part name="request" element="tns:createResource"/>
</message>
<message name="CreateResourceResponse">
	<part name="response" element="tns:createResourceResponse"/>
</message>

<portType name="PersonNameFactoryPortType">
	<operation name="createResource">
		<input message="tns:CreateResourceRequest"/>
		<output message="tns:CreateResourceResponse"/>
	</operation>
</portType>

</definitions>
        



Back to top


WSDL for the PersonName and the PersonAddress service

Important Tip

WSDL for PersonName and PersonAddress service is declaring different namespaces related to different WS-RF specifications and later importing the correspoding XML Schemas. WSDL is only declaring these different operations relevant to WS-RF specifications and their implementations are provided by the WS-RF engine and as a developer we don't need to care about their implementations unless we want to extend the functionality.

WS-Core has a utility called WSDL Preprocessor , which means developer don't need to declare the signature of WS-RF related operations in the WSDL and only need to declare the name of operations required. In the final WSDL, WSDL Preprocessor will embed the complete signature. I have used the complete signature of WS-RF related operations as in coming Tutorials we will use the same WSDL's for Apache implementation of WS-RF. Using WSDL Preprocessor restricts the re-use of WSDL for other implementaions of WS-RF.

PersonName service has operations related to the Name part of the Person resource, thus it can retrieves the name of the Person and change the name of Person; similarly PersonAdress Web Services has operations to modify and retrieve the Address part of the Person resource. Both services are working on the same resource Person. The WSDL file is very simple the only tricky bit is to import our separate schema file in the WSDL, for this first we have to declare its namespace in the < definition > section of the WSDL file xmlns:myTypes=http://test.wsrf.resource.sharing and then import the schema in the < schema > part of the WSDL by giving the absolute or relevent location of schema.


Importing the external Schema in the < schema > part of the WSDL

< import namespace="http://test.wsrf.resource.sharing" schemaLocation="Person.xsd"/>
        

After importing the external XML schema, we can use the elements defined in the external schema within the WSDL with their fully qualified names just as they are defined in the same WSDL. The WSDL for PersonName has two operations changeName and getNameRP (along with WS-RF required standard operations), which are related to the Name part of the Person type; the changeName operation changes the Name part of the Person resource and getNameRP retrieves the Name part of the Person resource, although we don't need this getNameRP operation as WS-RF defined operation GetResourceProperty will retrieve both the Name and the Address of the Person resource, but this is just to prove the concept.


Listing 4. WSDL for the PersonName service

<definitions name="PersonNameService"
    targetNamespace="http://sharing.wsrf.dl.ac.uk/name/person"
    xmlns:tns="http://sharing.wsrf.dl.ac.uk/name/person"
    xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd"    
     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:myTypes="http://test.wsrf.resource.sharing"
    xmlns="http://schemas.xmlsoap.org/wsdl/">
  <import
    namespace="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-BaseFaults-1.2-draft-01.wsdl"
    location="../wsrf/faults/WS-BaseFaults.wsdl"/>  
  <import
    namespace="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.wsdl"
    location="../wsrf/properties/WS-ResourceProperties.wsdl"/>
  <import
    namespace="http://docs.oasis-open.org/wsn/2004/06/wsn-WS-BaseNotification-1.2-draft-01.wsdl"
    location="../wsrf/notification/WS-BaseN.wsdl"/>
  <import
    namespace="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ServiceGroup-1.2-draft-01.wsdl"
    location="../wsrf/servicegroup/WS-ServiceGroup.wsdl"/>
    
  <types>
    <schema
        targetNamespace="http://sharing.wsrf.dl.ac.uk/name/person"
        xmlns:tns="http://sharing.wsrf.dl.ac.uk/name/person"
        xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    
    <import
        namespace="http://schemas.xmlsoap.org/ws/2004/03/addressing"
        schemaLocation="../ws/addressing/WS-Addressing.xsd"/>
    <import
        namespace="http://test.wsrf.resource.sharing"
        schemaLocation="Person.xsd"/>

    <import
        namespace="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ServiceGroup-1.2-draft-01.xsd"
        schemaLocation="../wsrf/servicegroup/WS-ServiceGroup.xsd"/>

      <element name="PersonResourcePropertiesSet">
        <complexType>
          <sequence>
            <element ref="myTypes:myName"/> 
            <element ref="myTypes:myAddress"/> 
          </sequence>
        </complexType>
      </element>

      <!-- Elements related to changeName Method -->
      <element name="changeName" ref="myTypes:myName" />
      <element name="changeNameResponse" type="xsd:string" />   
      
      <!-- Elements related to getNameRP Method -->
      <element name="getNameRP" >
        <complexType/>
       </element>
       <element name="getNameRPResponse" ref="myTypes:myName"/>  
      
    </schema>
  </types>

  <message name="ChangeNameRequest">
    <part name="ChangeNameRequest"  element="tns:changeName" />
  </message>
  <message name="ChangeNameResponse">
    <part name="ChangeNameResponse" element="tns:changeNameResponse" />
  </message>

  <message name="GetNameRPRequest">
    <part name="GetNameRPRequest" element="tns:getNameRP" />
  </message>
  <message name="GetNameRPResponse">
    <part name="GetNameRPResponse" element="tns:getNameRPResponse" />
  </message> 

  <portType name="PersonNamePortType"
            wsrp:ResourceProperties="PersonResourcePropertiesSet">

    <operation name="GetResourceProperty">
      <input name="GetResourcePropertyRequest"
             message="wsrpw:GetResourcePropertyRequest"
             wsa:Action="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-
                      ResourceProperties/GetResourceProperty"/>
      <output name="GetResourcePropertyResponse"
              message="wsrpw:GetResourcePropertyResponse"
              wsa:Action="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-
                      ResourceProperties/GetResourcePropertyResponse"/>
      <fault  name="InvalidResourcePropertyQNameFault"
              message="wsrpw:InvalidResourcePropertyQNameFault"/>
      <fault name="ResourceUnknownFault" message="wsrpw:ResourceUnknownFault"/>
    </operation>
  
    <operation name="SetResourceProperties">
      <input  name="SetResourcePropertiesRequest" 
                   message="wsrpw:SetResourcePropertiesRequest" 
                   wsa:Action="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-
                           ResourceProperties/SetResourceProperties"/>
      <output name="SetResourcePropertiesResponse" 
                   message="wsrpw:SetResourcePropertiesResponse" 
                   wsa:Action="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-
                            ResourceProperties/SetResourcePropertiesResponse"/>
      <fault  name="ResourceUnknownFault" 
                   message="wsrpw:ResourceUnknownFault" />
      <fault  name="InvalidSetResourcePropertiesRequestContentFault" 
               message="wsrpw:InvalidSetResourcePropertiesRequestContentFault" />     
      <fault  name="UnableToModifyResourcePropertyFault" 
                   message="wsrpw:UnableToModifyResourcePropertyFault" />
      <fault  name="InvalidResourcePropertyQNameFault" 
                   message="wsrpw:InvalidResourcePropertyQNameFault" />     
      <fault  name="SetResourcePropertyRequestFailedFault" 
                   message="wsrpw:SetResourcePropertyRequestFailedFault" />
    </operation>      
    
    <operation name="Subscribe">
      <input message="wsntw:SubscribeRequest" 
          wsa:Action="http://docs.oasis-open.org/wsn/2004/06/wsn-WS-BaseNotification/Subscribe"/>
      <output message="wsntw:SubscribeResponse" 
          wsa:Action="http://docs.oasis-open.org/wsn/2004/06/wsn-WS-BaseNotification/SubscribeResponse"/>
      <fault name="TopicPathDialectUnknownFault" 
           message="wsntw:TopicPathDialectUnknownFault"/>
      <fault name="SubscribeCreationFailedFault" 
            message="wsntw:SubscribeCreationFailedFault"/>
      <fault name="ResourceUnknownFault" message="wsntw:ResourceUnknownFault"/>
    </operation>

    <!--  name attribute in input and output element is optional-->    
    <operation name="changeName">
      <input  name="ChangeNameRequest"  message="tns:ChangeNameRequest" />
      <output name="ChangeNameResponse" message="tns:ChangeNameResponse" />
    </operation>

    <operation name="getNameRP">
      <input  name="GetNameRPRequest"  message="tns:GetNameRPRequest" />
      <output name="GetNameRPResponse" message="tns:GetNameRPResponse" /> 
    </operation>	
	
  </portType>
</definitions>
        

The WSDL for PersonAddress has two operations changeAddress and getAddressRP (along with WS-RF required standard operations), which are related to the Address part of the Person type; the changeAddress operation changes the Address part of the Person resource and getAddressRP retrieves the Address part of the Person resource. Both WSDL files are very similar therefore the WSDL for PersonAddress is not repeated here and can be downloaded with source code of the example.



Back to top



Go to the previous pagePage 3 of 11Go to the next page

skip to main content

developerWorks  >  Grid computing | SOA and Web services  >

Resource Sharing among multiple Web Services, Part 1: Resource Sharing using Implied Resource Pattern

developerWorks
Go to the previous pagePage 4 of 11Go to the next page

Document options
PDF format - A4

PDF - A4
45KB (9 pages)

PDF format - letter

PDF - Letter
45KB (10 pages)

Get Adobe® Reader®

Sample code


Rate this tutorial

Help us improve this content


Implementation Details

There are few Java classes are involved in the implementaion of whole example and it is important to know the role and requiremetns of each Java class. Our example is based on the Implied Resource Pattern which is the recommended way of implementing stateful Web Services; therefore we have one Factory Service and two Instance Service. Below is the list of all classes used in the implementation along with their brief description.



Table 1. List of the Java Classes implemented in the Tutorial
Java ClassesTheir Role in the Application
PersonFactoryService

There is only one Factory Service which is deployed twice to instantiate both Instance Services (PersonNameService and PersonAddressService). Technically there is no need to deploy the Factory Service twice for each service; better approach is to change the createResource method which takes the String and based on the String it initialize the corresponding service. In this tutorial we have followed crude approach to keep the code simple; but in the next tutorial I will discuss the other option w hich fairly complicates the code.

PersonNameService

PersonNameService Service is simple service only wrapping the operations related to the Name of the Person resource.

PersonAddressService

Similar to PersonNameService with only difference that PersonAddressService has logic to change the Address property of the Person resource.

PersonResourceHome

The Resource Home class is used to initialize the Person resource. Be sure we have only one Person resource shared among two services therefore we have only one Resource Home.

PersonResource

The Person resource is shared among different services and has very simple implementation.

PersonResourceQNames

The PersonResourceQNames is the interface to create the Qualified Names for our resource with static and final varaibles.



Important Tip
One important thing to remember, which can be considered as bug, the qualified names declared in this interface only matters and client should use the same qualified names for different Resource Properties accordingly. In other words if the WSDL file has Resource Property with local name as "address" and in the interface the same Resource Property has local name "myAddress" even then Server Side implementation will work, but now client has to use "myAddress" rather than "address" to access the Resource Property.








Back to top


Implementation Details of PersonServiceQNames

PersonServiceQNames is simple interface with final and static variables; which are QName of the ResourceProperties declared in the WSDL. The interface is using two different namespaces declared in the WSDL, one for our separate schema i.e. http://test.wsrf.resource.sharing, which represents that data type of the Person Resource and one for the namespace of the services declared in the WSDL i.e. http://test.wsrf.dl.ac.uk/name/person which is used for the fully qualified name of the Person Resource. Technically these namespaces don't make too much difference as they can be anything even different from the what are declared in the WSDL of Instance Service and the XML schema but using different namespaces will kill the purpose of the WSDL as then client has to use the same namespace and QNames as used by the server side implementation but the client can only guess the QNames of the ResourceProperties from the WSDL. Therefore, namespace and QNames on the server side implementation should match namespace and QNames declared in the WSDL, although the WS-Core; the Globus implementation of the WS-RF doesn’t impose this restriction on the server side implementation.


Listing 5. Source Code of the PersonServiceQNames

package uk.ac.dl.wsrf.sharing.name.person;

import javax.xml.namespace.QName;
public interface PersonServiceQNames {

  public static final String NS = "http://test.wsrf.dl.ac.uk/name/person";
  public static final String NS2 = "http://test.wsrf.resource.sharing";

  public static final QName RPNAME = new QName(NS2, "myName");
  public static final QName RPAddress = new QName(NS2, "myAddress");
  public static final QName RESOURCEPROPERTIES = new QName(NS,
      "NameResourcePropertiesSet");
}
        



Back to top


Implementation Details of PersonFactoryService

Implementation of PersonFactoryService is very similar to any other Factory Services with just single method createResource which creates the EndpointReference for the Resource and returns to the client. In reality Factory Service has nothing to do with Instance service, Factory Service only instantiate the resource which it shares with Instance Service (through "deploy-jndi-config.xml")and manually creates the EndpointReference for the instance service and returns. The createResource operation relies heavily on the deploy-jndi-config.xml and deploy-server.wsdd to instantiate the appropriate resource. The configuration fiels deploy-jndi-config.xml and deploy-server.wsdd are discussed in the next section.


Listing 6. Source Code of the PersonFactoryService

import java.rmi.RemoteException;
import java.net.URL;

import org.globus.wsrf.ResourceContext;
import org.globus.wsrf.ResourceKey;
import org.apache.axis.message.addressing.EndpointReferenceType;
import org.apache.axis.MessageContext;
import org.globus.wsrf.utils.AddressingUtils;
import org.globus.wsrf.container.ServiceHost;
import uk.ac.dl.wsrf.sharing.name.person.*;

public class PersonFactoryService {

    /* Implementation of createResource Operation */
    public CreateResourceResponse createResource(CreateResource request) throws 
            RemoteException {
        System.out.println("PersonFactoryService create");
        ResourceContext ctx = null;
        PersonResourceHome home = null;
        ResourceKey key = null;

        /* First, we create a new PersonResource through the PersonResourceHome  */
        try {
            ctx = ResourceContext.getResourceContext();
            home = (PersonResourceHome) ctx.getResourceHome();
            key = home.create();
        } catch (Exception e) {
            e.printStackTrace();
        }
        EndpointReferenceType epr = null;

        /* We construct the instance's endpoint reference. The instance's service
         * path can be found in the WSDD file as a parameter. */
        try {
            URL baseURL = ServiceHost.getBaseURL();
            String instanceService = (String) MessageContext
                   .getCurrentContext().getService().getOption("instance");
            String instanceURI = baseURL.toString() + instanceService;
            // The endpoint reference includes the instance's URI and the resource key
            epr = AddressingUtils.createEndpointReference(instanceURI, key);
        } catch (Exception e) {
            e.printStackTrace();
        }

        /* Finally, return the endpoint reference in a CreateResourceResponse */
        CreateResourceResponse response = new CreateResourceResponse();
        response.setEndpointReference(epr);
        return response;
    }
}
        

In deploy-jndi-config.xml (discussed later) for Factory Service we have something similar to the following where Factory Service doesn't have its own resource but has link to the resource declared in the "AnyService":


Listing 7. Resource Linkage in "deploy-jndi-config.xml"

<service name="AnyService">
  <resource name="home" type="XXX.XXX.XXX">
    <resourceParams>
      .........
    </resourceParams>
 </resource>
</service>
<service name="FactoryService">
  <resourceLink name="home" target="java:comp/env/services/AnyService/home"/>  
</service>
        

If the name of resource in the "AnyService" is changed to "myResource" from home then FactoryService will have something similar to following code in the "deploy-jndi-config.xml":


Listing 8. Another way of Resource Linkage in "deploy-jndi-config.xml"

< resourceLink name="home" target="java:comp/env/services/AnyService/myResource"/ >
        

The following code fragment for the Factory Service, which is normally used in different WS-RF online examples and tutorials, will only fetch that resource whose name is "home" in the deploy-jndi-config.xml for the Instance Service; if resource has any other name then it can't be fetched or instantiated directly and the only option is to use InitialContext which will be dicussed in the next part of this series. "FactoryService" is only instantiating the resource which it is sharing with the Instance service (in above example it is "AnyService").


Listing 9. Source COde to Retrieve Resource Home

ctx = ResourceContext.getResourceContext();
     home = (PersonResourceHome) ctx.getResourceHome();
        



Back to top


Implementation of PersonResource

Implementation of PersonResource is very simple; it is encapsulating the Name and the Address part of our Person resource. Axis will create the matching Java classes for the Name and the Address part of our Person resource in the package according to namespace used in the XML schema. The sample source code has few additional code related to Topic, TopicList and Notification, which is not used in this example but is the basis of the forthcoming tutorials on the Web Services Notification and is discussed in those tutorials. PersonResource.java is the implementation of the Person resource to declare and create instances of the resource, and in fact it is also initializing the resources with the Unique Key, which is used in the EPR. Direct access to PersonResource is prohibited and all calls to initialize the instances of resource should be through PersonResourceHome.java which is discussed in next section. Below is the implementation of PersonResource.java.


Listing 10. Source Code of the PersonResource

package uk.ac.dl.wsrf.sharing.name.person;

import org.globus.wsrf.Resource;
import org.globus.wsrf.ResourceProperties;
import org.globus.wsrf.ResourceProperty;
import org.globus.wsrf.ResourcePropertySet;
import org.globus.wsrf.ResourceIdentifier;
import org.globus.wsrf.impl.SimpleResourceProperty;
import org.globus.wsrf.impl.SimpleResourcePropertySet;
import org.globus.wsrf.TopicListAccessor;

import uk.ac.dl.wsrf.sharing.name.person.*;
import sharing.resource.wsrf.test.*;
import org.globus.wsrf.TopicList;
import org.globus.wsrf.impl.SimpleTopicList;
import org.globus.wsrf.impl.ResourcePropertyTopic;
import org.globus.wsrf.Topic;

public class PersonResource implements Resource, ResourceProperties,
        ResourceIdentifier, TopicListAccessor {

    /** the identifier of this Resource */
    private Object id;

    /** Stores the ResourceProperties */
    private ResourcePropertySet propSet;

    /* Variable for Resource property */
    private Name name;
    private Address address;


    /** Resource property name and address */
    private ResourceProperty nameRP;
    private ResourceProperty addressRP;


    /** Create Topic List**/
    private TopicList topicList;

    /** initializes the PersonResource. */
    public void initialize() throws Exception {
        System.out.println("PersonResource.initialize() PersonService");

        // choose an ID
        this.id = new Integer(hashCode());

        // create the resource property set
        this.propSet = new SimpleResourcePropertySet(
           PersonServiceQNames.RESOURCEPROPERTIES);

        // create resource properties
        this.nameRP = new SimpleResourceProperty(PersonServiceQNames.RPNAME);
        this.addressRP = new SimpleResourceProperty(PersonServiceQNames.
                RPAddress);

        //Initialize TopicList
        this.topicList = new SimpleTopicList(this);

        // Wrap ResourceProperty to make it Topic
        this.nameRP = new ResourcePropertyTopic(this.nameRP);
        this.addressRP = new ResourcePropertyTopic(this.addressRP);

        // Add RP in the TopicList
        this.topicList.addTopic((Topic)this.nameRP);
        this.topicList.addTopic((Topic)this.addressRP);

        this.propSet.add(this.nameRP);
        setName(new Name("Asif ", "Akram", " ", "Mr."));
        this.nameRP.add(name);

        this.propSet.add(this.addressRP);
        setAddress(new Address("Daresbury", "United kingdom", "Cheshire", "23",
                               "Wilson Patten"));
        this.addressRP.add(address);

    }

    public ResourcePropertySet getResourcePropertySet() {
        return propSet;
    }

    public void setNameRP(Name nameValue) {
        setName(nameValue);
        this.nameRP.set(0, name);
    }

    public Name getName() {
        return name;
    }

    public void setName(Name name) {
        this.name = name;
    }

    public void setAddressRP(Address addressValue) {
        setAddress(addressValue);
        this.addressRP.set(0, address);
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }


    public Object getID() {
        return id;
    }

    public TopicList getTopicList() {
        return topicList;
    }
}
        

Important Tip

In the WSDL for Instance Services there is one element PersonResourcePropertiesSet, which has two sub-elements of the type Name and Address. PersonResourcePropertiesSet is the resource and in the programming API it is represented as ResourcePropertySet and sub-elements of ResourcePropertySet are called ResourceProperties.WS-RF based Web Service can have any number of the Resource Properties and all of them are wrapped in different ResourcePropertySet for later retrieval, modification or deletion. It is always nice to follow good naming conventions which should be self explanatory, in the source code any data type, which will encapsulate the "resource" for our Instance Service ends with ResourcePropertiesSet to indicate that it is ResourcePropertySet, and the name of all sub-elements (Resource Property) of the resource ends with "RP" (Resource Property) to keep things clear and simple.

In the code the variable "propSet" is initialized as the object of the SimpleResourcePropertySet, and you may have figured out that the ResourcePropertySet is the interface and the "SimpleResourcePropertySet" is the concrete implementation of the ResourcePropertySet. The constructor of the SimpleResourcePropertySet takes the QName i.e. the qualified name of our resource property as declared in the WSDL file. Similarly the ResourceProperty is an interface and the ReflectionResourceProperty and the SimpleResourceProperty are its implementation used to declare and initialize the variable nameRP (name Resource Property) and addressRP (address Resource Property). ReflectionResourceProperty has three different constructors and the constructor normally used is: ReflectionResourceProperty(QName name, String propertyName, Object obj), QName should match the qualified name of the Resource Property in the WSDL and "String propertyName" is the name of the variable in the implementation. It can be called anything like myName different from the name used in the WSDL. SimpleResourceProperty(QName name) only takes QName of the Resource Property and the variable encapsulating the value of the Resource Property has to be coupled manually with the Resource Property. In the source code SimpleResourceProperty is used. Finally we have to add these newly created Resource Property into our ResourcePropertySet, e.g. this.propSet.add(nameRP) and assign the initial values to the Resource Property by calling utility set method for private variables.

One important thing in the source code is to import the package "sharing.resource.wsrf.test.*", in which WSDL2Java will create all Java mappings for the Name and the Address data types which are later used in the resource. Following are the key points related to the PersonResource:
  1. Local variables for Name and Address
    
    /* Variable for Resource property */
    private Name name;
    private Address address;
                

  2. Declaring ResourcePropertySet
    
    /** Stores the ResourceProperties */
    private ResourcePropertySet propSet;
                

  3. Declaring ResourceProperty objects for Name and Address
    
    /** Resource property name and address */
    private ResourceProperty addressRP;
    private ResourceProperty nameRP;
                

  4. Initializing the ResourcePropertySet
    this.propSet = new SimpleResourcePropertySet(PersonServiceQNames.RESOURCEPROPERTIES);

  5. Initializing the ResourceProperty for Name and Address
    
    this.nameRP = new SimpleResourceProperty(PersonServiceQNames.RPNAME);
    this.addressRP = new SimpleResourceProperty(PersonServiceQNames. RPAddress);
                

  6. Initializing Address and Name ResourceProperty after adding them in the ResourcePropertySet
    
    /*Initializing Name and adding in the ResourcePropertySet*/
    this.propSet.add(this.nameRP);
    setName(new Name("Asif ", "Akram", " ", "Mr."));
        this.nameRP.add(name);
    /*Initializing Name and adding in the ResourcePropertySet*/
    this.propSet.add(this.addressRP);
    setAddress(new Address("Daresbury", "United kingdom", "Cheshire", "23",
            "Wilson Patten"));
    this.addressRP.add(address);
                

  7. get and set methods for Name and Address objects
    
    public Address getAddress() { return address; }	
    public void setAddress(Address address) { this.address = address }
    
    public Name getName() {  return name;  }
    public void setName(Name name) {  this.name = name; }
                

  8. get method for Name and Address ResourcePropety
    
    public void setNameRP(Name nameValue) { 
       setName(nameValue);
       this.nameRP.set(0, name);
    }
    public void setAddressRP(Address addressValue) {
       setAddress(addressValue);
       this.addressRP.set(0, address);
    }
                

The one main issue in the initializion of the Name and the Address part of the Person resource is that variable in the Resource Property like title, firstName or lastName are not in the same order as they are declared in the schema, therefore as a developer you have to check the order of the variables in the constructor of the corresponding class. Better solution is to use the default constructor to create the object i.e. Name/Address and set different values through their set methods.



Back to top


Implementation of PersonResourceHome

PersonResourceHome.java is only to initialize our PersonResource.java. PersonResourceHome extends ResourceHomeImpl and has create() method to instantiate the resource which returns the ResourceKey. The ResourceKey is the Unique Key for the resource instance and is used to identify specific instance of the resource in the EPR. Below is the complete implementation of the PersonResourceHome


Listing 11. Source Code of the PersonResourceHome

import org.globus.wsrf.ResourceKey;
import org.globus.wsrf.impl.ResourceHomeImpl;
import org.globus.wsrf.impl.SimpleResourceKey;
import org.globus.wsrf.Resource;
import org.globus.wsrf.ResourceContext;

public class PersonResourceHome extends ResourceHomeImpl {
    private static java.util.Hashtable resources = new java.util.Hashtable ();

    private int counter=0;
    public ResourceKey create() {
        System.out.println("PersonResourceHomeFactory create() " + counter++);
        try {
            PersonResource resource = (PersonResource) createNewInstance();
            resource.initialize();
            ResourceKey key = new SimpleResourceKey(keyTypeName, resource.getID());
            this.add(key, resource);
            resources.put(key,resource);
            return key;
        } catch (Exception e) {
            System.out.println("Exception when creating PersonResource: ");
            e.printStackTrace();
            return null;
        }
    }
}
        



Back to top


Implementation of PersonNameService

In the actual implementation both Instance Services are named as PersonService but service which is referred as PersonNameService in the tutorial is in the package "uk.ac.dl.wsrf.sharing.name.person" and the service termed as PersonAddressService is in the package "uk.ac.dl.wsrf.sharing.address.person". It was better to name both services differently but I preferred to put them in different packages to distinguish them.

PersonService has the business logic to manage the Person resource according to the corresponding WSDL's. The PersonService in the package "uk.ac.dl.wsrf.sharing.name.person" has two public methods the getNameRP() and the changeName(); similarly PersonService in the package "uk.ac.dl.wsrf.sharing.address.person" has two public methods the getAddressRP() and the changeAddress() along with the utility method getResource() to locate the resource referenced in the EPR.


Listing 12. Source Code of the PersonNameService

package uk.ac.dl.wsrf.sharing.name.person;

import java.rmi.RemoteException;
import org.globus.wsrf.ResourceContext;

import uk.ac.dl.wsrf.sharing.name.person.*;
import sharing.resource.wsrf.test.Name;
public class PersonService {

  public PersonService() throws RemoteException {  }

  public String changeName(Name name) throws RemoteException {
        System.out.println("PersonNameService changeName Method Called");
        PersonResource nameResource = getResource();
        nameResource.setNameRP(name);
        return "Name Changed " + name.getFirstName() + " "+name.getLastName() + " !";
    }

    public Name getNameRP(GetNameRP params) throws RemoteException {
        System.out.println("PersonNameService getNameRP Method Called");
        PersonResource personResource = getResource();
        return personResource.getName();        
    }

    public PersonResource getResource() throws RemoteException {
         System.out.println("PersonNameService getResource() Method Called");
        Object resource = null;
        try {
            resource = ResourceContext.getResourceContext().getResource();

        } catch (Exception e) {
            throw new RemoteException("", e);
        }
        PersonResource personResource = (
                PersonResource) resource;
        return personResource;
    }
}
        



Back to top


Implementation of PersonAddressService

The implementation of the PersonService in the package uk.ac.dl.wsrf.sharing.address.person, is very similar to the PersonService discussed in the last section and is exactly on the same lines. The only difference in this PersonService is that it is manipulating the Address part of the Person resource. Below is the complete code of PersonService in the package uk.ac.dl.wsrf.sharing.address.person.


Listing 13. Source Code of the PersonAddressService

package uk.ac.dl.wsrf.sharing.address.person;

import java.rmi.RemoteException;
import org.apache.axis.message.addressing.EndpointReferenceType;
import org.globus.wsrf.ResourceContext;
import org.globus.wsrf.ResourceKey;
import org.globus.wsrf.utils.AddressingUtils;
import org.apache.axis.MessageContext;

import uk.ac.dl.wsrf.sharing.name.person.*;
import sharing.resource.wsrf.test.*;
import javax.xml.soap.SOAPElement;
import javax.xml.namespace.QName;
import org.globus.wsrf.impl.SimpleResourceKey;

public class PersonService {

    public PersonService() throws RemoteException {
    }

    public String changeAddress(Address address) throws RemoteException {
        System.out.println("PersonService changeAddress Method Called");
        PersonResource resource = getResource();
        resource.setAddressRP(address);
        return "Address Changed " + address.getCity() + " " +
                address.getCountry() + " !";
    }

    public Address getAddressRP(GetAddressRP params) throws RemoteException {
        System.out.println("PersonService getAddressRP Method Called");
        PersonResource resource = getResource();
        return resource.getAddress();
    }

    public PersonResource getResource() throws RemoteException {
        System.out.println("PersonService getResource() Method Called");
        Object resource = null;        
        try {
            resource = ResourceContext.getResourceContext().getResource();

        } catch (Exception e) {
            throw new RemoteException("", e);
        }
        PersonResource personResource = (
                PersonResource) resource;
        return personResource;

    }
} 	
        



Back to top



Go to the previous pagePage 4 of 11Go to the next page

skip to main content

developerWorks  >  Grid computing | SOA and Web services  >

Resource Sharing among multiple Web Services, Part 1: Resource Sharing using Implied Resource Pattern

developerWorks
Go to the previous pagePage 5 of 11Go to the next page

Document options
PDF format - A4

PDF - A4
45KB (9 pages)

PDF format - letter

PDF - Letter
45KB (10 pages)

Get Adobe® Reader®

Sample code


Rate this tutorial

Help us improve this content


Configuration Files

In this section we will examine different configuration files related for successful deployment of the WS-RF based Web Services. These configurations files are related to Axis framework and WS-Core is implemented on the top of Axis framework. If you are new to the Axis framework then understanding of these configuration files is very important to understand the underlying concept of the WS-RF application.

Implementation of Deployment Descriptor

The implementation discussed in last section is very simple and similar to any other WS-RF and WS-Core online tutorial and example. The trickiest part is to glue different classes together through "Deployment Descriptor" for resource sharing within the application. The Deployment Descriptor used in this example is slightly different from "Deployment" Descriptors for normal Web Services and if you conceptually know what you are trying to achieve, then it is simple enough to understand. Below is the whole "Deployment Descriptor" for our application followed by the explanation:


Listing 15. Source Code of the Deployment Descriptor

<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="PersonNameService" provider="Handler" use="literal" style="document">
    <parameter name="providers" value="GetRPProvider SetRPProvider SubscribeProvider"/>
    <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.wsrf.sharing.name.person.PersonService"/>
    <wsdlFile>share/schema/tutorial/PersonNameservice.wsdl</wsdlFile>
  </service>

  <service name="PersonAddressService" provider="Handler" use="literal" style="document">
    <parameter name="providers" value="GetRPProvider SetRPProvider SubscribeProvider"/>
    <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.wsrf.sharing.address.person.PersonService"/>
    <wsdlFile>share/schema/tutorial/PersonAddressservice.wsdl</wsdlFile>
  </service>

  <!-- Factory service -->
  <service name="PersonNameFactoryService" provider="Handler" use="literal" style="document">    
   <parameter name="handlerClass" value="org.globus.axis.providers.RPCProvider"/>
   <parameter name="scope" value="Application"/>
   <parameter name="allowedMethods" value="*"/>
   <parameter name="instance" value="PersonNameService"/>
   <parameter name="className" value="uk.ac.dl.wsrf.sharing.name.person.PersonFactoryService"/>
   <wsdlFile>share/schema/tutorial/FactoryPersonservice.wsdl</wsdlFile>
  </service>

  <service name="PersonAddressFactoryService" provider="Handler" use="literal" style="document">
    <parameter name="handlerClass" value="org.globus.axis.providers.RPCProvider"/>
    <parameter name="scope" value="Application"/>
    <parameter name="allowedMethods" value="*"/>
    <parameter name="instance" value="PersonAddressService"/>
    <parameter name="className" value="uk.ac.dl.wsrf.sharing.name.person.PersonFactoryService"/>
    <wsdlFile>share/schema/tutorial/FactoryPersonservice.wsdl</wsdlFile>
  </service>
</deployment>
        

In the above "Deployment Descriptor" the PersonNameFactoryService and the PersonAddressFactoryService both have the same implementation class "uk.ac.dl.wsrf.sharing.name.person.PersonFactoryService", in other words same the service is deployed with two different names. This is the easiest approach which requires no complicated logic in the implementation of the Factory Service. Although both Factory Services are instantiating the same Person resource associated with the Instance Services but they return the different EPR to the client using the parameter name "instance" which returns the name of corresponding Instance Service. In the implementaion of the Factory Service we have something similar to:

String instanceService = (String) MessageContext.getCurrentContext().getService().getOption("instance");

Thus for both PersonNameFactoryService and PersonAddressFactoryService the "instance" parameter will return different value, although this limitation can be solved by having two parameters i.e. "nameInstance" and "addressInstance" in the Deployment Descriptor for the Factory Service but then Factory Service has to parse the createResource request message to find the target Instance Service and then call corresponding parameter to create EndPointReference. Alternative and easier approach is to have two method as createNameService and createAddressService in the Factory Service to instantiate the resource and create EPR for corresponding resource, which is very childish approach.



Back to top


Details of JNDI Configuration File

The JNDI configuration file is named as "deploy-jndi-config.xml" in the same directory as Deployment Descriptor. For this tutorial the "deploy-jndi-config.xml" has one resource declared globally rather than declared locally with respect to any service. The globally declared resource can be consumed by any service i.e. Instance Services and Factory Services. In the example both Instance Services are using the same Person Resource directly and both Factory Services are instantiating the same resource indirectly through the Instance Service. There is no requirement to have shared resource declared globally, it can be local to anyone of the Instance Service and other Instance Service can reference it through < resourceLink > element. Below is the JNDI configuration file with the global resource:


Listing 16. Source Code of the JNDI Configuration File with GLobal Resource

<jndiConfig xmlns="http://wsrf.globus.org/jndi/config">
  <global>
    <resource
      name="myGlobalResource" type="uk.ac.dl.wsrf.sharing.name.person.PersonResourceHome">
      <resourceParams>
        <parameter>
          <name>factory</name>
          <value>org.globus.wsrf.jndi.BeanFactory</value>
        </parameter>
        <parameter>
          <name>resourceClass</name>
          <value>uk.ac.dl.wsrf.sharing.name.person.PersonResource</value>
        </parameter>
        <parameter>
          <name>resourceKeyName</name>
          <value>{http://sharing.wsrf.dl.ac.uk/name/person}PersonKey</value>
        </parameter>
        <parameter>
          <name>resourceKeyType</name>
          <value>java.lang.Integer</value>
        </parameter>
      </resourceParams>
    </resource>
  </global>
    
  <service name="PersonNameService">
    <resourceLink name="home" target="java:comp/env/myGlobalResource" /> 
  </service>
    
  <!-- Factory service -->
  <service name="PersonNameFactoryService">	
    <resourceLink name="home" target="java:comp/env/services/PersonNameService/home"/>       
  </service>

  <service name="PersonAddressService">
    <resourceLink name="home" target="java:comp/env/myGlobalResource" /> 
  </service>
    
    <!-- Factory service -->
  <service name="PersonAddressFactoryService">
    <resourceLink name="home" target="java:comp/env/services/PersonAddressService/home"/>	
  </service>

</jndiConfig>
        

One important thing to remember is that Global Resources are referenced as "java:comp/env/XX", where XX is the name of global resource. The < resourceLink > is frequently used in the Implied Design Pattern, which means sharing of the resource between the Instance Service and the Factory Service. The only difference in this tutorial is the sharing of the resource among different Instance Services. It should not be that confusing once you can grasp the logic behind it. Second point to remember is that the Factory Service can reference the global resource directly in the same way as Instance Services are doing instead of calling the pareamter "home" of the Instance Service. In other words:


<resourceLink name="home" target="java:comp/env/myGlobalResource" /> 

is equivalent to:

<resourceLink name="home" target="java:comp/env/services/PersonAddressService/home"/>
<resourceLink name="home" target="java:comp/env/services/PersonNameService/home"/>
        

As I said there is no need to have the global resource and the resource can be declared locally with respect to any of the Instance Service, in that case the deploy-jndi-config.xml will be like this:


Listing 17. Source Code of the JNDI Configuration File with Local Resource

<jndiConfig xmlns="http://wsrf.globus.org/jndi/config">
    
  <service name="PersonNameService">
    <resource
      name="myGlobalResource" type="uk.ac.dl.wsrf.sharing.name.person.PersonResourceHome">
      <resourceParams>
        <parameter>
          <name>factory</name>
          <value>org.globus.wsrf.jndi.BeanFactory</value>
        </parameter>
        <parameter>
          <name>resourceClass</name>
          <value>uk.ac.dl.wsrf.sharing.name.person.PersonResource</value>
        </parameter>
        <parameter>
          <name>resourceKeyName</name>
          <value>{http://sharing.wsrf.dl.ac.uk/name/person}PersonKey</value>
        </parameter>
        <parameter>
          <name>resourceKeyType</name>
          <value>java.lang.Integer</value>
        </parameter>
      </resourceParams>
    </resource>
  </service>
    
  <!-- Factory service -->
  <service name="PersonNameFactoryService">	
	<resourceLink name="home" target="java:comp/env/services/PersonNameService/home"/>       
  </service>

  <service name="PersonAddressService">
	<resourceLink name="home" target="java:comp/env/services/PersonNameService/home"/>
  </service>
    
  <!-- Factory service -->
  <service name="PersonAddressFactoryService">
    <resourceLink name="home" target="java:comp/env/services/PersonAddressService/home"/>	
  </service>

</jndiConfig>
        

It is normally prefered to declare global resource/s which keeps things more neat and clean; and uniform. Why resource is not declared twice in the both Instance Services? Yes! It is possible but this solution will not work. If the same resource is declared twice locally then each Instance Service will have its own instance of Resource Home and thus resource created by one Instance Service will not be available to other Instance Service. Remember Resource Home has HashTable which keeps the track of the resources created through it. In other words when PersonNameService creates object of PersonResource called resourceObject1, then any attempt to access this resourceObject1 through PersonAddressService will throw the exception "no such resource available". The reason for this is very simple PersonAddressService will try to find resourceObject1 in its own instance of PersonResourceHome. I had the same problem which I initially solved by using static HashTable of resources in the PersonResourceHome where I was adding the resources myself rather than adding in the HashTable of super class and then was locating the resource mamually. This approach works fine but there is no reason for this extra effort unless you want to do something extra, like monitoring the resources, calculating the number of active resources for statistical reasons. In the PersonResourceHome you can locate/find any specific resource in the HashTable declared in the super class but can't list all existing resources. The requirement to monitor the resources is very realistic, imagine you have a Portal where user can login and once they are successfully logged then list all the instances of different resources created by that specific user or group of users working as team is displayed. The user can click any specific resource and Portal dynamically creates its EPR and update the other part of Portal with its Resource Properties. Monitoring of the resources is also very important in the load balancing, where the number of the specific resources on the particular machine should not exceed certain level and after that spare machine is used or non-active resources are persisted.



Back to top


Details of Build Script

The last missing part of the puzzle is Build script file. The Build script used in this tutorial comes with the WS-Core and is very helpful to compile and deploy the application. This Build script take cares of all required packages and the WS-RF specific WSDL’s and the XML schema files which are required for successful compilation and creation of the gar file. This build script is very similar to the default Build script with only difference that this time we have three different WSDL’s, therefore we need extra targets in the script to parse the WSDL’s and create corresponding Java mappings. The Build script is three page long and is available with the source code.



Back to top



Go to the previous pagePage 5 of 11Go to the next page

skip to main content

developerWorks  >  Grid computing | SOA and Web services  >

Resource Sharing among multiple Web Services, Part 1: Resource Sharing using Implied Resource Pattern

developerWorks
Go to the previous pagePage 6 of 11Go to the next page

Document options
PDF format - A4

PDF - A4
45KB (9 pages)

PDF format - letter

PDF - Letter
45KB (10 pages)

Get Adobe® Reader®

Sample code


Rate this tutorial

Help us improve this content


Client Implemetaion and Result Discussion

Everything required to implement the example is successfully completed and the example is ready to be compiled and deployed, but before that we need the client to test the example. In this section first we will discuss the implementation of the Client and later examine the result for the proof of the concept.

Implementation of the Client

The client code is implemented in the ClientName.java class, which is in the package "uk.ac.dl.wsrf.sharing.name.person.client". The client has utility method getInstanceEPR() which takes the String parameter. This String parameter is the name of the Factory Service to be invoked for creating the resource. The getInstanceEPR() method is called only once and this really doesn’t make any difference if PersonNameFactory or PersonAddressFactory is called as at the end of the day both are initializing the same resource i.e. PersonResource. Calling getInstanceEPR() method twice will create two different instances of the same resource and still both instances of the resource will be shared between Instance Services. The getInstanceEPR() method returns the EPR as the result of call to createResource() method in the Factory Service according to the WSDL, this returned EPR is used to retrieve the unique ID of the resource and is used in manually creating the EPR for other Instance Service. Later in the client the Name part and the Address part of the Person resource are modified by corresponding Instance Services and finally the Person resource is printed on the display for the proof of the concept.


Listing 18. Source Code of the Client

 package uk.ac.dl.wsrf.sharing.name.person.client;

import org.oasis.wsrf.properties.GetResourcePropertyResponse;

import org.apache.axis.message.addressing.EndpointReferenceType;

import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.CommandLine;

import org.globus.wsrf.client.BaseClient;
import org.globus.wsrf.utils.AnyHelper;
import org.globus.wsrf.utils.FaultHelper;

import uk.ac.dl.wsrf.sharing.name.person.PersonServiceQNames;
import uk.ac.dl.wsrf.sharing.name.person.service.*;
import uk.ac.dl.wsrf.sharing.address.person.service.*;
import uk.ac.dl.wsrf.sharing.name.person.*;
import uk.ac.dl.wsrf.sharing.address.person.*;
import sharing.resource.wsrf.test.*;
import javax.xml.rpc.*;

public class ClientName extends BaseClient {

    final static PersonNameServiceAddressingLocator locator =
            new PPersonNameServiceAddressingLocator();

    final static PersonFactoryServiceAddressingLocator factoryLocator =
            new PersonFactoryServiceAddressingLocator();

    final static PersonAddressServiceAddressing locator2 =
            new PersonAddressServiceAddressingLocator();

    private static EndpointReferenceType service1InstanceEPR = null;
    private static EndpointReferenceType service2InstanceEPR = null;

    private EndpointReferenceType getInstanceEPR(String path) {
        EndpointReferenceType instanceEPR;        
        try {
            this.getEPR().getAddress().setPath(path);            
            PersonNameFactoryPortType factoryPort = factoryLocator.
                    getPersonNameFactoryPortTypePort(
                            this.getEPR());
            CreateResourceResponse createResponse = factoryPort
                    .createResource(new CreateResource());
            instanceEPR = createResponse.getEndpointReference();
            instanceEPR.getAddress().setPort(8082);            
            return instanceEPR;

        } catch (ServiceException ex) {
            ex.printStackTrace();
        } catch (Exception ex1) {
            ex1.printStackTrace();
        }

        return null;
    }

    public static void main(String[] args) {
        ClientName client = new ClientName();

        // 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 {
            service1InstanceEPR = client.getInstanceEPR(
                    "/wsrf/services/PersonNameFactoryService");
            /*
            service2InstanceEPR = client.getInstanceEPR(
                    "/wsrf/services/PersonAddressFactoryService");*/
            service2InstanceEPR = new EndpointReferenceType();
            service2InstanceEPR.setAddress(new org.apache.axis.message.
                                           addressing.Address(
                    "http://XX.XX.XX.XX:8082/wsrf/services/PersonAddressService"));
            service2InstanceEPR.setProperties(service1InstanceEPR.getProperties());
            System.out.println(service2InstanceEPR.getProperties().toString());
            System.out.println("  " + service2InstanceEPR.toString());
            PersonNamePortType port;
            PersonAddressPortType port2;
            
            // Get instance PortType
            port = locator.getPersonNamePortTypePort(service1InstanceEPR);
            port2 = locator2.getPersonAddressPortTypePort(service2InstanceEPR);
            System.out.println("Created instance.");
            
            GetResourcePropertyResponse response =
                    port.getResourceProperty(PersonServiceQNames.RP_NAME);
            System.out.println(AnyHelper.toSingleString(response));
            response = port.getResourceProperty(PersonServiceQNames.RP_Address);
            System.out.println(AnyHelper.toSingleString(response));

            Thread.sleep(1000);
            String result = port.changeName(new Name("AsIf", "AkRaM", "…", " Mr."));
            System.out.println(result);
            result = port2.changeAddress(new Address("London", "United Kingdom", 
			"London", "38", "Hamilton Street"));
            System.out.println(result);

            response = port.getResourceProperty(PersonServiceQNames.RP_NAME);
            System.out.println(AnyHelper.toSingleString(response));
            response = port.getResourceProperty(PersonServiceQNames.RP_Address);
            System.out.println(AnyHelper.toSingleString(response));
            
        } catch (Exception e) {
            if (client.isDebugMode()) {
                FaultHelper.printStackTrace(e);
            } else {
                System.err.println("Error: " + FaultHelper.getMessage(e));
            }
        }
    }
}  
		



Back to top


Executing the Client

Now it is the time to test the example by executing the client. Before executing the client start the TCP Monitor utility which is the part of Axis Framework to examine the SOAP messages sent between the client and the services. By default embedded container in the WS-Core listens on the port 8080; and I am assuming the TCP Monitior is listening on the port 8082 and re-directing the messages to the port 8080. If you are using different ports then adjsut the command to run the client. For running the client use following command (I have split the command on two lines for editing purposes):


%GLOBUS_LOCATION%\bin\ClientPerson -s
          http://localhost:8082/wsrf/services/PersonNameFactoryService
        

Below is the final outcome obtained after running the client(I have edited the code to make it clear):


Listing 19. Final Outcome

<ns1:myName xmlns:ns1="http://test.wsrf.resource.sharing">
 <ns1:title>Mr.</ns1:title>
 <ns1:firstName>Asif </ns1:firstName>
 <ns1:lastName>Akram</ns1:lastName>
 <ns1:middleName> </ns1:middleName>
</ns1:myName>
<ns1:myAddress xmlns:ns1="http://test.wsrf.resource.sharing">
 <ns1:houseNumber>23</ns1:houseNumber>
 <ns1:streetName>Wilson Patten</ns1:streetName>
 <ns1:city>Daresbury</ns1:city>
 <ns1:county>Cheshire</ns1:county>
 <ns1:country>United kingdom</ns1:country>
</ns1:myAddress>
Name Changed !
Address Changed !
<ns1:myName xmlns:ns1="http://test.wsrf.resource.sharing">
 <ns1:title> Mr.</ns1:title>
 <ns1:firstName>AsIf</ns1:firstName>
 <ns1:lastName>AkRaM</ns1:lastName>
 <ns1:middleName>…</ns1:middleName>
</ns1:myName>
<ns1:myAddress xmlns:ns1="http://test.wsrf.resource.sharing">
 <ns1:houseNumber>38</ns1:houseNumber>
 <ns1:streetName>Hamilton Street</ns1:streetName>
 <ns1:city>London</ns1:city>
 <ns1:county>London</ns1:county>
 <ns1:country>United Kingdom</ns1:country>
</ns1:myAddress>
        

First part is printing the initial values of the Person resource, set in the PersonResoruce.java class and the second part is printing the modified values of the Person resource. In the client code we have something similar to:


String result = port.changeName(new Name("AsIf", "AkRaM", "…", " Mr."));
result = port2.changeAddress(new Address("London", "United Kingdom",
        "London", "38", "Hamilton Street"));
          

The important thing is that I am using different handlers for our Instance Services; "port" handler is for the PersonNameService to call changeName() method and the "port2" handler is for the PersonAddressService to call the changeAddress() method. Both method returns the String to confirm the successful execution.

My name hasn't changed during this tutorial so I have used mixture of uppercase and lowercase to differentiate it. Initial values are "Mr. Asif Akram" and changed values are "AsIf AkRaM". I have changed my address but it should be other way around as I moved here in the Daresbury from London but who knows I may move back to London. If you are wondering about Daresbury then:

"Daresbury Village is a charming place, and it's well worth spending a few hours here just wandering around. The village is situated in the Cheshire countryside and the birth place of Lewis Caroll who wrote the famous childrens book 'Alice's adventures in wonderland' ".



Back to top



Go to the previous pagePage 6 of 11Go to the next page

skip to main content

developerWorks  >  Grid computing | SOA and Web services  >

Resource Sharing among multiple Web Services, Part 1: Resource Sharing using Implied Resource Pattern

developerWorks
Go to the previous pagePage 7 of 11Go to the next page

Document options
PDF format - A4

PDF - A4
45KB (9 pages)

PDF format - letter

PDF - Letter
45KB (10 pages)

Get Adobe® Reader®

Sample code


Rate this tutorial

Help us improve this content


Links



Back to top



Go to the previous pagePage 7 of 11Go to the next page

skip to main content

developerWorks  >  Grid computing | SOA and Web services  >

Resource Sharing among multiple Web Services, Part 1: Resource Sharing using Implied Resource Pattern

developerWorks
Go to the previous pagePage 8 of 11Go to the next page

Document options
PDF format - A4

PDF - A4
45KB (9 pages)

PDF format - letter

PDF - Letter
45KB (10 pages)

Get Adobe® Reader®

Sample code


Rate this tutorial

Help us improve this content



Downloads

DescriptionNameSizeDownload method
Java implementation of sample codeResourceSharing-Part1.zip352KBHTTP
Web Services Resource 1.2 (wsrf-ws_resource-1.2-spec-os.pdf115KBHTTP
Web Services Resource Properties 1.2wsrf-ws_resource_properties-1.2-spec-os.pdf242KBHTTP
Web Services Lifetime 1.2wsrf-ws_resource_lifetime-1.2-spec-os.pdf190KBHTTP
Web Services Service Group 1.2wsrf-ws_service_group-1.2-spec-os.pdf169KBHTTP
Web Services Base Faults 1.2wsrf-ws_base_faults-1.2-spec-os.pdf90KBHTTP
Information about download methodsGet Adobe® Reader®

skip to main content

developerWorks  >  Grid computing | SOA and Web services  >

Resource Sharing among multiple Web Services, Part 1: Resource Sharing using Implied Resource Pattern

developerWorks
Go to the previous pagePage 9 of 11Go to the next page

Document options
PDF format - A4

PDF - A4
45KB (9 pages)

PDF format - letter

PDF - Letter
45KB (10 pages)

Get Adobe® Reader®

Sample code


Rate this tutorial

Help us improve this content


Resources

Learn

Get products and technologies
  • Download free Globus Toolkit , the best Grid Middleware.

  • Get open source Apache WSRF implementation of WSRF, which can be deployed on any Java ™ Web Server.

  • Downlaod IBM ETTK ® for Web Services , a software development kit for designing, developing, and executing emerging technologies and Web services.



Back to top



Go to the previous pagePage 9 of 11Go to the next page

skip to main content

developerWorks  >  Grid computing | SOA and Web services  >

Resource Sharing among multiple Web Services, Part 1: Resource Sharing using Implied Resource Pattern

developerWorks
Go to the previous pagePage 10 of 11Go to the next page

Document options
PDF format - A4

PDF - A4
45KB (9 pages)

PDF format - letter

PDF - Letter
45KB (10 pages)

Get Adobe® Reader®

Sample code


Rate this tutorial

Help us improve this content


About the author

Author1 photo

Asif Akram has done Chemical Engineering from Punjab University, Lahore, Pakistan. Since then he is in the IT research field and currently works in the CCLRC, one of Europe's largest multidisciplinary research organisations. Before joining CCLRC he was teaching in different universities and was associated with Cardiff University, Wales UK.



skip to main content

developerWorks  >  Grid computing | SOA and Web services  >

Resource Sharing among multiple Web Services, Part 1: Resource Sharing using Implied Resource Pattern

developerWorks
Go to the previous pagePage 11 of 11

Document options
PDF format - A4

PDF - A4
45KB (9 pages)

PDF format - letter

PDF - Letter
45KB (10 pages)

Get Adobe® Reader®

Sample code

Rate this tutorial


Please take a moment to complete this form to help us better serve you.



YesNoDon't know




12345


    About IBMPrivacyContact