Skip to main content

skip to main content

developerWorks  >  SOA and Web services  >

Implement and access stateful Web services using WebSphere Studio, Part 3

Accessing properties of a WS-Resource

developerWorks
Document options

Document options requiring JavaScript are not displayed

Sample code


Rate this page

Help us improve this content


Level: Intermediate

Hidayatullah Shaikh (hshaikh@us.ibm.com), Senior Software Engineer, IBM Corporation

08 Jun 2004

The Web Services Resource Framework proposes a model for accessing state using Web services. The WS-Resource Properties specification defines how you can use Web services technologies to query and change data associated with a stateful resource. This allows a standard means by which clients can access data associated with a WS-Resource. This article illustrates how you can use IBM® WebSphere® Studio Application Developer V5.1 to implement WS-Resource properties in a WebSphere Application Server environment.

The WS-Resource Properties specification describes the means by which service requestors can view and modify the type and values of a WS-Resource’s state through a Web services interface. The WS-Resource state is expressed as an XML resource property document using XML schema. The WS-Resource Properties specification standardizes the means by which the definition of a resource's properties may be declared as part of the Web service interface. It also defines a standard set of message exchanges that allow a requestor to query or update the property values of the implied resource instance.

In this article, I use a simple Calculator service example to show how you can specify and access WS-Resource properties in an IBM WebSphere Application Server environment.

Intended audience

You should have a basic understanding of J2EE technology, Web services, and WebSphere Application Server V5.1. If you are hoping to familiarize yourself with these technologies, please consult the Resources section of this article for quality sources of introductory material. You might also consult additional resources available at IBM developerWorks.

You should also read Part 1 and Part 2 in this series, "Accessing resources through services" and "Managing the lifecycle of WS-Resources," and become familiar with the Calculator example used in these articles (see Resources).



Back to top


Contents and requirements for the sample code

The samples referenced in this article were created with WebSphere Studio Application Developer V5.1.1 GM Version. The samples were also unit tested using the WebSphere Application Server V5.1 Built-in Test Environment. The WSDLs in the samples have been configured to use the tcpmon utility that comes with Apache Axis for monitoring the SOAP messages being exchanged. Configure the tcpmon utility to listen on port 81 (listenPort) and forward the requests to a target port of 9080 (targetPort). For more information on tcpmon refer to the Resources section of this article.

The file ws-statefulws3code.zip contains the code samples that accompany this article. You can download it by clicking on the Code icon at the top or bottom of this paper. It contains the following files:

WASv5WSAExtensions.jar A JAR file containing the utility classes that WebSphere Application Server V5.1 needs in order to create and access WS-Addressing message information headers in SOAP messages. Helper classes for manipulating WS-Addressing endpoint references are also included. These classes may be configured for use with WebSphere Studio applications.
WASvsWSAExtensions-javadoc.zip The javadoc for the utility classes.
CalculatorService.ear A sample stateful calculator service. A Web application is provided that allows the calculator service to be easily invoked.



Back to top


The calculator sample

The calculator sample introduced in Part 1 of this series provided a simple calculator service to client programs via a standard WSDL v1.1 interface. The service interface allowed clients to create instances of a calculator and subsequently add and subtract from the calculator total. Calculator instances are treated as WS-Resources in the sample. Also note that the Calculator Web service implementation was able to use existing J2EE best practices with the service interface implemented as a stateless session bean and the state maintained in a CMP entity bean.

This article takes you through the steps to selectively expose pieces of the calculator state as properties using the techniques described in the WS-Resource Properties specification. Specifically, you will:

  • Add an additional attribute request to the CalculatorState bean.
  • Create an XML Schema to represent the properties that are to be exposed from the WS-Resource.
  • Associate the resource properties with the Calculator service by attaching the schema to the Calculator service WSDL.
  • Update the Calculator service WSDL to include the WS-Resource property access operations that you plan to implement.
  • Extend the Calculator service implementation to support the new operations.

The instructions in this article help you modify the sample code in the first part of this series; when you are done with these modifications, you should have the code that looks like the code in ws-statefulws3code.zip.



Back to top


Modifying the CalculatorStateBean

