Skip to main content

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

Accessing resources through services

Hidayatullah Shaikh (hshaikh@us.ibm.com), Senior Software Engineer, IBM Corporation
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 architectures, grid computing, e-commerce, J2EE technology, and DBMSs. Contact him at hshaikh@us.ibm.com
Sonny Fulkerson, Senior Technical Staff Member, IBM Corporation
Sonny Fulkerson is a Senior Technical Staff Member working in the IBM On Demand Development organization. He is based in Research Triangle Park, North Carolina.

Summary:  Web services are deployed and then often made available for client access via the advertisement of address and binding information in directories. While the lifecycle of a Web service is generally bound to its deployment, the service implementation itself may maintain dynamic state on behalf of clients or within a particular business context. The Web Services Resource Framework proposes a model for accessing state using Web services. The model builds on the WS-Addressing protocol. This article illustrates how you can access Web serivces resources in IBM® WebSphere® Studio Application Developer V5.1.1 using the technique described in the Web Services Resource Framework.

Date:  09 Mar 2004
Level:  Advanced
Activity:  667 views
Comments:  

Web services are generally thought of as being stateless. However, while it is true that Web services are most often accessed over unreliable, stateless protocols such as HTTP, in practice these services can often maintain state or resources on behalf of an individual service requestor or within a particular business context across multiple interactions. The most commonly cited example of this is a shopping cart application, where the server application is able to maintain the contents of a cart across multiple independent interactions on behalf of an individual requestor.

To maintain state across multiple requests from multiple clients, server applications must have a means for identifying the state data that is to be updated on each interaction. A common means of correlating requests is to make this an explicit part of the application design. In the shopping cart example, the designer could require that a shopping cart identifier be provided as input on each interaction. This would allow the server application to identify the cart from which it should add and remove items.

Some designers consider placing correlation data in the application interface to be burdensome on the client application. This has caused some to pursue techniques for implicit correlation or session creation that do not require the client application code to participate explicitly. The approaches proposed to date generally involve the server application using features of the underlying communication protocol, such as cookies with HTTP, or requiring explicit support in the Web services client runtime to provide this capability.

The whitepaper "Modeling stateful resource with Web services" (see the Resources section below for a link) proposes an Implied Resource pattern for accomplishing this task. This pattern allows service providers to make use of extensibility features in the WS-Addressing protocol (see Resources) to reduce the client burden, and to do so in a way that is not bound to a specific transport protocol and does not require unique support in the Web services client runtime.

This article does not debate the merits of the above approaches. Instead, we focus our efforts on documenting our experience with implementing these approaches to stateful Web services for deployment on IBM® WebSphere® Application Server V5.1 using IBM WebSphere Studio Application Developer V5.1.1. We hope to illustrate that, by utilizing existing J2EE best practices in the service implementation, we have been able to not only easily support multiple interface styles, but also leverage the wealth of tooling and runtime support features that are currently available.

We use a simple calculator application as the basis of our samples. First, we implement the calculator for use by RMI/IIOP clients using the J2EE Session Bean Entity Facade pattern. We then show you how the application can be easily exposed to Web services clients via a WSDL interface. Finally, we document the steps necessary to expose the calculator service using the Implied Resource pattern, and show you how to build a client of the calculator service using the approaches outlined in the Web Services Resource Framework (see Resources for a link). Where possible, we attempt to highlight forthcoming support that may further aid the development of applications that make use of these patterns. The EAR containing both the service implementation and client code is part of this article's code download package (see Resources).

After reading this article, you should be familiar with the core issues and tasks for implementing and accessing stateful resources through a Web services interface within Application Server. You should also have an understanding of where application extensions are provided in advance of formal runtime support for emerging Web services standards such as WS-Addressing. This information is intended to help you understand the implementation costs and potential migration issues that you are likely to encounter based on interface design choices.

Intended audience

We assume that you have a basic understanding of J2EE, Web services, and Application Server. If you are hoping to familiarize yourself with this technology, please consult the Resources section of this article for sources of good introductory material. We also suggest that you consult the resources available at IBM developerWorks.


Content and requirements for the sample code

