Skip to main content

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

Model dynamic WS-Resources

Hidayatullah Shaikh (hshaikh@us.ibm.com), Senior Software Engineer, IBM Corporation
Hidayatullah H. Shaikh is a Senior Software Engineer on the IBM Software Group 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, enterprise Java, and database management systems. You can contact Hidayatullah at hshaikh@us.ibm.com.
Jaipaul Antony (jantony@us.ibm.com), Advisory Software Engineer, IBM Corporation
Jaipaul Antony is an Advisory Software Engineer with the eServer Advanced Systems Infrastructure Development team in IBM Systems and Technology Group. His areas of interest are primarily in the emerging fields of Web services and grid computing. You can contact Jaipaul at jantony@us.ibm.com.
Revathi Subramanian (revathi@us.ibm.com), Senior Software Engineer, IBM Corporation
Revathi Subramanian is a Senior Software Engineer with the Advanced Systems Infrastructure Development Team in IBM Systems Group. Her areas of expertise include e-commerce applications, grid computing, Java technology and Web services, while her real interests lie in natural language processing, speech recognition, creative writing, and foreign languages. You can contact Revathi at revathi@us.ibm.com.

Summary:  The Web Services Resource Properties specification defines how you can use Web services technology to query and change the data associated with a stateful WS-Resource, allowing a standard means by which a client can access data associated with a WS-Resource. Learn how Web services front-ending dynamic WS-Resources can interact with the actual physical resources in an IBM® WebSphere® Business Integration Server Foundation V5.1 environment using WebSphere Studio Application Developer Integration Edition V5.1.0.

Date:  27 Jul 2004
Level:  Advanced
Activity:  1104 views

Introduction

The Web Services Resource Framework (WS-Resource -- see Resources) defines a family of specifications for accessing stateful resources using Web services. Web services, by their nature, typically do not maintain state information during their interactions. However their interfaces must frequently allow for the manipulation of state, that is, data values that persist across and evolve as a result of Web services interactions. In the WS-Resource Framework state is modeled as stateful resources and the relationship between Web services is codified in terms of an implied resource pattern.

Previously in this series, we used a simple Calculator as a stateful resource. In this installment we pick a more complex real-life example in the System Management domain and show how you can present to the client the properties and operations of that resource through a Web services interface and tie the Web services implementation to the actual physical resource.

There are various standards that provide definition of management information for systems. We chose the Distributed Management Task Force (DMTF) Common Information Model (CIM) standard. CIM provides a common definition of management information for systems, networks, applications, and services and allows for vendor extensions. CIM’s common definitions enable vendors to exchange semantically-rich management information between systems throughout the network. We also chose the OperatingSystem WS-Resource which has properties like name, version, virtual memory, and so forth.

Intended audience

We recommend that you have a basic understanding of J2EE technology, Web services, and WebSphere Business Integration Server Foundation V5.1. If you are hoping to familiarize yourself with these technologies, please consult the Resources section of this paper for links to good introductory material. We also suggest you consult additional resources available at IBM developerWorks. We also recommend that you read the first three articles in this series (see Resources) and are familiar with the WS-Resource Framework concepts.

Contents and requirements for the sample code

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

The file ws-statefulws4code.zip contains the code samples that accompany this paper. You can download the file by clicking on the Code icon at the top or bottom of this paper. The zip file 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 (EPRs) are also included. These classes may be configured for use with WebSphere Studio applications.
  • WASvsWSAExtensions-javadoc.zip: The javadoc for the utility classes.
  • CimConnector.rar: A RAR file containing the J2EE CIM Connector.
  • OperatingSystem.ear: A sample stateful operating system service. A Web application is provided that allows the operating system service to be easily invoked.

Container Managed Persistence over Anything (CMP/A)

Before the release of WebSphere Business Integration Server Foundation V5.1, Container Managed Persistence (CMP) supported a number of relational back-end systems. Container Managed Persistence over Anything (CMP/A) extends the CMP entity to support any back-end system that supports create, retrieve, update, and delete methods. To represent non-relational entities in J2EE technology, you would normally use Bean Managed Persistence, which requires you to deal with all of the connection logic that must go directly into the bean implementation class. Instead, CMP/A lets you represent entities that existed in a business model, including non-relational back-end systems using a simple CMP entity.