For this example, the CalculatorState bean is modified to keep track of how many times the resource is accessed via the add, sub, and getTotal operations. To do this, you add an attribute called request to the CalculatorState bean. Further, you modify the add, sub, and getTotal methods to increment the request counter every time they are called. Listing 1 includes a code sample of the Calculator service's modified add method. For details, refer to the CalculatorServiceSoapBindingImpl.java file included in the CalculatorService.ear.


Listing 1. Implementation of add method
public float add(float value) {

	float _newTotal = 0f;

	try {
		CalculatorStateLocalHome home = getCalculatorStateHome();
		if (home != null) {
			String calcID = getPrimaryKeyFromContext();
			CalculatorStateLocal calculatorState =
				home.findByPrimaryKey(calcID);
			if (calculatorState != null) {
				_newTotal = calculatorState.getTotal() + value;
				calculatorState.setTotal(_newTotal);
 		      }
		      //Increment the request counter
		      int request = calculatorState.getRequest();
		      calculatorState.setRequest(++request);
	     }

	} catch (FinderException e) {
		e.printStackTrace();
	}

	return _newTotal;
}



Back to top


Defining resource properties document for the Calculator WS-Resources

The WS-Resource Properties specification defines the resource properties document as the XML document representing a logical composition of resource property elements. The resource properties document defines a particular view or projection of the state data implemented by the WS-Resource. The Calculator WS-Resource has three resource properties: calcid, request, and value. In the sample, you expose these as properties of the WS-Resources exposed via the Calculator service. You should be aware that I arbitrarily picked properties to expose from the Calculator service to illustrate the mechanics of implementing this. The WS-Resource Properties specification does not dictate what properties you are required to expose from a service. It is expected that over time, higher level, domain-specific specifications will emerge that define a style and best practice pattern for exposing resource properties. You can find early examples of this in the WS-Manageability specifications being produced by the OASIS WSDM Technical Committee (see Resources for more information on WS-Manageability and WSDM).

As per the WS-Resource Properties specification, the schema for resource properties should be added to the WSDL definition of the Web service through which the WS-Resource is exposed. Listing 2 shows this for the Calculator service WSDL. For details, you can refer to the CalculatorService.wsdl file included in the CalculatorService.ear.


Listing 2. Schema for the Calculator resource properties
...
   <!-- Resource property element declarations -->
   <element name="calcId" type="string"/>
   <element name="total" type="float"/>
   <element name="request" type="int"/>

   <!-- Resource properties document declaration -->   
   <element name="GenericCalculatorProperties">
       <complexType>
       <sequence>
           <element ref="intf:calcId"/>
           <element ref="intf:total"/>
           <element ref="intf:request"/>
       </sequence>
       </complexType>
   </element>
...


The WS-Resource Properties document declaration is associated with the WSDL portType definition via the use of the ResourceProperties attribute, as Listing 3 shows. For details, you can refer to the CalculatorService.wsdl file included in the CalculatorService.ear.


Listing 3. Associating resource property document with portType
...
<wsdl:portType name="CalculatorService" wsrp:ResourceProperties=
"intf:GenericCalculatorProperties">

...



Back to top


Adding WS-Resource Properties operations to the Calculator service

The WS-Resource Properties specification defines a collection of message exchanges that standardize the means by which a requestor can retrieve values of resource properties, update values of resource properties, and issue queries against resource properties. The WS-Resource Properties specification defines four operations:

  • GetResourceProperty: This operation allows a requestor to retrieve the value of a single resource property of a WS-Resource. A Web service implementing a portType that includes the resources properties document type declaration MUST support this operation.
  • GetMultipleResourceProperties: This operation allows a requestor to retrieve the values of multiple resource properties of a WS-Resource. Support for this operation is optional.
  • SetResourceProperties: This operation allows a requestor to modify the values of multiple resource properties of a WS-Resource. There are three types of changes that this operation allows -- insert, update, and delete. Support for this operation is optional.
  • QueryResourceProperties: This operation allows a requestor to query the resource properties document of a WS-Resource using a query expression such as XPath. Support for this operation is optional.

In this example, you extend the Calculator sample to support GetResourceProperty and the GetMultipleResourceProperties. A future article will discuss the implementation of the SetResourceProperties and QueryResourceProperties operations. Listing 4 shows the modification to the Calculator service WSDL to support the GetResourceProperty operation. Do the following to support the GetResourceProperty operation in the WSDL (repeat these steps for other WS-ResourceProperties operations):

  1. Paste the WS-ResourceProperties schema into the WSDL document. This schema contains the definition for the BaseFaultType and the GetRequestProperty request and response.
  2. Add WSDL messages for the various faults and the GetRequestProperty request and response as defined by the WS-Resource Properties specification.
  3. Add the GetResourceProperty operation to the CalculatorService portType.
  4. Add binding information for the GetResourceProperty operation to the soap binding of the CalculatorService.

Note that you only include the operations that you intend to implement in the WSDL. This ensures that any service requestor will have the ability to determine what operations are supported, as well as the properties that are accessible by introspecting the WSDL either manually or programmatically. For details on changes needed to support other operations, you can refer to the CalculatorService.wsdl file included in the CalculatorService.ear.


Listing 4. The GetResourceProperty operation added to the Calculator service WSDL
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://calculator.samples.ibm.com" ...>
  <wsdl:types>
    <xsd:schema targetNamespace=
    "http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceProperties" xmlns:wsrp=
"http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceProperties" ...>
              
    <!-- ======= Global Attribute Declaration for WSDL 1.1 portType==== -->
    <xsd:attribute name="ResourceProperties" type="xsd:QName"/>
    
      
<!-- ==== Common fault information to carry in all fault messages ==== -->       
       <xsd:complexType name="BaseFaultType">
          <xsd:sequence>
             <xsd:element maxOccurs="1" minOccurs="1" name="Timestamp" type=
             "xsd:dateTime"/>
             <xsd:element maxOccurs="1" minOccurs="0" name="Originator" type=
             "wsa:EndpointReferenceType"/>
                      
             <!-- 
             <xsd:element name="ErrorCode" 
                      minOccurs="0" maxOccurs="1">
                <xsd:complexType>
                   <xsd:complexContent mixed="true">
                      <xsd:extension base="xsd:anyType">
                         <xsd:attribute name="dialect" type="xsd:anyURI"
                                    use="required"/>
                      </xsd:extension>
                   </xsd:complexContent>
                </xsd:complexType>      
             </xsd:element>
             -->
             
             <xsd:element maxOccurs="unbounded" minOccurs="0" name=
             "Description" type="xsd:string"/>
             <xsd:element maxOccurs="unbounded" minOccurs="0" name=
             "FaultCause" type="wsrp:BaseFaultType"/> 
          </xsd:sequence>
       </xsd:complexType>

<!-- ========== Message Types for GetResourceProperty  ============ -->
       
       <xsd:element name="GetResourcePropertyRequest" type="xsd:QName"/>

       <xsd:element name="GetResourcePropertyResponse">
         <xsd:complexType>
           <xsd:sequence>
             <xsd:any maxOccurs="unbounded" minOccurs="0"/>
           </xsd:sequence>
         </xsd:complexType>
       </xsd:element>

      <xsd:complexType name="ResourceUnknownFaultType">
         <xsd:complexContent>
            <xsd:extension base="wsrp:BaseFaultType"/>
         </xsd:complexContent>
      </xsd:complexType>
      <xsd:element name="ResourceUnknownFault" type="wsrp:ResourceUnknownFaultType"/>

      <xsd:complexType name="InvalidResourcePropertyQNameFaultType">
         <xsd:complexContent>
            <xsd:extension base="wsrp:BaseFaultType"/>
         </xsd:complexContent>
      </xsd:complexType>
      <xsd:element name="InvalidResourcePropertyQNameFault" type=
      "wsrp:InvalidResourcePropertyQNameFaultType"/>

...

  <wsdl:message name="InvalidResourcePropertyQNameFault">
    <wsdl:part name="InvalidResourcePropertyQNameFault" element=
    "wsrp:InvalidResourcePropertyQNameFault"/>
  </wsdl:message>
  <wsdl:message name="GetResourcePropertyResponse">
    <wsdl:part name="GetResourcePropertyResponse" element=
    "wsrp:GetResourcePropertyResponse"/>
  </wsdl:message>
  <wsdl:message name="GetResourcePropertyRequest">
    <wsdl:part name="GetResourcePropertyRequest" element=
    "wsrp:GetResourcePropertyRequest"/>
  </wsdl:message>
  <wsdl:message name="ResourceUnknownFault">
    <wsdl:part name="ResourceUnknownFault" element=
    "wsrp:ResourceUnknownFault"/>
  </wsdl:message>

...

  <wsdl:portType name="CalculatorService" wsrp:ResourceProperties=
  "intf:GenericCalculatorProperties">
    <wsdl:operation name="GetResourceProperty">
      <wsdl:input name="GetResourcePropertyRequest" message=
      "impl:GetResourcePropertyRequest"/>
      <wsdl:output name="GetResourcePropertyResponse" message=
      "impl:GetResourcePropertyResponse"/>
      <wsdl:fault name="InvalidResourcePropertyQNameFault" message=
      "impl:InvalidResourcePropertyQNameFault"/>
      <wsdl:fault name="ResourceUnknownFault" message=
      "impl:ResourceUnknownFault"/>
    </wsdl:operation>
...
  </wsdl:portType>
  <wsdl:binding name="CalculatorServiceSoapBinding" type="impl:CalculatorService">
    <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="GetResourceProperty">
      <wsdlsoap:operation soapAction=""/>
      <wsdl:input name="GetResourcePropertyRequest">
        <wsdlsoap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="GetResourcePropertyResponse">
        <wsdlsoap:body use="literal"/>
      </wsdl:output>
      <wsdl:fault name="InvalidResourcePropertyQNameFault">
        <wsdlsoap:fault name="InvalidResourcePropertyQNameFault" use="literal"/>
      </wsdl:fault>
      <wsdl:fault name="ResourceUnknownFault">
        <wsdlsoap:fault name="ResourceUnknownFault" use="literal"/>
      </wsdl:fault>
    </wsdl:operation>
    ...
  </wsdl:binding>
...
</wsdl:definitions>


Listing 5 shows the service endpoint interface (SEI) that results when you run the updated WSDL through the WSDL2Java utility.


Listing 5. The service endpoint interface containing the WS-ResourceProperties methods
public interface CalculatorService extends Remote 
{

public GetResourcePropertyResponse
getResourceProperty(QName getResourcePropertyRequest) 
throws RemoteException,                      
       InvalidResourcePropertyQNameFaultType,          
       ResourceUnknownFaultType;

public GetMultipleResourcePropertiesResponse getMultipleResourceProperties(
GetMultipleResourcePropertiesRequest getMultipleResourcePropertiesRequest) 
throws RemoteException,                      
       InvalidResourcePropertyQNameFaultType, 
       ResourceUnknownFaultType;

public SOAPElement 
getCalculator(String accountName) 
throws RemoteException;

public float 
add(float value) 
throws RemoteException;

public float 
sub(float value) 
throws RemoteException;

public float 
getTotal() 
throws RemoteException;

}




Back to top


Implementing and invoking the WS-Resource Properties operations

Listing 6 shows the implementation of the GetResourceProperty method in the Calculator Web service. For details, refer to the CalculatorServiceSoapBindingImpl.java file included in the CalculatorService.ear.


Listing 6. Implementation of the GetResourceProperty method in the Calculator Web service
001  public com.ibm.samples.wsrp.GetResourcePropertyResponse
002  getResourceProperty(javax.xml.namespace.QName 
003  getResourcePropertyRequest) 
004    throws com.ibm.samples.wsrp.
       InvalidResourcePropertyQNameFaultType, 