The samples referenced in this article were created with WebSphere Studio Application Developer Version V5.1.1 GM Version (build ID 20031120_1915). They were unit tested using the WebSphere Application Server V5.1 Built-in Test Environment.

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

WASv5WSAExtensions.jarA JAR file containing the utility classes that WebSphere Application Server V5.1 needs 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.zipThe javadoc for the utility classes.
CalculatorService.earA sample stateful calculator service. A Web application is provided that allows the calculator service to be easily invoked.

Implementing the calculator service for EJB clients

Listing 1 proposes an interface for a calculator service that could be consumed by RMI/IIOP clients.


Listing 1. Calculator service interface for remote RMI/IIOP clients
public interface CalculatorService extends Remote {	
   
   public float add(float value1, float value2) throws java.rmi.RemoteException;
   public float sub(float value1, float value2) throws java.rmi.RemoteException;

 }

You can see that the calculator service interface has been designed so that the requestor must input all information necessary to perform an operation; the result is returned as an output of the operation. This type of service is often referred to as being stateless with respect to its interaction with its requestors. This interface design simplifies the job of the service implementer, who can choose to treat each request as an independent interaction. Listing 2 includes a code snippet that highlights this simple implementation.


Listing 2. Implementation of the calculator service add() operation
public float add(float value1, float value2) 
  {
   
    // Add the two input values and return result. Note, that we do not need to
    // reference any requestor state to perform the operation

    return value1 + value2;
  }


The natural next step in developing this service would be to allocate each user a particular calculator instance. Each requestor could then simply add, subtract, or query the current total from this calculator. A service that maintains information on behalf of a particular requestor is often referred to as being stateful with respect to its interaction with that requestor.

There are many ways in which the service implementer could choose to maintain the calculator total on behalf of a client. It could take advantage of existing context that is available to the service implementation on each request as a means for understanding the calculator state that is to be acted upon. For example, the implementer could retrieve the requestor's user ID from the security context on each request and use that to identify the target calculator total.

While using the security context to identify a requestor is a workable solution, forming a one-to-one relationship between a requestor and a calculator's state could be viewed as poor application design. An alternative means of correlating requests to access a particular calculator total is to make that correlation a formal part of the calculator service interface. Listing 3 proposes an updated interface.


Listing 3. Calculator service interface with explicit state identifier
public interface CalculatorService extends Remote {
	
   public String getCalculator(String AcctName)  throws java.rmi.RemoteException;
   public float  add(String calcID, float value) throws java.rmi.RemoteException;
   public float  sub(String calcID, float value) throws java.rmi.RemoteException;
   public float  getTotal(String calcID)         throws java.rmi.RemoteException;

}       


The updated interface contains a getCalculator() method that takes an account name as input. For the sample, we assume that requestors have obtained an account name beforehand via some out-of-band administrative process. The getCalculator() method acts as a factory for creating calculator instances, returning a calcID to the requestor. When the requestor subsequently wishes to add, subtract, or query the total of his current calculator, he simply invokes the appropriate calculator service operation, providing his calcID in the request parameters. The calcID is opaque to the program that is accessing the calculator service.

CalculatorService.ear contains an implementation of the updated CalculatorService interface using the J2EE Session Bean Entity Facade pattern. This pattern is considered a best practice because it isolates the requestor from the details of how the service implementation maintains the underlying calculator state, while also providing a means to institute additional business rules regarding access to the calculator service. For example, the provider could add logic that, before creating a calculator for the requestor to use, ensures that the requestor is in an organization that has paid for access to this service. Listing 4 depicts the logic that can exist within the calculator service session bean controller.


Listing 4. The session bean acts as a controller for the calculator service
public String getCalculator(String AccountName) 
{
   // Determine if requestor has business entitlements to create a calculator
   // instance. This function will check if payments have been made and insure
   // that the department has not used up all of its calculators  
   // Create a calculator total, set it to zero. Build a calculator identifier to
   // be returned to the requestor
                   
    If (acctAllowedToCreateMoreCalcs(AccountName)) == true) {
       calcID = this.generateCalcID(); 
       home.create(calcID());     // Call the EJB Entity Bean home to create a 
                                  // Calculator State object with the calcid   
      }
       :::    
       :::
  return calcID;           
}

