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
- Coherence*Web and WebLogic Server
- Installing Coherence*Web on the WebLogic Server 10.3
- Stateful JAX-WS
- Oracle Enterprise Pack for Eclipse
