« Understanding Custom Context propagation | Main | Developing custom MBeans to manage J2EE Applications (Part II) »

Stateful JAX-WS with Coherence*Web


We describe a stateful JAX-WS web service with high availability provided by Coherence*Web [1]. Deployed to two separate WebLogic managed servers, the web service stores its state in http session cookies. Coherence*Web distributes and synchronizes http session data between both managed servers. As a result, two endpoints with synchronized web service state provide high availability. With one endpoint down, another could continue to serve the service request with current web service state.

Note that WebLogic clustering can also provide highly available http sessions. However, we want to demonstrate Coherence*Web as an alternative to clustering for high availability. Therefore, we do not use clustering here. Instead, we use Coherence*Web.

Setting up the stateful web service with Coherence*Web involves the following steps.

  • start Coherence*Web cache server 
  • create and configure managed servers
    • deploy Coherence*Web as a shared library to the managed servers
  • create and deploy the web service
    • stores state in http session
    • instrument the web service using Coherence*Web
    • deploy the web service to both managed servers
Start Coherence*Web Cache Server

Start Coherence*Web cache server using the command below [2].

java -server -Xms512m -Xmx512m 
-cp coherence/lib/coherence.jar:coherence/lib/coherence-web-spi.war
-Dtangosol.coherence.management.remote=true
-Dtangosol.coherence.cacheconfig=WEB-INF/classes/session-cache-config.xml
-Dtangosol.coherence.session.localstorage=true
com.tangosol.net.DefaultCacheServer

Create and Configure Managed Servers

Copy coherence/lib/coherence.jar [2] to $DOMAIN_HOME/lib.

Start WebLogic AdminServer using

$DOMAIN_HOME/bin/startWebLogic.sh

Create two managed servers Server-2 at port 7012 and Server-3 at port 7013 using the admin console. Start both servers using the commands below.

$DOMAIN_HOME/bin/startManagedWebLogic.sh Server-2
$DOMAIN_HOME/bin/startManagedWebLogic.sh Server-3

Deploy coherence\lib\coherence-web-api.war [2] to the servers as a shared library. 

Create and Deploy the Web Service

Install Oracle Enterprise Pack for Eclipse (OEPE) on Eclipse Galileo [4]. In Eclipse, create a web service using the following WSDL and implementation.

<definitions
 xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
 xmlns:tns="http://oracle.ws.demo/"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 xmlns="http://schemas.xmlsoap.org/wsdl/"
 targetNamespace="http://oracle.ws.demo/"
 name="StatefulWSService">
<types>
<xsd:schema>
<xsd:import namespace="http://oracle.ws.demo/"
 schemaLocation="http://localhost:7001/Stateful_WS_Coherence/StatefulWSService?xsd=1" />
</xsd:schema>
</types>
<message name="addItem">
<part name="parameters" element="tns:addItem" />
</message>
<message name="addItemResponse">
<part name="parameters" element="tns:addItemResponse" />
</message>
<portType name="StatefulWS">
<operation name="addItem">
<input message="tns:addItem" />
<output message="tns:addItemResponse" />
</operation>
</portType>
<binding name="StatefulWSPortBinding" type="tns:StatefulWS">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
style="document" />
<operation name="addItem">
<soap:operation soapAction="" />
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
</binding>
<service name="StatefulWSService">
<port name="StatefulWSPort" binding="tns:StatefulWSPortBinding">
<soap:address
 location="http://localhost:7001/Stateful_WS_Coherence/StatefulWSService" />
</port>
</service>
</definitions>

StatefulWS.java and Item.java

package demo.ws.oracle;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.*;
import javax.xml.ws.handler.MessageContext;
import javax.jws.*;
import javax.annotation.Resource;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*
@WebService
public class StatefulWS {
@Resource
WebServiceContext ctx;
@WebMethod()
public int addItem(String name) {
HttpServletRequest req = (HttpServletRequest)
ctx.getMessageContext().get(MessageContext.SERVLET_REQUEST);
HttpSession session = req.getSession(true);
if (session == null)
throw new WebServiceException("No HTTP Session found");
System.out.println("httpsession: id="+session.getId());

//Get the cart object from the HttpSession
List<Item> cart = (List<Item>)session.getAttribute("myCart");
if (cart == null)
{ cart = new ArrayList(); }
// Add the item to the cart
cart.add(new Item(name));
// Save the updated cart in the HTTPSession
session.setAttribute("myCart", cart);
// return the number of items in the stateful cart
return cart.size();
}
}
package demo.ws.oracle;
public class Item implements java.io.Serializable {
public String name;public Item(String name){
this.name = name;
}
}

Add coherence-web-api library into weblogic.xml [2].

<weblogic-web-app
 xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://xmlns.oracle.com/weblogic/weblogic-web-app
 http://xmlns.oracle.com/weblogic/weblogic-web-app/1.0/weblogic-web-app.xsd"
>
<weblogic-version>10.3.1</weblogic-version>
<context-root>Stateful_WS_Coherence</context-root>
<library-ref>
<library-name>coherence-web-spi</library-name>
<specification-version>1.0.0.0</specification-version>
<implementation-version>1.0.0.0</implementation-version>
<exact-match>false</exact-match>
</library-ref>
</weblogic-web-app>

Deploy the web service to both managed servers.

Test 

Run the test.

package demo.ws;
import demo.ws.oracle.*;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider;

public class StatefulWSClient {
public static void main(String[] args) throws Exception {
StatefulWSService service =
new
StatefulWSService(Thread.currentThread().getContextClassLoader()
.getResource("META-INF/wsdls/StatefulWSService.wsdl")
 , new QName("http://oracle.ws.demo/", "StatefulWSService"));
StatefulWS port = service.getStatefulWSPort();

((BindingProvider)port).getRequestContext()
.put(BindingProvider.SESSION_MAINTAIN_PROPERTY, true);

((BindingProvider)port).getRequestContext()
.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
"http://stacd15.us.oracle.com:7012/Stateful_WS_Coherence/StatefulWSService");

System.out.println("calling " +
((BindingProvider)port).getRequestContext()
.get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY));
for (int j=0; j<5; j++) {
try {
int response = port.addItem("abc");
System.out.println("Got " + response);
Thread.currentThread().sleep(3000);
} catch (Exception ex) {}
}

((BindingProvider)port).getRequestContext()
.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
"http://stacd15.us.oracle.com:7013/Stateful_WS_Coherence/StatefulWSService");
System.out.println("calling " +
((BindingProvider)port).getRequestContext()
.get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY));
for (int j=0; j<5; j++) {
try {
int response = port.addItem("abc");
System.out.println("Got " + response);
Thread.currentThread().sleep(3000);
} catch (Exception ex) {}
}
}
}

The test invokes the web service five times for each endpoint.  The output shows that the returned count increases, indicating synchronized web service state across both endpoints.

calling http://stacd15.us.oracle.com:7012/Stateful_WS_Coherence/StatefulWSService
Got 1
Got 2
Got 3
Got 4
Got 5
calling http://stacd15.us.oracle.com:7013/Stateful_WS_Coherence/StatefulWSService
Got 6
Got 7
Got 8
Got 9
Got 10

Both managed servers output the same http session id's.

httpsession: id=tS1DNs2XTJZuQNhNfsl4fvpuj0Qd2ZnmTmHFKtKlUX4EytukR9V0!-280396885!1257829391923
httpsession: id=tS1DNs2XTJZuQNhNfsl4fvpuj0Qd2ZnmTmHFKtKlUX4EytukR9V0!-280396885!1257829391923
httpsession: id=tS1DNs2XTJZuQNhNfs14fvpuj0Qd2ZnmTmHFKtKlUX4EytukR9V0!-280396885!1257829391923
httpsession: id=tS1DNs2XTJZuQNhNfsl4fvpuj0Qd2ZnmTmHFKtKlUX4EytukR9V0!-280396885!1257829391923

Reference
  1. Coherence*Web and WebLogic Server
  2. Installing Coherence*Web on the WebLogic Server 10.3
  3. Stateful JAX-WS
  4. Oracle Enterprise Pack for Eclipse

TrackBack

TrackBack URL for this entry:
http://blogs.oracle.com/mt/mt-tb.cgi/15178

Post a comment

About This Entry

This page contains a single entry from the blog posted on November 9, 2009 9:11 PM.

The previous post in this blog was Understanding Custom Context propagation .

The next post in this blog is Developing custom MBeans to manage J2EE Applications (Part II).

Many more can be found on the main index page or by looking through the archives.

Powered by
Movable Type and Oracle