The sample application maintains the calculator state using a CMP entity bean that makes use of a relational database as the underlying persistence mechanism. We made this choice because it offers the most runtime and tooling support for persistence while meeting the requirements of the application. We are able to take advantage of EJB local interfaces as a means of enhancing performance. A service implementer could choose to maintain calculator state by an alternative means -- for example, via a database or an in-memory hash table, or by accessing one or more legacy systems that comprise the state attributes. The means by which a service provider names and maintains its state is an integral part of the application design and is driven by the requirements of the service and the constraints regarding environments in which it must execute.

We do not require that requestors explicitly return or destroy the calculators they have been allocated. We assume that a calculator will expire after some period of inactivity. This fact is exposed to calculator requestors when they open an account. We do not focus on techniques for managing the timeout of the state in this article. Instead, we assume that there are background reapers that periodically examine the underlying database and provide cleanup. We include and maintain usage metrics (creation time, last access time, etc.) in the underlying database containing the calculator state. We do not currently expose these attributes via the calculator service.


Exposing the calculator service as a Web service

CalculatorService.ear also contains code that exposes our updated calculator interface as a Web service that can be invoked using SOAP over HTTP. The J2EE standard dictates that a Web service may be implemented as a Java class (within the Web container) or as a stateless session bean (see Resources for more information on the J2EE standard and Web services). We were able to easily generate the necessary artifacts to expose our calculator service stateless session EJB component as a Web service using the Web Services wizard support in WSAD. This support includes generation of the WSDL and sample client code for invoking the service. We were also able to use the new Web Services Explorer to unit-test our service. The explorer can generate a Web-based interface for invoking a service based on its service definition. (See Resources for more information on accessing and developing Web services in WebSphere Studio.)

Recall that Web services really provide for interoperability via message exchange. Now that we have defined a WSDL document describing the message formats and protocol bindings for our calculator service, any client program that can generate and send an appropriate message over the appropriate protocol can invoke our service. This means that our calculator service is no longer restricted to RMI/IIOP clients. Listing 5 highlights a valid SOAP message targeted to the calculator service.


Listing 5. A sample SOAP-over-HTTP message targeted to our calculator service
001 POST /Calculator HTTP/1.1
002 Host: XYZ.com
003 Content-Type: text/xml; charset=utf-8
004 Content-Length: 99999
005 SOAPAction: 


006 <?xml version="1.0" encoding="UTF-8"?>

007 <soapenv:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" 
                                        xmlns:sec="...">
   
008      <S:Header>
009           <sec:Security>
                <!-- WS-Security signature of Body, To, -->
                <!-- Action and From goes here. --> ... 
010    </sec:Security> 
011  </S:Header> 

012  <S:Body>
013    <add xmlns="http://calculator.ibm.com">
014       <CalculatorID>DEPT23CALC</CalculatorID>
015       <value>100</value>
016    </add>
017  </S:Body>

018 </soapenv:Envelope>


Let's look at this message in detail. Lines 6 through 18 represent the SOAP message that is being sent to the endpoint http://XYZ.com/Calculator. This is the endpoint address of the WebSphere Application Server Web services runtime containing the calculator service. Application Server will interrogate the message content, perform the necessary context set-up, and then dispatch on the service implementation based on the configuration of the deployed service implementation. In our example, this will be dispatched on the add() method of our stateless session bean.

Lines 8 through 11 represent control information in the form of SOAP headers. Increasingly, new types of control information are being defined and supported in Web services runtimes and intermediaries. WebSphere Application Server V5.0.2 contains support for understanding security tokens that are transmitted in WS-Security headers. Specifically, Application Server is able to validate a token with the configured authentication service; if the token is valid, Application Server can map that to a security principal. The principal is established as the J2EE context so that we can ensure that the security constraints that are defined on the service implementation are met before dispatching the component. Finally, we should note that the stateless session bean representing our Web service is able to retrieve the security context via the same API whether it is being invoked by an RMI/IIOP client or as the result of a message from a Web services requestor. Application Server ignores SOAP headers that it does not understand.