This means that you can define methods on a CMP bean that, rather than being implemented by you (in a BMP style of putting connection logic directly in the EJB component's method implementation), are instead handled by the container and deployment tools. You can accomplish this by defining the method as abstract, and then marking new EJB Extended deployment descriptor settings for these methods as pushdowns. The tool generates the bean's UserDefinedPushDownMethods interface, and generates skeleton Java source code for the bean's UserDefinedPushDownMethodsImpl class. You must fill this class in with the appropriate logic, compile it, and package it into the appropriate EJB JAR file.

For more information on CMP/A, you can refer to the IBM WebSphere Business Integration Server Foundation, Version 5.1: Applications document (see Resources).


CIM and Pegasus CIMOM

CIM is a DMTF standard and a model for describing overall management information in a network or enterprise environment. CIM is comprised of a specification and a schema. The CIM specification is the language and methodology for describing management data. The CIM schema includes models for systems, applications, networks (LAN) and devices. The CIM schema is extensible and enables applications from different developers on different platforms to describe management data in a standard format so that it can be shared among a variety of management applications. To learn more about CIM and the CIM standards, please visit the DMTF Web site (see Resources).

The CIM client can exchange information with the CIM server using CIM-XML, which is a standard protocol for information exchange in CIM. A central component in the CIM server is the CIM Object Manager, or CIMOM, that handles the interaction between management applications and providers. The CIMOM supports services such as event notification, remote access, and query processing.


Figure 1. CIM Server
Figure 1. CIM Server

The Open Group's Pegasus open source project develops one of the most popular CIMOM implementations (see Resources). For Linux systems, the Standards Based Linux Instrumentation for Manageability (SBLIM) project offers another implementation of the CIM schema (see Resources). You can use these providers with Pegasus to manage additional Linux resources in a CIM environment. For the purposes of this demonstration, we ask that you install the Pegasus CIMOM along with the SBLIM base providers. The install instructions are provided later in the section Install the Pegasus CIMOM of this paper.


CIM J2EE Connector Architecture (JCA) Adapter

The J2EE Connector Architecture (JCA) enables J2EE components such as enterprise beans to communicate with heterogeneous information systems, such as ERP systems, mainframe systems or, in our case, a CIMOM. The JCA specification defines a set of interfaces that allows development of pluggable application server components called resource adapters. You can deploy a JCA-compliant resource adapter to any J2EE-compliant application server. J2EE components running within the application server make calls to the resource adapter through the Common Client Interface (CCI), and the resource adapter translates these calls into corresponding calls on the underlying information system using a native protocol. For more information, refer to the JCA specification (see Resources).

A JCA-compliant resource adapter for CIM is included with the IBM Grid Toolbox (see Resources). This is a very light-weight resource adapter which knows how to communicate with the CIMOM using CIM-XML/HTTP. The CIM-XML message itself is composed or parsed externally to the resource adapter. So, the resource adapter acts as a simple conduit, and the knowledge of how to map Web services operations to CIM operations and vice-versa resides in a separate component. Figure 2 shows the conceptual flow when a Web service operation is invoked.


Figure 2. Conceptual flow for a Web services operation invocation
Figure 2. Conceptual flow for a Web services operation invocation

At deployment time, you must install the CIM resource adapter into the J2EE server and configure a connection factory for the specific CIMOM location.


The OperatingSystem sample

To demonstrate the use of CMP/A entity bean to push-down operations made on a stateful resource, we define the OperatingSystem WS-Resource using WSDL. We follow the instructions in Part 1 of this series to implement the "Implied Resource Pattern" as described in the "Modeling stateful resources" paper (see Resources). The operations to find all operating systems and to get ResourceProperties are "pushed down" by editing the deployment descriptor for CMP/A EJB. The actual OperatingSystem WS-Resource is instrumented by a Pegasus instrumentation provider for operating systems and is accessed using a JCA adapter to the Pegasus CIMOM, as Figure 3shows.


Figure 3. The OperatingSystem Web service
Figure 3. The OperatingSystem Web service

The sample in this paper consists of a test client that is implemented as a JSP file. This JSP file invokes a findAllOperatingSystems operation on the OperatingSystem service, which returns a list of endpoint references (EPRs) for all WS-Resources of the OperatingSystem at the CIMOM server. The test client then invokes a getResourceProperty operation on the first OperatingSystem WS-Resource that the findAllOperatingSystems operation returns.


Resource properties document for the OperatingSystem WS-Resource

Now let's look into defining the properties of the OperatingSystem WS-Resource. The WS-ResourceProperties specification (see Resources) defines the ResourceProperties document as the XML document representing a logical composition of ResourceProperty elements. The ResourceProperties document defines a particular view or projection of the state data that the WS-Resource implements. The OperatingSystem WS-Resource has the following ResourceProperties:

Resource Property NameDescriptions
NameThe name of the operating system.
OperationalStatusA string indicating the current health and operational status of the operating system.
CSNameThe name of the computer system on which the operating system is running.
OSTypeA string indicating the type of the operating system (for example, Linux, AIX, Win2000)
VersionThe operating system's version number.
numberOfUsersNumber of user sessions for which the operating system is currently storing state information.
numberOfProcessesNumber of process contexts currently loaded or running on the operating system.
totalSwapSpaceSizeTotal swap space in Kbytes. This value may be NULL (unspecified) if swap space is not distinguished from page files. However, some operating systems distinguish these concepts. For example, in UNIX, whole processes can be "swapped out" when the free page list falls and remains below a specified amount.
totalVirtualMemorySizeNumber of Kbytes of virtual memory.
freeVirtualMemoryNumber of Kbytes of virtual memory currently unused and available.
freePhysicalMemoryNumber of Kbytes of physical memory currently unused and available.
totalVisibleMemorySizeThe total amount of physical memory (in Kbytes) available to the OperatingSystem. This value does not necessarily indicate the true amount of physical memory, but what is reported to the operating system as available to it.

According to the WS-ResourceProperties specification, you should add the schema for ResourceProperties to the WSDL definition of the Web service through which you expose the WS-Resource. Listing 1 shows the schema for the ResourceProperties of the OperatingSystem WSDL. For additional details, please refer to the OperatingSystem.wsdl file included in the OperatingSystem.ear file.


Listing 1. Schema for the OperatingSystem ResourceProperties
<xsd:element name="Name" type="os:NameType" />

<xsd:element name="OperationalStatus">
<xsd:complexType>
	<xsd:sequence>
	<xsd:element name="state" 
			 type="os:OperationalStateType" 
			 minOccurs="0" 	
			 maxOccurs="unbounded" />
	</xsd:sequence>
</xsd:complexType>
</xsd:element>
			
<xsd:element name="CSName" type="os:CSNameType" />
<xsd:element name="OSType" type="os:OSTypeType" />
<xsd:element name="version" type="os:versionType" />
<xsd:element name="numberOfUsers" type="xsd:integer"/>
<xsd:element name="numberOfProcesses" type="xsd:integer"/>
<xsd:element name="totalSwapSpaceSize" type="xsd:long"/>
<xsd:element name="totalVirtualMemorySize" type="xsd:long" />
<xsd:element name="freeVirtualMemory" type="xsd:integer"/>
<xsd:element name="freePhysicalMemory" type="xsd:integer"/>
<xsd:element name="totalVisibleMemorySize" type="xsd:long" />
			
<!-- RPDoc declaration for OS -->
<xsd:element name="OSProperties" type="os:OSPropertiesType"/>

<xsd:complexType name="OSPropertiesType">
<xsd:sequence>
	<xsd:element ref="os:Name"/>
	<xsd:element ref="os:OperationalStatus"/>
	<xsd:element ref="os:CSName" />
	<xsd:element ref="os:OSType" />
	<xsd:element ref="os:version"/>
	<xsd:element ref="os:numberOfUsers" />
	<xsd:element ref="os:numberOfProcesses" />
	<xsd:element ref="os:totalSwapSpaceSize" />
	<xsd:element ref="os:totalVirtualMemorySize" />
	<xsd:element ref="os:freeVirtualMemory" />
	<xsd:element ref="os:freePhysicalMemory" />
	<xsd:element ref="os:totalVisibleMemorySize" />
	<xsd:element ref="os:resourceID" minOccurs="1" maxOccurs="1" />
	<xsd:element ref="wsrl:CurrentTime" minOccurs="1" maxOccurs="1"/>
	<xsd:element ref="wsrl:TerminationTime" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>		
</xsd:complexType>

The WS-ResourceProperties document declaration is associated with the WSDL portType definition using the ResourceProperties attribute, as shown in Listing 2. For details, please refer to the OperatingSystem.wsdl file included in the OperatingSystem.ear file.


Listing 2. Associate ResourceProperty document with port type
<wsdl:portType name="OperatingSystem" wsrp:ResourceProperties="os: OSProperties">
...


Define the OperatingSystem interface

The OperatingSystem interface supports two operations: findAllOperatingSystems and GetResourceProperty.

  • findAllOperatingSystems: This is envisioned as a bootstrap operation on the OperatingSystem Web service. A Web services client that knows the address (URL) of the OperatingSystem Web service can invoke this operation to get back a list of EPRs to OperatingSystem WS-Resources. The client can then use one or more of the EPRs to drive down additional operations against specific OperatingSystem instances (such as GetResourceProperty).
  • GetResourceProperty: According to the WS-ResourceProperties specification, any Web service implementing a portType that exposes a ResourceProperty document MUST implement the GetResourceProperty method exchange. In the context of the OperatingSystem WSDL, this operation lets users retrieve a single ResourceProperty (using its QName) of the OperatingSystem WS-Resource.

Listing 3 shows the two operations defined in the WSDL. For additional details with respect to parts, messages and bindings for each of these operations, please refer to the OperatingSystem.wsdl file in the OperatingSystem.ear file.


Listing 3. OperatingSystem port type definition.
			...
<!-- =================== PortType Definitions ===================== -->
<wsdl:portType name="OperatingSystem" wsrp:ResourceProperties="os:OSProperties">
    
 <!-- findAll, typically, will be the first discovery operation by the client. 
      The result of the operation is an array of EPRs -->
 <wsdl:operation name="findAllOperatingSystems">
      <wsdl:input  message="os:findAllOperatingSystemsInputMessage" 
                   name="findAllOperatingSystemsInput"/>
      <wsdl:output message="os:findAllOperatingSystemsOutputMessage" 
                   name="findAllOperatingSystemsOutput"/>
 </wsdl:operation>

<!-- ========= GetResourceProperty: WS-ResourceProperties ====== -->    
<wsdl:operation name="GetResourceProperty">
      <wsdl:input   name="GetResourcePropertyRequest" 
                    message="wsrp:GetResourcePropertyRequest" />
       <wsdl:output name="GetResourcePropertyResponse" 
                    message="wsrp:GetResourcePropertyResponse" />
       <wsdl:fault  name="ResourceUnknownFault" 
                    message="wsrp:ResourceUnknownFault" />
        <wsdl:fault  name="InvalidResourcePropertyQNameFault" 
                     message="wsrp:InvalidResourcePropertyQNameFault" />
</wsdl:operation>
</wsdl:portType>
...

Listing 4 shows the Service Endpoint Interface (SEI) that results when you run the OperatingSystem WSDL through the WSDL2Java utility.


Listing 4. The service endpoint interface containing the OperatingSystem methods
package com.ibm.samples.ws.os;

public interface OperatingSystem extends java.rmi.Remote 
{

public com.ibm.samples.ws.os.EPRArray 
findAllOperatingSystems() 
throws java.rmi.RemoteException;

public com.ibm.ws.stateful.wsrp.GetResponsePropertyType getResourceProperty(
javax.xml.namespace.QName getResourcePropertyRequest) 
throws java.rmi.RemoteException,  
       com.ibm.ws.stateful.wsrp.InvalidResourcePropertyQNameFaultType, 
       com.ibm.ws.stateful.wsrp.ResourceUnknownFaultType;
}


Implement the OperatingSystem operations

The OperatingSystem service implementation uses existing J2EE best practices with the service interface implemented as a stateless session bean -- OperatingSystemSoapBindingImpl -- and the state maintained in a CMP/A entity bean -- OperatingSystemResource. The ResourceProperties of the OperatingSystem WS-Resource are defined as attributes on the OperatingSystemResource bean.

Let's take a look at the implementation of getResouceProperty operation of the OperatingSystem Web service as the code snippet in Listing 5 shows. For details you can refer to the OperatingSystemSoapBindingImpl.java file included in the OperatingSystem.ear file.


Listing 5. Implementation of the GetResourceProperty operation
001 public GetResponsePropertyType getResourceProperty(
002     QName getResourcePropertyRequest) 
003      throws ... {
004    
005     GetResponsePropertyType resp = null;
006     OperatingSystemResourceLocal osResource = null;
007
008     try {
009
010         //
011         // get the WS-Resource addressed by this EPR.
012         //
013         osResource = getOSResource();
014
015     } catch (SOAPException e) {
016         ...
017     }
018    
019     //
020     // get the Requested ResourceProperty.
021     //
022     Object[] objs = getResourceProperty(
023                         osResource, 
024                         getResourcePropertyRequest);
025    
026     resp = new GetResponsePropertyType();
027     resp.set_Any(objs); // set the resource property.
028    
029     return resp;
030 }
031
032
033 private OperatingSystemResourceLocal getOSResource() throws ... {
034
035     ...
036
037     //
038     // get the primary key from context.
039     //
040    OperatingSystemResourceKey osKey = new 
041 OperatingSystemResourceKey();
042    
043     osKey.csCreationClassName = 
044         EPRHelper.getReferencePropertyFromContext(OS_NS,
045         "csCreationClassName");
046     osKey.csName = 
047         EPRHelper.getReferencePropertyFromContext(OS_NS, 
048         "csName");
049     osKey.creationClassName = 
050         EPRHelper.getReferencePropertyFromContext(OS_NS, 
051         "creationClassName");
052     osKey.name = 
053         EPRHelper.getReferencePropertyFromContext(OS_NS, 
054         "name");
055
056     ...
057
058     //
059     // find the resource using the primary key.
060     //
061     ...
062    
063     try {
064         osBean = osHome.findByPrimaryKey(osKey);
065     } catch (FinderException e) {
066         ...
067     }
068
069     ...
070
071     return osBean;
072 }
073
074
075 private Object[] getResourceProperty(
076                     OperatingSystemResourceLocal osResource, 
077                     QName getResourcePropertyRequest) {
078     ...
079    
080     //
081     // get the localpart of the qname for the property.
082     // not using the namespace qualifier.
083     // match case sensitive.
084    String propName = 
085         getResourcePropertyRequest.getLocalPart().toUpperCase(); 
086
087     //
088     // Find the accessor 'get'method on the impl obj that matches 
089     // the local part of the qname.
090     //     
091     Method[] methods = osResource.getClass().getMethods();
092     Method method = null;
093     for (int i = 0; i <methods.length; i++) {
094         if (mname.equalsIgnoreCase("get"+propName)) {
095             method = methods[i];
096             break;
097         }
098     }
099    
100     //
101    // exec the method.
102     //
103    try {
104        objs[0] = method.invoke(osResource, null);
105    } catch ( ... ) {
106        ...
107    }
108
109    return objs;

Let's take a look at the above code snippet in detail:

  1. In the above code listing, lines 1-30 are the implementation of the getResouceProperty operation. It uses two private helper methods: getOSResource, and getResourceProperty.
  2. Lines 41-54 shows how the primary key is created from an EPR by making use of the EPRHelper utility class, included in the WASv5WSAExtensions.jar library. Once the primary key is obtained, the OperatingSystem WS-Resource is located by invoking the findByPrimaryKey method on the OperatingSystemResource's Home.
  3. The method name for accessing the ResourceProperty is created by prefixing the localpart of the ResourceProperty’s QName with get. It is assumed that for each ResourceProperty for the OperatingSystem there is a corresponding getter defined on the bean. Once the method is located (lines 091-097), it is invoked using standard the Java reflection API.
  4. The findByPrimaryKey operation is defined as a CMP/A push-down method in the EJB deployment descriptor for the OperatingSystemResource entity bean.

Now let's take a look at the push down method for the findByPrimaryKey operation of the OperatingSystemResource bean. Based on the CMP/A naming convention, the push-down method is called ejbFindByPrimaryKey, as the code snippet in Listing 6 shows. For details you can refer to the OperatingSystemResourceBeanUserDefinedPushDown-MethodsImpl.java file included in the OperatingSystem.ear file.


Listing 6. Implementation of the ejbFindByPrimaryKey push-down method
001 public Record ejbFindByPrimaryKey(OperatingSystemResourceKey arg0, ...)
002   throws ...
003 {
004     ...
005
006   IndexedRecord returnValue = helper.createCCIIndexedRecord();
007   try {
008     ...
009
010      //
011      // create the cimxml request document to get the instance.
012      //
013      Document cimRequest = getInstanceCIMRequest(arg0);
014      Document cimResponse = sendCIMXML(
015                                 cimRequest, 
016                                 "eis/CimConnector1", 
017                                 "GetInstance");
018     
019      Node instanceNode = XPathAPI.selectSingleNode(cimResponse, 
020                                                    "//INSTANCE");
021     
022      returnValue.add(convertToIndexedRecord(instanceNode));
023    
024    ...
025   } catch (Exception e) {
026     ...
027   }
028     ...
029
030   return returnValue;
031 }

In the above code listing:

  1. On line 013, a cimRequest Document is created using the getInstanceCIMRequest private helper method. This method creates a CIM-XML document to get the instance of the OperatingSystem WS-Resource.
  2. On line 014, the cimRequest Document is sent to the CIMOM through the CIM JCA adapter. eis/CimConnector1 is the JNDI name of the CIM JCA adapter connection factory that is configured in the WebSphere Application Server. This result is returned as a CIM-XML document.
  3. Line 019 shows how the INSTANCE node is selected from the cimResponse document using the XPathAPI.
  4. Line 022. The node is converted into an IndexedRecord using the private helper function convertToIndexedRecord and added into the IndexedRecord that is returned.

Listings 7 and 8 show a sample CIM-XML message exchange -- request and response -- with the CIMOM (over HTTP) in the push-down method through the CIM Adapter.


Listing 7. Sample CIMXML request
<?xml version="1.0" encoding="UTF-8"?>
<CIM CIMVERSION="2.0" DTDVERSION="2.0">
    <MESSAGE ID="1088435131213" PROTOCOLVERSION="1.0">
        <SIMPLEREQ>
            <IMETHODCALL NAME="GetInstance">
                <LOCALNAMESPACEPATH>
                    <NAMESPACE NAME="root"/>
                    <NAMESPACE NAME="cimv2"/>
                </LOCALNAMESPACEPATH>
                <IPARAMVALUE NAME="InstanceName">
                    <INSTANCENAME CLASSNAME="Linux_OperatingSystem">
                        <KEYBINDING NAME="CreationClassName">
                            <KEYVALUE VALUETYPE="string">
                                Linux_OperatingSystem
                            </KEYVALUE>
                        </KEYBINDING>
                        <KEYBINDING NAME="CSCreationClassName">
                            <KEYVALUE VALUETYPE="string">
                                Linux_ComputerSystem
                            </KEYVALUE>
                        </KEYBINDING>
                        <KEYBINDING NAME="CSName">
                            <KEYVALUE VALUETYPE="string">
                                hazelrah.pok.ibm.com
                            </KEYVALUE>
                        </KEYBINDING>
                        <KEYBINDING NAME="Name">
                            <KEYVALUE VALUETYPE="string">
                                hazelrah.pok.ibm.com
                            </KEYVALUE>
                        </KEYBINDING>
                    </INSTANCENAME>
                </IPARAMVALUE>
                <IPARAMVALUE NAME="LOCALONLY">
                    <VALUE>TRUE</VALUE>
                </IPARAMVALUE>
                <IPARAMVALUE NAME="IncludeQualifiers">
                    <VALUE>TRUE</VALUE>
                </IPARAMVALUE>
                <IPARAMVALUE NAME="IncludeClassOrigin">
                    <VALUE>FALSE</VALUE>
                </IPARAMVALUE>
            </IMETHODCALL>
        </SIMPLEREQ>
    </MESSAGE>
</CIM>




Listing 8. Sample CIMXML response
<?xml version="1.0" encoding="utf-8" ?>
<CIM CIMVERSION="2.0" DTDVERSION="2.0">
<MESSAGE ID="1088604271024" PROTOCOLVERSION="1.0">
	<SIMPLERSP>
	<IMETHODRESPONSE NAME="GetInstance">
		<IRETURNVALUE>
		<INSTANCE CLASSNAME="Linux_OperatingSystem">
			<PROPERTY NAME="Caption" TYPE="string">
				<VALUE>Operating System</VALUE>
			</PROPERTY>
			<PROPERTY NAME="Description" TYPE="string">
				<VALUE>A class derived from OperatingSystem to 
				represents the running Linux OS.</VALUE>
			</PROPERTY>
			<PROPERTY NAME="ElementName" TYPE="string">
				<VALUE<Red Hat Linux release 8.0 (Psyche)</VALUE>
			</PROPERTY>
			<PROPERTY NAME="InstallDate" TYPE="datetime">
				<VALUE>20030203094856.000000-240</VALUE>
			</PROPERTY>
                  ...
			<PROPERTY NAME="OSType" TYPE="uint16">
				<VALUE>36</VALUE>
			</PROPERTY>
			...
			<PROPERTY NAME="Version" TYPE="string">
				<VALUE>Red Hat Linux release 8.0 (Psyche)</VALUE>
			</PROPERTY>
			...
			<PROPERTY NAME="FreeVirtualMemory" TYPE="uint64">
				<VALUE>1605008</VALUE>
			</PROPERTY>
			<PROPERTY NAME="FreePhysicalMemory" TYPE="uint64">
				<VALUE>60064</VALUE>
			</PROPERTY>
			<PROPERTY NAME="TotalVisibleMemorySize" TYPE="uint64">
				<VALUE>772412</VALUE>
			</PROPERTY>
			<PROPERTY NAME="SizeStoredInPagingFiles" TYPE="uint64">
				<VALUE>1566328</VALUE>
			</PROPERTY>
			<PROPERTY NAME="FreeSpaceInPagingFiles" TYPE="uint64">
				<VALUE>1526548</VALUE>
			</PROPERTY>
			<PROPERTY NAME="MaxProcessMemorySize" TYPE="uint64">
				<VALUE>4294967295</VALUE>
			</PROPERTY>
			<PROPERTY NAME="Distributed" TYPE="boolean">
				<VALUE>FALSE</VALUE>
			</PROPERTY>
			...
		</INSTANCE>
	</IRETURNVALUE>
	</IMETHODRESPONSE>
</SIMPLERSP>
</MESSAGE>
</CIM>

The OperatingSystem Web service's findAllOperatingSystem operation implementation is similar to the getResourceProperty's implementation. In this case, there is no primary key available in the EPR. This method is also "pushed down" to CMP/A. For more information you can refer to the OperatingSystemSoapBindingImpl.java and OperatingSystemResourceBeanUserDefinedPushDownMethodsImpl.java files included in the OperatingSystem.ear file.


CIM mapping explained

In this example, for each push-down method, there is a corresponding CIM operation that needs to be invoked. The results of that CIM operation must be parsed and converted into appropriate "results" on one or more bean instances. In this section we explain the details of the CIM mappings for the two operations.

The following assumptions are made in the CIM mapping:

  • All connections are made to a CIM namespace called root/cimv2. This is the default CIM namespace that comes with your Pegasus installation.
  • The OperatingSystem EJB component maps to the CIM_OperatingSystem class. This mapping is explicitly assumed and hardcoded.
  • The OperatingSystem primary key maps by name to the keys of the CIM_OperatingSystem class.
  • The OperatingSystem type is Linux.

a. FindAllOperatingSystems: In this method, the objective is to get a set of operating systems known to the CIMOM and activate a set of entity bean instances corresponding to the retrieved set. You can accomplish this as follows:

  1. Compose a CIM-XML request document to invoke an EnumerateInstances operation against the CIMOM for resource type CIM_OperatingSystem.
  2. Send this CIM-XML to the CIMOM using the CIM resource adapter's sendCIMXML method.
  3. The results coming back from the CIMOM will contain a list of one or more operating system instances.
  4. Parse the incoming CIM-XML response and extract the XML snippet corresponding to each OperatingSystem instance. The use of XPathAPI to achieve this was shown in Listing 6.
  5. For each extracted instance, perform additional XPath selects in order to retrieve the values for specific CIM properties. Convert each of the CIM properties to the appropriate CMP field types. Note: Some ResourceProperties may not be available in CIM; also the Web services does not expose many of the CIM properties.

The mappings between CMP fields and CIM properties are known at build time. For the purposes of this example, a simple name-based mapping is assumed. Therefore, in order to populate the IndexedRecord with the value of the CMP field Version, the CIM-XML response would be parsed in order to get the corresponding value for the CIM property Version as shown in the code snippet in Listing 9:


Listing 9. Implementation of convertToIndexedRecord method
private IndexedRecord convertToIndexedRecord(Node instanceNode) {
	
  IndexedRecord ir = null;
  try {
      ir = helper.createCCIIndexedRecord();
  } catch (ResourceException e) {
      e.printStackTrace();
  }
  String value = "";
		
  value = getValue(instanceNode, "//PROPERTY[@NAME=\"CreationClassName\"]");
  ir.add(value); value = "";
  …
  …
  …
  value = getValue(instanceNode, "//PROPERTY[@NAME=\"Version\"]");
  ir.add(value); value = "";
  return ir;
}

  1. For each extracted instance, compose an IndexedRecord with the ResourceProperties (CMP fields) in the right order. The order is dictated by container and MUST be correct. The order of CMP fields is helpfully generated as part of the javadoc for the push-down method. Null values are not allowed in the IndexedRecord.
  2. Return an IndexedRecord that contains IndexedRecords corresponding to individual OperatingSystem instances. The container uses this IndexedRecord collection in order to initialize and activate EJB instances.

b. FindByPrimaryKey: In this method, the objective is to get back a single OperatingSystem instance from the CIMOM using the primary keys of an entity bean. There is a need to convert these keys into CIM properties and invoke an appropriate operation against the CIMOM, parse the results of this operation, and successfully populate an entity bean. You can accomplish this as follows:

  1. Compose a CIM-XML request document to invoke a GetInstance operation against the CIMOM for resource type CIM_OperatingSystem.
  2. Send this CIM-XML to the CIMOM using the CIM resource adapter's sendCIMXML method.
  3. The results coming back from the CIMOM will contain at most one OperatingSystem instance.
  4. Perform additional XPath selects in order to retrieve the values for specific CIM properties.
  5. Compose an IndexedRecord with the ResourceProperties (CMP fields) in the right order. The order is dictated by container and MUST be correct. The order of CMP fields is helpfully generated as part of the javadoc for the push-down method. Null values are not allowed in the IndexedRecord.
  6. Return this IndexedRecord which will then be used by the container in order to activate and populate the EJB instance.

Invoke the OperatingSystem operations

Now let's take a look at how a client invokes the various operations that we implemented in the previous section. Listing 10 shows a code snippet. For details, you can refer to the TestOS.jsp file included in the OperatingSystem.ear file.


Listing 10. Sample client code
001 try {
002     // Lookup OS SI
003     com.ibm.samples.ws.os.OperatingSystemService osSI =
004        (com.ibm.samples.ws.os.OperatingSystemService)   
005         ic.lookup("java:comp/env/service/OperatingSystemService");
006	
007     ...
008	
009     // Get the OS SEI
010     com.ibm.samples.ws.os.OperatingSystem os =
011 	 (com.ibm.samples.ws.os.OperatingSystem) 
012         osSI.getPort(com.ibm.samples.ws.os.OperatingSystem.class);
013	
014     ...
015	
016     com.ibm.samples.ws.os.EPRArray eprArray = null;
017	
018     ...
019
020     eprArray = os.findAllOperatingSystems();
021
022     if (eprArray != null && eprArray.getEndpointReference().length > 0) 
023 		listOfOSes = eprArray.getEndpointReference();
024		
025     if (listOfOSes != null && listOfOSes.length != 0)
026 		anOS = listOfOSes[0];
027     ...
028
029     if (listOfOSes != null) {
030         ...
031
032         if (anOS != null) {
033
034         ...
035 	  com.ibm.ws.stateful.utils.JAXRPCHelper.setEPR(
036 				(javax.xml.rpc.Stub) os,
037 	 			                     anOS);
038         ...
039	  com.ibm.ws.stateful.wsrp.GetResponsePropertyType resp 
040             = os.getResourceProperty(
041 		      new javax.xml.namespace.QName(
042 		      "http://OperatingSystem.odirm.ibm.com",
043 			  "freeVirtualMemory"));
044         Object[] obj = resp.get_Any();
045 	  Integer nameValue = (Integer) obj[0];
046 	  ...
047		
048         } // end anOS!=null
049     } // end if listOfOSes != null 
050
051 } catch (Exception e) {
052 	e.printStackTrace();
053 	success += e.getMessage();
054 }

Take a look at the above code sample in detail:

  1. In lines 2 through 12 you look up the OperatingSystem Web service and obtain a handle to its SEI.
  2. In line 20 you invoke the findAllOperatingSystems operation on the OperatingSystem SEI, obtained in the previous step, to get an array of EPRs for the different operating systems.
  3. In lines 22 through 34 you select an operating system that is not NULL from the list obtained in previous step.
  4. In lines 35 through 37 you populate the OperatingSystem Web service stub instance with the EPR of the operating system, selected in the previous step, so that subsequent requests through the stub include the EPR information as SOAP message headers.
  5. In lines 39 through 45 you invoke the getResourceProperty operation to get the value of the freeVirtualMemory property of the OperatingSystem WS-Resource.

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. Listings 11 and 12 show the SOAP encoding of the GetResourceProperty message exchange.


Listing 11. GetResourceProperty 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 xmlns: ... >
            http://localhost:9080/OperatingSystemWeb/services/OperatingSystemPort
        </wsa:To>
        <csCreationClassName xmlns: ... >
            Linux_ComputerSystem
        </csCreationClassName>
        <csName xmlns: ... >
            hazelrah.pok.ibm.com
        </csName>
        <creationClassName xmlns: ... >
            Linux_OperatingSystem
        </creationClassName>
        <name xmlns: ... >
            hazelrah.pok.ibm.com
        </name>
    </soapenv:Header>
    <soapenv:Body>
        <GetResourcePropertyRequest 
        xmlns:ns914761362="http://OperatingSystem.samples.ibm.com" 
        xmlns="
        http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceProperties">
            ns914761362:freeVirtualMemory
        </GetResourcePropertyRequest>
    </soapenv:Body>
</soapenv:Envelope>




Listing 12. 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="
            http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceProperties">
            <_any xsi:type="xsd:int" xmlns="">1588532</_any>
        </GetResourcePropertyResponse>
    </soapenv:Body>
</soapenv:Envelope>


Install the Pegasus CIMOM

This section lists the steps needed to download, compile, and test the Pegasus CIMOM.

  1. Go to the Release Snapshots page in the OpenPegasus Web site (see Resources). This is shown in Figure 4.
    Figure 4. Download page for OpenPegasus CIMOM 2.3.2.
    Figure 4. Download page for OpenPegasus CIMOM 2.3.2.
  2. In the list of source releases, pick the 2.3.2 point release and, using the GZ link, download Pegasus-2.3.2.tar.gz to a directory of your choice, as shown in Figure 4.
  3. In order to build Pegasus, you need the GNUMAKE utility and can obtain it at http://www.gnu.org. Please refer to the Release 2.3.2 README for more information on Pegasus dependencies.
  4. Unzip and untar the downloaded file in a directory of your choice $(YOURDIR). This will create a directory called $(YOURDIR)/pegasus-2.3.2.
  5. Define the following three environment variables:
    1. PEGASUS_ROOT -- this should be $(YOURDIR)/pegasus-2.3.2
    2. PEGASUS_HOME -- to point to a directory to contain output binary files (for example, set it to $HOME/pegasus_home). Then the output will go into $HOME/pegasus_home/bin and $HOME/pegasus_home/lib.
    3. PEGASUS_PLATFORM -- this must be set to a supported platform identifier. This identifier has the following form: [Operating-System]_[Architecture]_[Compiler]. For example (Linux on IA32 platform using the GNU Compiler): LINUX_IX86_GNU.
  6. Place $PEGASUS_HOME/bin on your path.
  7. Place $PEGASUS_HOME/lib on your LD_LIBRARY_PATH (for Unix only). For RedHat/SuSE/UL, edit /etc/ld.so.conf and add $PEGASUS_HOME/lib.
  8. For CMPI enablement, the following environment variables must be set prior to running make.
    • ENABLE_PROVIDER_MANAGER2=1
    • ENABLE_CMPI_PROVIDER_MANAGER=1
    • Please refer to the readme.cmpi file in $(YOURDIR)/pegasus-2.3.2 for further details.
  9. Change to the root of the Pegasus distribution, $(YOURDIR)/pegasus-2.3.2, and type make (where make refers to GNU make). Takes a while.
  10. Then create the repository, which is needed to serve data. In $(YOURDIR)/pegasus-2.3.2, type make repository.
  11. At this point you have set up Pegasus. Test the installation by performing the following steps:
    • Start the cimserver with the command cimserver &. You can find the cimserver executable in $PEGASUS_HOME/bin.
    • Type CLI ei CIM_OperatingSystem to enumerate operating system instances. If Pegasus is set up correctly, you will see an instance of PG_OperatingSystem. CLI can also be found in $PEGASUS_HOME/bin.
    • Type CLI ei CIM_Process to enumerate process instances. You will see a list of PG_UnixProcess.
    • Stop the cimserver with the command cimserver -s.

Install the SBLIM providers

This section lists the steps needed to download, compile and test the SBLIM providers.

  • Go to the SBLIM instrumentation Web page (http://oss.software.ibm.com/developerworks/oss/sblim/instrumentation.html). This is shown in Figure 5.
  • In the Description column, follow the link that enables you to get the sources as a tarball and click on sblim-cmpi-base. This is shown in Figure 5.
  • Select the sblim-cmpi-base package versioned 1.2.5 and download sblim-cmpi-base-1.2.5.tar.gz to a directory of your choice.
    Figure 5. Download page for SBLIM Instrumentation provider
    Figure 5. Download page for SBLIM Instrumentation provider
  • In the $(YOURDIR)/sblim-cmpi-base-1.2.5 directory, edit setting.cmpi. Search for the section titled "Pegasus flavor." Make sure that the CIMOMINC variable is set as follows: CIMOMINC=$(PEGASUS_ROOT)/src/Pegasus/Provider/CMPI.
  • Create a directory called include under $(YOURDIR)/sblim-smpi-base-1.2.5. Then change the COMMONINC as follows: COMMONINC=$(YOURDIR)/sblim-cmpi-base-1.2.5/include. This is where the include files will be copied over during the build.
  • From $(YOURDIR)/sblim-cmpi-base-1.2.5 run make, followed by make install.
  • At this point SBLIM has been set up. Test the installation by performing the following steps:
    • Start the cimserver with the command cimserver &. You can find the cimserver executable in $PEGASUS_HOME/bin.
    • Type CLI ei CIM_OperatingSystem to enumerate operating system instances. If Pegasus is set up correctly, you will see an instance of Linux_OperatingSystem. CLI can also be found in $PEGASUS_HOME/bin.
    • Type CLI ei CIM_Process to enumerate process instances. You will see a list of Linux_UnixProcess.
    • Type CLI ei CIM_OSProcess to enumerate association instances between OperatingSystem and Process. You will see a list of OSProcess instances.
    • Stop the cimserver with the command cimserver -s.

Set up and run the OperatingSystem Web service

This section describes how to create a workspace in WebSphere Application Developer Integration Edition V5.1.0 (Application Developer) that contains the OperatingSystem sample and how to set up the built-in WebSphere Application Server Test Environment (Test Environment).

  1. Create a new workspace called cmpa in Application Developer.
  2. Enable the Server Targeting function in Application Developer. You can do this by selecting Window > Preferences > J2EE > Enable server targeting support.
  3. Import the J2EE CIM Connector, CimConnector.rar, into your workspace as a standalone connector project. This creates a new connector project named CimConnector.
  4. Import the CMPA Adapter. You can do this by importing the cmpaAdapter.rar into a new Connector project. This will create a cmpaAdapterConnector project. You can obtain the cmpaAdapter.rar file from the installableApps directory of the built-in WebSphere Test Environment directory. For our installation this directory happens to be C:\IBM\WebSphere Studio\runtimes\ee_v51\installableApps.
  5. Import the OperatingSystem.ear file into your workspace. Make sure that Integration Server V5.1 is selected as the target server. This creates the following projects:
    1. An Enterprise Application Project (J2EE 1.3) called OperatingSystem.
    2. A Dynamic Web Project called OperatingSystemWeb, which contains the Web services router project.
    3. An Enterpise Java Beans project called OperatingSystemEJB, which contains the implementation of the OperatingSystem EJB components.
    4. A Dynamic Web Project called OperatingSystemClientWeb, which contains the Web services client to the OperatingSystem service and a test JSP file.
  6. Add the CimConnector project to the Java Build Path of the OperatingSystemEJB project.
  7. Create a new server and server configuration called WebSphere Version 5.1 Integration Test Environment in the server perspective of Application Developer. Use WebSphere version 5.1 > Integration Test Environment as the server type.
  8. Add the CIM Connector to the test server configuration:
    1. Add a J2C Resource Adapter, CimConnector, using the J2C Configuration setting window of the test server created in step 7. This should display the Create Resource Adapter dialog box. In this dialog box select the CimConnector from the drop down list and click OK.
    2. Select the CimConnector and add J2C Connection Factory with the following information:
      1. Name: CimConnector
      2. JNDI Name: eis/CimConnector1
    3. Set the Resource Property value for ServerName to point to the server where your CIMOM server is running.
  9. Add the CMPA Adapter to the test server configuration.
    1. Add a J2C Resource Adapter, cmpaAdapterConnector, using the J2C Configuration setting window of the test server created in step 7. This should display the Create Resource Adapter dialog box. In this dialog box select the cmpaAdapterConnector from the drop down list and click OK.
    2. Select the cmpaAdapterConnector and add a J2C Connection Factory with the following information:
      1. Name: CMPAConnector
      2. JNDI Name: eis/CmpAConnectorFactory
  10. Start the WebSphere Test Environment. In the server perspective, add the OperatingSystemEAR project to the server, publish it, and then start it.
  11. Execute the client. Right-click TestOS.jsp in the OperatingSystemClientWeb project and select Run on Server. This should open the Server Selection dialog. On this screen, select the Use an existing server radio button and make sure that the Set server as project default box is checked. Click Finish. This launches a Web browser in Application Developer. If the Web service invocation is successful, you should see a list of operating systems and the value of the freeVirtualMemory ResourceProperty, as shown in Figure 6.

Figure 6. OperatingSystem service invocation successful
Figure 6. OperatingSystem service invocation successful

Summary

This paper showed you how a Web service interface can provide access to the properties of a WS-Resource whose state is modeled using an entity bean with CMP/A. You also learned how to use a CIM JCA connector and CIM-XML from within the push-down methods of the CMP/A entity bean to talk to a CIMOM server that is managing the WS-Resource's state natively by using the SBLIM instrumentation provider.


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.



Download

NameSizeDownload method
ws-statefulws4code.zip763.0 KB HTTP

Information about download methods


Resources

About the authors

Hidayatullah H. Shaikh is a Senior Software Engineer on the IBM Software Group 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, enterprise Java, and database management systems. You can contact Hidayatullah at hshaikh@us.ibm.com.

Jaipaul Antony is an Advisory Software Engineer with the eServer Advanced Systems Infrastructure Development team in IBM Systems and Technology Group. His areas of interest are primarily in the emerging fields of Web services and grid computing. You can contact Jaipaul at jantony@us.ibm.com.

Revathi Subramanian is a Senior Software Engineer with the Advanced Systems Infrastructure Development Team in IBM Systems Group. Her areas of expertise include e-commerce applications, grid computing, Java technology and Web services, while her real interests lie in natural language processing, speech recognition, creative writing, and foreign languages. You can contact Revathi at revathi@us.ibm.com.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=SOA and Web services
ArticleID=11947
ArticleTitle=Implement and access stateful Web services using WebSphere Studio, Part 4
publish-date=07272004
author1-email=hshaikh@us.ibm.com
author1-email-cc=
author2-email=jantony@us.ibm.com
author2-email-cc=
author3-email=revathi@us.ibm.com
author3-email-cc=author email

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers