The lifetime of a WS-Resource is the period between its creation and destruction. The life cycle of a resource can either be static or dynamic. Resources with a static life cycle are those that are created on or deployed to the system and remain there in a permanent or semi-permanent fashion. A hardware or software failure can unintentionally destroy a static life cycle resource, as opposed to a system management actor, which can intentionally destroy the resource. By contrast, dynamic life cycle resources are created and destroyed more frequently.
In many scenarios, it is appropriate for clients of a resource to explicitly destroy that resource. In such cases, the WS-Resource might support a message exchange pattern that allows a service requestor to request that resource's destruction. This is the immediate destruction mechanism identified in the WS-Resource Lifetime specification (see Resources).
However, in a distributed computing Web environment, a user might become disconnected from the service provider's endpoint and therefore might be unable to explicitly destroy the resource. The WS-Resource Lifetime specification standardizes the means by which a resource with a dynamic life cycle can be destroyed. This specification defines the means by which any client of a resource instance can establish and renew its interest in the resource instance for a specific period of time. If that time expires, the resource instance might self-destruct without the need for an explicit destroy request from a client. This time-based approach used for managing the destruction of a WS-Resource is also known as scheduled destruction.
In this article, I will use a simple Calculator service example to show how both immediate and scheduled destruction of WS-Resources can be implemented in IBM® WebSphere® Application Server environment.
You should have a basic understanding of J2EE technology, Web services, and WebSphere Application Server V5, Enterprise Edition. 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 the first article in this series, "Implement and access stateful Web services using WebSphere Studio, Part 1: Accessing resources through services" and become familiar with the Calculator example used in the article.
Contents and requirements for the sample code
IBM® WebSphere® Studio Application Developer, Integration Edition, V5.0.1 was used to create the samples in this article. The samples also were unit-tested using the WebSphere Application Server Enterprise Edition V5.0.2 Built-in Test Environment.
The file ws-statefulws2code.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 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 might 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. |
WASv5WSRLExtensions.jar | WSRL helper class for scheduled destruction support. |
You will use the Calculator sample that was in Part 1 of this series. The Calculator resource state is stored in the CalculatorState entity bean. You will also extend the Calculator Web service interface to support immediate destruction of the calculator state and alter some of the implementation to illustrate how scheduled destruction of the calculator state can be implemented. The instructions in this article will help you modify the sample code from 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-statefulws2code.zip.
To support immediate destruction, the Calculator WS-Resource has to support the destroy message exchange pattern so that a service requestor can request the resource's immediate destruction. This is done by adding the Destroy operation to the Calculator Web service WSDL. The signature of the Destroy operation is dictated by the WS-Resource Lifetime specification. The specification also defines the message definition for the request and the response for this operation. Listing 1 shows the relevant portion of this WSDL. For details, you can refer to the Calculator.wsdl file included in CalculatorService.ear.
Listing 1. The Destroy operation added to the Calculator WSDL
<wsdl:definitions targetNamespace="http://calculator.samples.ibm.com"
...
xmlns:wsrl="http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceLifetime"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:types>
<xsd:schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.ibm.com/xmlns/stdwip/web-services/WS-
ResourceLifetime">
<xsd:element name="Destroy">
<xsd:complexType />
</xsd:element>
<xsd:element name="DestroyResponse">
<xsd:complexType />
</xsd:element>
</xsd:schema>
...
</wsdl:types>
...
<wsdl:message name="DestroyRequest">
<wsdl:part name="DestroyRequest" element="wsrl:Destroy" />
</wsdl:message>
<wsdl:message name="DestroyResponse">
<wsdl:part name="DestroyResponse" element="wsrl:DestroyResponse" />
</wsdl:message>
...
<wsdl:portType name="CalculatorService">
...
<wsdl:operation name="Destroy">
<wsdl:input message="intf:DestroyRequest" name="DestroyRequest"/>
<wsdl:output message="intf:DestroyResponse" name="DestroyResponse"/>
</wsdl:operation>
</wsdl:portType>
...
|
Listing 2 shows the service endpoint interface that results when you run the updated WSDL through the WSDL2Java utility.
Listing 2. The service endpoint interface containing the destroy() method
public interface CalculatorService extends java.rmi.Remote
{
public javax.xml.soap.SOAPElement getCalculator(java.lang.String accountName)
throws java.rmi.RemoteException;
public float add(float value) throws java.rmi.RemoteException;
public float getTotal() throws java.rmi.RemoteException;
public float sub(float value) throws java.rmi.RemoteException;
public void destroy() throws java.rmi.RemoteException;
}
|
Listing 3 shows the implementation of the destroy() method in the Calculator Web service. For your example, the values necessary for the service to identify the target implied resource are contained in the WS-Addressing reference properties, calcID. 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. You then destroy the WS-Resource by calling the remove() method on the CalculatorState bean.
Listing 3. The implementation of the destroy() method
public void destroy(){
System.out.println("Destroy called in Service");
try {
CalculatorStateLocalHome home = getCalculatorStateHome();
if (home != null) {
String calcID = EPRHelper.getReferencePropertyFromContext(
CALCULATOR_NS,
CALCULATOR_LOCALNAME_CALCID);
CalculatorStateLocal calculatorState =
home.findByPrimaryKey(calcID);
if (calculatorState != null) calculatorState.remove();
}
} catch (FinderException e) {
e.printStackTrace();
} catch (EJBException e) {
e.printStackTrace();
} catch (RemoveException e) {
e.printStackTrace();
}
}
|
The clients of the Calculator WS-Resource can now call the destroy() method to explicitly destroy it, as shown in Listing 4. For details, you can refer to the CalculatorTestExecute.jsp file included in CalculatorService.ear.
The destroy 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 and must appear as part of the destroy request message in the SOAP headers. Listings 5 and 6 show the SOAP encoding of the destroy message exchange.
Listing 5. Destroy 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 xmlns="http://calculator.samples.ibm.com">1079046560736</calcID> <dummyProp xmlns="http://calculator.samples.ibm.com">EXAMPLE PROPERTY</dummyProp> </soapenv:Header> <soapenv:Body> <Destroy xmlns= "http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceLifetime"/> </soapenv:Body> </soapenv:Envelope> |
Listing 6. DestroyResponse 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>
<DestroyResponse
xmlns="http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceLifetime"/>
</soapenv:Body>
</soapenv:Envelope>
|
In the previous section, you saw how immediate destruction support can be added to the calculator WS-Resource. In this section, you will extend the Calculator sample to support time-based or scheduled destruction. For this, you are going to use the scheduler service of WebSphere Application Server V5, Enterprise Edition. The scheduler service enables tasks to execute at a requested time. The following tasks can be scheduled:
- The invocation of a session bean method
- The sending of a JMS message
For more information on enabling and configuring the scheduler service, please refer to the Resources section at the end of this article.
You will create the calculator resource and extend out to self-destruct in 30 seconds -- in other words, its lifetime is 30 seconds. To accomplish this, create a calculator resource and extend the Calculator service implementation. Make sure to schedule a life cycle task with the scheduler with a fire time of 30 seconds. When the scheduler fires the life cycle task, it calls the process() method of the life cycle bean. The implementation of the process() method contains the code to destroy the WS-Resource instance.
Now, let's take a look at the implementation of the life cycle task bean. You will perform the following steps:
- Create a stateless session bean,
CalculatorResourceLifeCycleTask. - In the bean's deployment descriptor, set the home and remote interfaces to
com.ibm.websphere.scheduler.TaskHandlerHomeandcom.ibm.websphere.scheduler.TaskHandler, respectively. - Implement the
process()method in theTaskHandlerremote interface. Theprocess()method is called when the task fires. Listing 7 shows theprocess()method for this example. The primary key for the calculator resource state,calcID, is first obtained from the task status object and then used to find the right instance of theCalculatorStateentity EJB component by calling thefindByPrimaryKey()method on theCalculatorStateEJB component home. You then destroy the WS-Resource by calling theremove()method on theCalculatorStatebean instance. For details, refer to theCalculatorResourceLifeCycleTaskBean.javafile included inCalculatorService.ear.
Listing 7. Implementing the process method of the life cycle task bean
public void process(TaskStatus status)
{
CalculatorStateLocal calculatorState = null;
try {
String calcID = status.getName();
InitialContext ic = new InitialContext();
Object o = ic.lookup("java:comp/env/ejb/CalculatorState");
CalculatorStateLocalHome home =
(CalculatorStateLocalHome) PortableRemoteObject.narrow(
o,
CalculatorStateLocalHome.class);
calculatorState = home.findByPrimaryKey(calcID);
calculatorState.remove();
} catch (NamingException e) {
e.printStackTrace();
} catch (FinderException e) {
e.printStackTrace();
} catch (EJBException e) {
e.printStackTrace();
} catch (RemoveException e) {
e.printStackTrace();
}
}
|
Once the implementation of the life cycle bean is ready, you need to modify the getCalulator() method of the Calculator service so that the life cycle task is scheduled upon creation of a resource. To modify the getCalulator()method, add two lines of code shown in bold in Listing 8. The sample uses a WSRL Helper class (WSRLHelper), which I have included in the sample code. The scheduleResourceLifeCycleTask() method is called with the session bean context, expiry time, and identifier of the resource (calcID) as parameters.
Listing 8. Modifying the getCalculator() method to schedule the life cycle task
public javax.xml.soap.SOAPElement getCalculator(java.lang.String accountName)
{
...
// Destroy the service after 30 seconds
Date startDate = new Date(System.currentTimeMillis() + 30000);
WSRLHelper.scheduleResourceLifeCycleTask(this.getSessionContext(),
startDate,
calcID);
...
}
|
The WSRLHelper should be used only if you follow these naming conventions:
- The life cycle bean should be named
<ServiceName>ResourceLifeCycleTaskBean(such asCalculatorResourceLifeCycleTaskBean). - The remote interface of the service implementation bean should be
<ServiceName>_RI.java(such asCalculator_RI.java).
The complete source code for the WSRL helper is included in the WASv5WSRLExtensions.jar.
This scheduleResourceLifeCycleTask() method walks through the following steps:
1. Looks up the home of the life cycle bean. Listing 9 illustrates this step.
Listing 9. Look up the lifecycle bean home
String taskId = null;
InitialContext ic = new InitialContext();
String className =
stub.getEJBHome().getEJBMetaData().getRemoteInterfaceClass().getName();
// Lets remove the word Remote from the end
int index = className.lastIndexOf("Remote");
if(index != -1) className = className.substring(0, index);
index = className.lastIndexOf(".");
if(index != -1) className = className.substring(index + 1, className.length());
String lookupName = "java:comp/env/ejb/"
+ className
+ "ResourceLifeCycleTask";
// Get the Task handler home
TaskHandlerHome taskHandlerHome = getTaskHandlerHome(lookupName);
|
2. Gets a handle to the ResourceLifeCycleScheduler scheduler. Listing 10 illustrates this step.
Listing 10. Get the scheduler object
Scheduler scheduler = null;
try {
InitialContext ic = new InitialContext();
Object o = ic.lookup("java:comp/env/ResourceLifeCycleScheduler");
scheduler =
(Scheduler) PortableRemoteObject.narrow(o, Scheduler.class);
} catch (NamingException e) {
e.printStackTrace();
}
|
3. Creates an instance of the BeanTaskInfo interface by using the createBeanTaskInfo() method on the scheduler. The TaskInfo interface contains various set methods that you can use to control aspects of the task's execution, including the time when the task will fire, and the work that the task will do when it fires. Listing 11 illustrates this step.
Listing 11. Populating the TaskInfo object
// Create Task info
BeanTaskInfo taskInfo = scheduler.createBeanTaskInfo();
taskInfo.setTaskHandler(taskHandlerHome);
taskInfo.setStartTime(startDate);
taskInfo.setName(pKey);
|
4. Submits the task to the scheduler instance for creation. Listing 12 illustrates this step.
Listing 12. Create the task
// Schedule Task
TaskStatus status = scheduler.create(taskInfo);
|
You are finished. You have now seen how the scheduled destruction of a WS-Resource can be implemented using the scheduler service in WebSphere Application Server, Enterprise Edition. In this example, you have hard-coded the 30-second interval. You can also have the WS-Resource client set this interval by calling the SetTerminationTime operation, provided that the Calculator Web service implements the operation. The WS-ResourceLifetime specification defines the SetTerminationTime operation and message exchange.
In a distributed computing environment with a large number of resources, it is important to make sure that these resources are destroyed in a controlled fashion, once they are no longer needed by service requestors. This article illustrates how two different WS-Resource destruction mechanisms can be implemented using existing tooling and runtime support in WebSphere Application Server, Enterprise Edition. It also provides minimal helper classes and documentation for building resources with life cycle support. While solutions that do not use the scheduler service are possible, this solution offers a clean and simple implementation by offloading the timer processing to the scheduler and making the Web service implementation agnostic to issues associated with threads in a J2EE environment. A new series of future articles will discuss programming model implementations of other WS-Resource specifications, such as WS-ResourceProperties, WS-ServiceGroup, and so forth. Watch for new developerWorks articles for this follow-on write-up.
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.
| Name | Size | Download method |
|---|---|---|
| ws-statefulws2code.zip | 382.0 KB | HTTP |
Information about download methods
- Read the other parts of the series "Implement and access stateful Web services using WebSphere Studio:"
- Part 1: Access resources through services (developerWorks, March 2004),
- Part 3: Accessing properties of a WS-Resource (developerWorks, June 2004).
- Part 4: Model dynamic WS-Resources (developerWorks, July 2004).
- Get the JAX-RPC specification from the Java Community Process.
- For more information on accessing and developing Web services in WebSphere Studio, check out "Support for J2EE Web Services in WebSphere Studio Application Developer V5.1, Part 1: The server environment," Greg Flurry (developerWorks, October 2003)
- Check out JSR 109, which covers Web services for J2EE environment.
- Check out the WebSphere Studio Application Developer Integration Edition trial downloads for Windows and Linux.
- For more on the Implied Resource pattern, see "Modeling stateful resource with Web services," Ian Foster, Jeffrey Frey, Steve Graham, Steve Tuecke, Karl Czajkowski, Don Ferguson, Frank Leymann, Martin Nally, Tony Storey, William Vambenepe, and Sanjiva Weerawarana (IBM/HP Whitepaper, January 2004)
- For more on the Web Services Resource Framework, see "Web Services Notification and Web Services Resource Framework," a set of specifications at IBM developerWorks.
- For more on Web Services Addressing, see "Web Services Addressing," specification at IBM developerWorks.
- More information on using the WebSphere Application Server scheduler service can be obtained from the WebSphere Application Server Enterprise Applications document. (Document is in PDF format.)
- Access Web services knowledge, tools, and skills with Speed-start Web services, which offers the latest Java-based software development tools and middleware from IBM (trial editions), plus online tutorials and articles, and an online technical forum.
- Browse for books on these and other technical topics.
- Want more? The developerWorks SOA and Web services zone hosts hundreds of informative articles and introductory, intermediate, and advanced tutorials on how to develop Web services applications.
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.
Comments (Undergoing maintenance)