Lines 12 through 17 represent the SOAP body. This information is used to dispatch onto our calculator service implementation. It is worth noting that because all of the parameter types of the existing CalculatorService Java interface map cleanly to valid XML and WSDL constructs, we were able to generate the Web service in a bottom-up fashion without any changes to the existing stateless session bean containing the implementation. We merely defined message parts that Application Server is able to interpret and dispatch onto the existing interface. This is the best-case scenario and results in a WSDL document and a Java implementation that can be developed and updated in a round-trip fashion.

CalculatorTestExecute.jsp (which is included in CalculatorService.ear) contains sample client code for invoking our calculator service as a Web service. The code makes use of the standard J2EE programming model for accessing services. Listing 6 illustrates client code for invoking the calculator service.


Listing 6. J2EE client code for invoking the calculator service
// Lookup Calculator Service Interface using standard JNDI 

com.ibm.calculator.CalculatorService calculatorSI =
    (com.ibm.calculator.CalculatorService)
           ic.lookup("java:comp/env/service/CalculatorService");
   
// Get an invokable Stub for service using standard J2EE programming model

com.ibm.calculator.Calculator calculator = 
    (com.ibm.calculator.Calculator)
       calculatorSI.getPort(com.ibm.calculator.Calculator.class);

// Obtain a calculator supplying my account name as input
String calcID = calculator.getCalculator(acctName);

// Invoke the service
calculator.add(calcID, 12);
      ::: 


Extending Application Developer to produce WS-Addressing message headers

The WS-Addressing standard designates that addressing and action information normally embedded in communication transport headers should be placed within the SOAP envelope. Specifically, the specification defines a schema for a portable address construct known as an endpoint reference. It also defines a set of rules for the represention of this information as message information headers in SOAP messages that are sent to Web services endpoints. This support not only enables further independence of a SOAP message from its communication protocol, but also defines a means by which Web services may pass references to themselves and other services. The article "Expanding the communications capabilities of Web services with WS-Addressing" (see Resources for a link) provides examples of using WS-Addressing.

Listing 7 shows a message targeted for our calculator service sent by a client program that has chosen to include WS-Addressing information in the control section. Note that the client Web services runtime has also included WS-Security headers.


Listing 7. Sample SOAP/HTTP message for calculator service containing WS-Addressing information
001 POST /Calculator HTTP/1.1
002 Host: XYZ.com
003 Content-Type: text/xml; charset=utf-8
004 Content-Length: 99999
005 SOAPAction: 


006 <?xml version="1.0" encoding="UTF-8"?>

007 <soapenv:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" 
                    xmlns:sec="..." 
                    xmlns:wsa="..."> 
   
008      <S:Header>
009    <wsa:to>http://XYZ.com/services/Calculator</wsa:to>   
       
010      <sec:Security>
            <!-- WS-Security signature of Body, To, -->
            <!-- Action and From goes here. --> ... 
011    </sec:Security> 
012  </S:Header>  

013  <S:Body>
014    <add xmlns="http://calculator.ibm.com">
015       <CalculatorID>DEPT23CALC</CalculatorID>
016       <value>100</value>
017    </add>
018  </S:Body>

019 </soapenv:Envelope>


Line 9 contains WS-Addressing information. Increasingly, Web services runtimes are being enhanced to include message information headers, as specified by WS-Addressing, in the headers of SOAP messages that are sent to service endpoints. The IBM Emerging Technologies Toolkit (ETTK; see Resources for a link) provides handlers to extend Axis to create WS-Addressing headers. The Microsoft Web Service Extensions (WSE) 2.0 toolkit provides similar capability for .Net environments.

WASv5WSAExtensions.jar contains a JAX-RPC client handler for use within Application Server. When configured with a client application, the handler will add WS-Addressing message information headers to messages being sent by that application. No change is required to the client application program to enable this support, as the handler is able to create the message headers from existing information.