005           com.ibm.samples.wsrp.ResourceUnknownFaultType 
006   {
007	GetResourcePropertyResponse   resourcePropertyResponse = null;
008		
009	if((getResourcePropertyRequest != null)&&
010		   011(getResourcePropertyRequest.getNamespaceURI().equals
011                      (CALCULATOR_NS)))
012	{
013		try {
014			CalculatorStateLocalHome home = 
015                       getCalculatorStateHome();
016			if (home != null) {
017				String calcID = getPrimaryKeyFromContext();
018				CalculatorStateLocal calculatorState =
019				    home.findByPrimaryKey(calcID);
020						
021				String name = 
022                     getResourcePropertyRequest.getLocalPart();
023				SOAPFactory sf = new SOAPFactory();
024				SOAPElement[] se = new SOAPElement[1];
025				se[0] = (SOAPElement) 
026                             sf.createElement(name, 
027                                              "calc", 
028                                              CALCULATOR_NS);
029
030				if(name.equals("calcId"))
031				{
032				    se[0].addTextNode(calcID);
033				    resourcePropertyResponse = new 
034                               GetResourcePropertyResponse();
035				    resourcePropertyResponse.set_any(se);
036					
037				}
038				else if(name.equals("total"))
039				{
040				    float total = calculatorState.getTotal();
041				    se[0].addTextNode(
042                                     (new Float(total)).toString());
043				    resourcePropertyResponse = new
044                               GetResourcePropertyResponse();
045				    resourcePropertyResponse.set_any(se);	
046
047				}
048				else if(name.equals("request"))
049				{
050				    int request = calculatorState.getRequest();
051				    se[0].addTextNode(
052                                 (new Integer(request)).toString());
053				    resourcePropertyResponse = new 
054                               GetResourcePropertyResponse();
055				    resourcePropertyResponse.set_any(se);
056				}
057				else
058				{
059				    String[] description 
060                             = {"Cannot find resource property"};
061				    throw new                                   
062                         InvalidResourcePropertyQNameFaultType
063                                 (Calendar.getInstance(), 
064                                  null, 
065                                  description, 
066                                  null);
067				
068				}
069				
070			}
071			} catch (FinderException e) {
072			e.printStackTrace();
073			String[] description = {"Cannot find resource"};
074			throw new ResourceUnknownFaultType
075                         (Calendar.getInstance(), 
076                          null, 
077                          description, 
078                          null);
079			} catch (SOAPException e) {
080				e.printStackTrace();
081			}		
082		
083		}		 	
084		else
085		{				
086			String[] description 
087                   = {"Cannot find resource property"};
088			throw new InvalidResourcePropertyQNameFaultType
089                         (Calendar.getInstance(), 
090                         null, 
091                         description, 
092                         null);
093		}
094     return resourcePropertyResponse;
095 }
096

Take a look at the above code sample in detail.

  1. In lines 9 through 11 you check to make sure that the getResourcePropertyRequest object is not null and that the namespace URI contained in it matches the namespace URI of the Calculator service.
  2. In lines 14 through 19, the calcID is first obtained from the reference properties and then used to find the right instance of the CalculatorState entity EJB component by calling the findByPrimaryKey method on the CalculatorState EJB home.
  3. In lines 23 through 29 you create a SOAP element using the Calculator service namespace. This SOAP element will be sent in the response object (resourcePropertyResponse).
  4. In lines 30 through 37 you see if the name contained in the getResourcePropertyRequest is calcId. If so, you set the value of the SOAP Element node (instantiated in step 3) to calcID (obtained in step 2). You further set the SOAP element in the resourcePropertyResponse response object.
  5. In lines 38 through 47 you see if the name contained in the getResourcePropertyRequest is total. If so, you get the value of total from the CalculatorState EJB instance (obtained in step 2) and set it in the SOAP element. You further set the SOAP element in the resourcePropertyResponse response object.
  6. In lines 48 through 56 you see if the name contained in the getResourcePropertyRequest is request. If so, you get the value of request from the CalculatorState EJB instance (obtained in step 2) and set it in the SOAP element. You further set the SOAP element in the resourcePropertyResponse response object.
  7. In lines 57 though 93 you throw different exceptions (defined in the WS-Resource Properties specification).
  8. In line 94 you return the resourcePropertyResponse object.

Listing 7 shows how a client invokes the GetResourceProperty operation provided by the Calculator Web service. For details, you can refer to the CalculatorTestExecute.jsp file included in the CalculatorService.ear. In this example, the client is interested in the resource property of the Calculator WS-Resource called total.


Listing 7. A sample client that wants to access a property of the calculator resource
com.ibm.samples.calculator.CalculatorService calculatorService = null;

// Initial Context
javax.naming.InitialContext ic = new javax.naming.InitialContext();

// Lookup calculator SI
// Returns object support javax.xml.rpc.Service
com.ibm.samples.calculator.CalculatorServiceService calculatorServiceSI 
 = (com.ibm.samples.calculator.CalculatorServiceService) ic.lookup(
 "java:comp/env/service/CalculatorServiceService");

// Get the calculator SEI
// Object that supports CalculatorService remote interface
//
calculatorService = 
(com.ibm.samples.calculator.CalculatorService) 
	  calculatorServiceSI.getPort(com.ibm.samples.calculator.CalculatorService.class);

if(calculatorService != null)
{
    try
    {
        String acctName = request.getParameter("acctName");

        float add 
            = (new Float(request.getParameter("add"))).floatValue();
        float sub 
            = (new Float(request.getParameter("sub"))).floatValue();
        
             
        javax.xml.soap.SOAPElement SE 
             = calculatorService.getCalculator(acctName);
        
        com.ibm.samples.wsa.wsaddr.EndpointReference epr 
        = com.ibm.samples.wsa.wsaddr.EndpointReference.fromSOAPElement(SE);   
                                            
	// Call JAXRPCHelper to associate EPR with account and 
      // make it stateful
	com.ibm.samples.wsa.utils.JAXRPCHelper.setEPR( 
                               (javax.xml.rpc.Stub) calculatorService , 
		                    epr);
      // Call a couple of other methods on calculator SEI		
      calculatorService.add(add);		
	calculatorService.sub(sub);
	javax.xml.namespace.QName rpQName 
		= new javax.xml.namespace.QName("http://calculator.samples.ibm.com", 
                          "total");
	com.ibm.samples.wsrp.GetResourcePropertyResponse getResourcePropertyResponse 
			= calculatorService.getResourceProperty(rpQName);
	    javax.xml.soap.SOAPElement[] se1 
                  =  getResourcePropertyResponse.get_any();

...


The GetResourceProperty request follows the implied resource pattern -- the identity values necessary for the service to identify the target implied resource are contained in the WS-Addressing reference properties. They must appear as part of the GetResourceProperty request message in the SOAP headers. Listing 8 and Listing 9 show the SOAP encoding of the GetResourceProperty message exchange.


Listing 8. GetResourceProperty request SOAP
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc=
"http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd=
"http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header xmlns:wsa="http://schemas.xmlsoap.org/ws/2003/03/addressing">
<wsa:To ...>
http://localhost:9080/CalculatorServiceWeb/services/CalculatorService
</wsa:To>
<calcID ...>
  1083949184296
</calcID>
<dummyProp...>
  EXAMPLE PROPERTY
</dummyProp>
</soapenv:Header>
<soapenv:Body>
     <GetResourceProperty xmlns="">
        <GetResourcePropertyRequest xmlns:ns-1495319864=
        "http://calculator.samples.ibm.com" xmlns=
        "http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceProperties">
         ns-1495319864:total
       </GetResourcePropertyRequest>
     </GetResourceProperty>
</soapenv:Body>
</soapenv:Envelope>





Listing 9. GetResourceProperty response SOAP message
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc=
"http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd=
"http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
     <GetResourcePropertyResponse xmlns="">
        <GetResourcePropertyResponse xmlns=
        "http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceProperties">
           <calc:total xmlns:calc="http://calculator.samples.ibm.com">5.0</calc:total>
        </GetResourcePropertyResponse>
     </GetResourcePropertyResponse>
</soapenv:Body>
</soapenv:Envelope>


Listing 10 shows the implementation of the GetMultipleResourceProperties method in the Calculator Web service. For details, refer to the CalculatorServiceSoapBindingImpl.java file included in the CalculatorService.ear. The implementation involves calling the getResourceProperty operation N number of times, where N is equal to the size of the QName array contained in the getMultipleResourcePropertiesRequest. The result of each invocation is collected into an array of SOAP elements and is then set in the resourcePropertiesResponse, which is returned to the client.


Listing 10. Implementation of the GetMultipleResourceProperties operation
public com.ibm.samples.wsrp.GetMultipleResourcePropertiesResponse
 getMultipleResourceProperties
(com.ibm.samples.wsrp.GetMultipleResourcePropertiesRequest
 getMultipleResourcePropertiesRequest) 
throws com.ibm.samples.wsrp.InvalidResourcePropertyQNameFaultType, 
       com.ibm.samples.wsrp.ResourceUnknownFaultType 
{

    QName[] resourceProperty 
        = getMultipleResourcePropertiesRequest.getResourceProperty();
    int size =  resourceProperty.length;
    SOAPElement[] se = new SOAPElement[size];
		
    GetMultipleResourcePropertiesResponse resourcePropertiesResponse 
        = null;
		
    if((resourceProperty != null)&&( size!= 0))
    {
        for(int i=0; i<size; i++)
	  {
		SOAPElement[] _se 
                = getResourceProperty(resourceProperty[i]).get_any();
		se[i] = _se[0];
	  }
			
	 resourcePropertiesResponse 
           = new GetMultipleResourcePropertiesResponse();
			
	 resourcePropertiesResponse.set_any(se);			        	
    }
    return resourcePropertiesResponse;
}



Listing 11 shows how a client invokes the GetMultipleResourceProperties operation provided by the Calculator Web service. For details, refer to the CalculatorTestExecute.jsp file included in the CalculatorService.ear. In this example, the client is interested in two resource properties of the Calculator WS-Resource -- total and request.


Listing 11. A sample client that wants to access multiple properties of the calculator resource
com.ibm.samples.calculator.CalculatorService calculatorService = null;

// Initial Context
javax.naming.InitialContext ic = new javax.naming.InitialContext();

// Lookup calculator SI
// Returns object support javax.xml.rpc.Service
com.ibm.samples.calculator.CalculatorServiceService calculatorServiceSI 
  = (com.ibm.samples.calculator.CalculatorServiceService) ic.lookup(
  "java:comp/env/service/CalculatorServiceService");

// Get the calculator SEI
// Object that supports CalculatorService remote interface
//
calculatorService = 
(com.ibm.samples.calculator.CalculatorService) 
	calculatorServiceSI.getPort(com.ibm.samples.calculator.CalculatorService.class);

if(calculatorService != null)
{
    try
    {
        String acctName = request.getParameter("acctName");

        float add 
            = (new Float(request.getParameter("add"))).floatValue();
        float sub 
            = (new Float(request.getParameter("sub"))).floatValue();
        
             
        javax.xml.soap.SOAPElement SE 
             = calculatorService.getCalculator(acctName);
        
        com.ibm.samples.wsa.wsaddr.EndpointReference epr 
        = com.ibm.samples.wsa.wsaddr.EndpointReference.fromSOAPElement(SE);   
                                            
	// Call JAXRPCHelper to associate EPR with account and 
      // make it stateful
	com.ibm.samples.wsa.utils.JAXRPCHelper.setEPR( 
                               (javax.xml.rpc.Stub) calculatorService , 
		                    epr);
      // Call a couple of other methods on calculator SEI		
      calculatorService.add(add);		
	calculatorService.sub(sub);
 ...
      com.ibm.samples.wsrp.GetMultipleResourcePropertiesRequest 
          getMultipleResourcePropertiesRequest =
      new com.ibm.samples.wsrp.GetMultipleResourcePropertiesRequest();

      javax.xml.namespace.QName[] resourceProperty 
          = new javax.xml.namespace.QName[2];
      resourceProperty[0] = new javax.xml.namespace.QName(
                            "http://calculator.samples.ibm.com", 
                            "total");
      resourceProperty[1] = new javax.xml.namespace.QName(
                            "http://calculator.samples.ibm.com",
                            "request");         
      getMultipleResourcePropertiesRequest.setResourceProperty(
                       resourceProperty);
        
      com.ibm.samples.wsrp.GetMultipleResourcePropertiesResponse 
          getMultipleResourcePropertiesResponse = 
          calculatorService.getMultipleResourceProperties(
              getMultipleResourcePropertiesRequest);

      javax.xml.soap.SOAPElement[] se 
          = getMultipleResourcePropertiesResponse.get_any();        

...



The GetMultipleResourceProperties request also follows the implied resource pattern. Listing 12 and Listing 13 show the SOAP encoding of the GetResourceProperty message exchange.


Listing 12. GetMultipleResourceProperties request SOAP message
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc=
"http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd=
"http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header xmlns:wsa="http://schemas.xmlsoap.org/ws/2003/03/addressing">
<wsa:To ...>
http://localhost:9080/CalculatorServiceWeb/services/CalculatorService
</wsa:To>
<calcID ...>
  1083949184296
</calcID>
<dummyProp...>
  EXAMPLE PROPERTY
</dummyProp>
</soapenv:Header>
<soapenv:Body>
      <GetMultipleResourceProperties xmlns="">
           <GetMultipleResourcePropertiesRequest xmlns=
           "http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceProperties">
               <ResourceProperty xmlns:ns-1495319864=
               "http://calculator.samples.ibm.com" xmlns=
               "">ns-1495319864:total</ResourceProperty>
               <ResourceProperty xmlns:ns-1495319864=
               "http://calculator.samples.ibm.com" xmlns=
               "">ns-1495319864:request</ResourceProperty>
           </GetMultipleResourcePropertiesRequest>
     </GetMultipleResourceProperties>
</soapenv:Body>
</soapenv:Envelope>






Listing 13. GetMultipleResourceProperties response SOAP message
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc=
"http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd=
"http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
   <GetMultipleResourcePropertiesResponse xmlns="">
      <GetMultipleResourcePropertiesResponse xmlns=
      "http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceProperties">
         <calc:total xmlns:calc="http://calculator.samples.ibm.com">5.0</calc:total>
         <calc:request xmlns:calc="http://calculator.samples.ibm.com">4</calc:request>
      </GetMultipleResourcePropertiesResponse>
   </GetMultipleResourcePropertiesResponse>
</soapenv:Body>
</soapenv:Envelope>






Back to top


Conclusions

This article provided a basic introduction of how service requestors define and access WS-Resource properties. It showed that the base service implementation which leverages J2EE best practices was easily extendible to support these new accessor operations. In particular, it showed you how to do a simple mapping of the QName defined in the properties document to an EJB Entity bean field containing that state. Similarly, you were able to leverage existing tooling to easily provide this implementation.

I expect that the optional operations introduced by WS-Resource properties will be increasingly easier to implement as other technologies emerge in this space. In particular, combining WS-transactions with Set Operation will give more structure and definition to update semantics. Similarly, some of the emerging technologies such as XMLBeans (see Resources) and Service Data Objects (see Resources) will allow us to better utilize the expressive power of XPATH. Using these structures as a construct to implement the query operation is an interesting item to prototype in the near future.



Back to top


Get the tools used in this article

If you are a developerWorks subscriber, you have a single user license to use WebSphere Studio Application Developer, and other DB2®, Lotus®, Rational®, Tivoli®, and WebSphere products -- including the Eclipse-based WebSphere Studio IDE -- to develop, test, evaluate, and demonstrate your applications. If you are not a subscriber, you can subscribe today.



Back to top


Acknowledgements

The author wishes to thank Sonny Fulkerson for reviewing this article and for providing technical guidance.




Back to top


Download

NameSizeDownload method
ws-statefulws3code.zipHTTP
Information about download methods


Resources



About the author

Hidayatullah H. Shaikh is a senior software engineer on the IBM Software Group's On Demand Architecture and Development Team. His areas of interest and expertise include business process modeling and integration, service-oriented architecture, grid computing, e-commerce, J2EE technology, and DBMSs. You can contact Hidayatullah at hshaikh@us.ibm.com.




Rate this page


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



 


 


Not
useful
Extremely
useful
 


Share this....

digg Digg this story del.icio.us del.icio.us Slashdot Slashdot it!



Back to top