To use the handler, you need to ensure that WASv5WSAExtensions.jar is on the classpath of the Web services client application. You can achieve this by importing the JAR file into your workspace and then updating the Web services client's project properties to include it as a dependent JAR file. You must then add the handler definition to the Web services client deployment descriptor. Listing 8 shows the updates made to the calculator service's Web services deployment descriptor. The deployment descriptor editor within WSAD makes it easy to perform these updates.


Listing 8. Updates to the webservicesclient.xml file of the CalculatorServiceWebClient application
<handler>
   <handler-name>com.ibm.samples.wsa.handler.ClientHandler</handler-name>
   <handler-class>com.ibm.samples.wsa.handler.ClientHandler</handler-class>
</handler>


Representing the calculator state as a Web services resource

The Implied Resource pattern we discussed earlier describes how to use the WS-Addressing endpoint reference element to identify a target Web service and to assist in the transport of information about the resources that a service implementation may use in its processing. This approach exploits the WS-Addressing protocol, which leverages the header section of a SOAP message rather than defining things within the messages in the SOAP body. Specifically, it proposes that the reference property portion of a WS-Addressing endpoint reference be used to contain the identity of the resources (as known by the Web service) being used.

In order to expose our calculators as Web services resources, we first change the getCalculatorResponse message in the WSDL file of the CalculatorService to contain an endpoint reference (as defined by the WS-Addressing schema) rather than a calcID. Similarly, we remove the calcID element from the add, sub, and getTotal input messages, as this information will now be encapsulated in the WS-Addressing endpoint reference used to address the calculator Web service. Listing 9 shows the resulting service endpoint interface after running the updated WSDL through the WSDL2Java utility.


Listing 9. Implied Resource pattern that allows us to remove the data identifier from the functional interface
public interface CalculatorService extends Remote {	
      
      public javax.xml.soap.SOAPElement getCalculator(String AcctName) 
      throws java.rmi.RemoteException;      
      public float add(float value) throws java.rmi.RemoteException;
      public float sub(float value) throws java.rmi.RemoteException;
      public float getTotal()       throws java.rmi.RemoteException;  

}       

You can see that the WSDL2Java utility has mapped the endpoint reference schema type from the getCalculator response message to a SOAPElement when generating the return type from the getCalculator() service interface method. This occurs due to the anyattribute extensibility types included in the endpoint reference schema definition. This variability makes this type fall outside of the WSDL-to-Java mapping rules prescribed by the JAX-RPC 1.1 specification. When a message part falls outside the rules, the Web services runtime presents it to the application (and vice versa) as a generic SOAPElement rather than a mapped type.

Given the above discussion, the getCalculator() method's implementor will have to produce a SOAPElement containing the XML constructs for an endpoint reference as the return type. We provide an endpoint reference helper class in WASv5WSAExtensions.jar to help with this task. The endpoint reference class is a Java mapping of the schema for an endpoint reference (EPR). The class provides support for initializing a Java EPR instance from a SOAPElement as well as support for serializing the Java EPR instance to a SOAPElement.

Listing 10 shows a code snippet depicting the logic within the updated getCalculator() method. Please note that CalculatorService.ear contains the full source code showing the updates made to our calculator to expose it as a Web services resource.


Listing 10. getCalculator() method updated to return a SOAPElement containing an EPR
public javax.xml.soap.SOAPElement getCalculatorEPR(String AccountName) {
		EndpointReference epr = null;
		SOAPElement eprAsSOAPElement = null;

	try {

        // If this account has not reached its maximum limit of calculators
	if (acctAllowedToCreateMoreCalcs(AccountName) == true) {
			
	CalculatorStateLocalHome home = getCalculatorStateHome();  
	if (home != null) {
          String calcID = generateCalcID();    // Generate an ID to 
          be assigned to this Calculator
	  home.create(calcID);                        // Call EJB home to 
	  create the Calculator State 

          epr = new EndpointReference();       
   	  String address = EPRHelper.getEndpointAddressFromCurrentContext();
	  epr.setAddress(address);

  	  epr.setReferenceProperty(CALCULATOR_NS,
	  			   CALCULATOR_LOCALNAME_CALCID,
				   calcID);
          eprAsSOAPElement = epr.toSOAPElement();  

        return eprAsSOAPElement;
...

The getCalculator() factory method currently takes the very simple approach of assuming that all calculators created by this service will be accessed via the same service endpoint. The method's implementation uses the supplied helper class to determine its endpoint address. In practice, this method's implementation could be much more sophisticated. In particular, a service registry or a workload manager could determine the most appropriate endpoint address in which to allocate this resource. Determining the contents of an EPR is a very environment-specific task; guidance on this topic is beyond the scope of this article.

Listing 11 shows the updates to the client code needed to access the calculator service using the Implied Resource pattern.


Listing 11. Client updates needed to access the calculator service using the Implied Resource pattern
com.ibm.samples.calculator.CalculatorService calculatorService = null;

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

// Lookup calculatorFactory 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 calculatorFactory 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
    {             
      javax.xml.soap.SOAPElement SE = calculatorService.getCalculator(acctName);
        
      com.ibm.samples.wsa.wsaddr.EndpointReference epr 
		= com.ibm.samples.wsa.wsaddr.EndpointReference.fromSOAPElement(SE);

     com.ibm.samples.wsa.utils.JAXRPCHelper.setEPR( (javax.xml.rpc.Stub) 
     calculatorService, epr);
        
     calculatorService.add(addvalue);    
    
}


You can see that the client interface has also been regenerated to accommodate the updated getCalculator() response message. As a result, the Java client will receive a SOAPElement from the Web services runtime as the output of a getCalculator() operation.

The client program stores the EPR as a name/value pair in the calculator service stub. The client handler (which we showed you how to configure previously) can look for an EPR in the stub. If an EPR is present, the client handler will take this information and create WS-Addressing message information headers in the outbound message.

In the previous sections, we have shown you how to produce a Web services resource-qualified EPR in the getCalculator() method and return that to the client. We have also shown how that client received what it knew to be an EPR and populated a CalculatorService stub instance so that subsequent requests through the stub include the EPR information as SOAP message headers. Listing 12 illustrates how the stateless session bean, acting as the Web services implementation, can access WS-Addressing reference properties propagated within the message headers from the client.


Listing 12. Sample code for retrieving WS-Addressing information from message context
                  :::
public float add(float value) {

		float _newTotal = 0f;

		try {
			CalculatorStateLocalHome home = getCalculatorStateHome();
			if (home != null) {
				
				String calcID = 
				EPRHelper.getReferencePropertyFromContext(
						 CALCULATOR_NS,
						 CALCULATOR_LOCALNAME_CALCID);	
				
				CalculatorStateLocal calculatorState =
					home.findByPrimaryKey(calcID);  //
					
				if (calculatorState != null) {
					_newTotal = 
					calculatorState.getTotal() + value;
					calculatorState.setTotal(_newTotal);
				}
			}
		} catch (FinderException e) {
			e.printStackTrace();
		} catch (SOAPException e) {
	        e.printStackTrace();
		}

		return _newTotal;
	}


You can see that the implementation of the add() method on the CalculatorService no longer obtains the calcID identifying the calculator state as an input parameter. Instead, we obtain this from the reference properties information that has arrived in the input message. Specifically, we retrieve an EPR representation of the header information from the SOAP message context.


Conclusions

In this article, we have shown examples of services that are stateful and stateless with respect to their client contract. We have illustrated that there are best practices and design patterns in place today for implementing applications that make use of state, and that these implementations can be extended with minimal change to Web services clients and can make use of new capabilities available to these clients.

We have provided minimal helper classes and documentation that facilitate the building of these applications. We expect higher-level programming models and runtime support to continue to emerge that further abstract these details from the application 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-statefulwscode.zip413.0 KB HTTP

Information about download methods


Resources

About the authors

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 architectures, grid computing, e-commerce, J2EE technology, and DBMSs. Contact him at hshaikh@us.ibm.com

Sonny Fulkerson is a Senior Technical Staff Member working in the IBM On Demand Development organization. He is based in Research Triangle Park, North Carolina.

Comments



Trademarks

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

My developerWorks community

Special offers