Consider migrating an OC4J 10.1.3 web service to WebLogic. If the migration preserves the service WSDL description, the original client for that OC4J 10.1.3 web service will work with the migrated service. However, if the service is stateful, the original client will no longer work. OC4J 10.1.3 stateful web service uses HTTP session to track the web service session. WebLogic, on the other hand, does not support such http session-based stateful web service. One way to allow the original client to work with the migrated service is to modify the migrated service implementation to map http session into the web service session. Below is a modified service implementation.
package cyclecounter.test.oracle;
import java.net.URI;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Vector;
import javax.jws.WebService;
import javax.xml.rpc.server.ServiceLifecycle;
import javax.xml.rpc.server.ServletEndpointContext;
import weblogic.jws.WLHttpTransport;
@WebService(serviceName = "testsfWS-serssion", portName = "HttpSoap11", endpointInterface = "cyclecounter.test.oracle.CycleCounterInterface") @WLHttpTransport(serviceUri = "/HttpSoap11", portName = "HttpSoap11")
public class CycleCounterInterfaceImpl implements ServiceLifecycle {
private ServletEndpointContext context;
public void init(Object context){
this.context = ((ServletEndpointContext)context);
}
public void destroy() {
}
public int getCurrentCounter() {
CycleCounterImpl impl = SessionManager.getImpl(context);
return impl.getCurrentCounter();
}
}
The CycleCounterInterfaceImpl class serves as a wrapper around the actual service implementation. The SessionManager class maps JSESSIONID cookie to its corresponding service implementation instance.
package cyclecounter.test.oracle;
import java.util.HashMap;
import javax.servlet.http.HttpSession;
import javax.xml.rpc.handler.MessageContext;
import javax.xml.rpc.server.ServletEndpointContext;
import weblogic.wsee.connection.transport.servlet.HttpTransportUtils;
public class SessionManager {
// timeout in 15 seconds
private final static long timeout = 15 * 1000l;
private final static HashMap<HttpSession, Long> timeoutMap = new HashMap<HttpSession, Long>();
private final static HashMap<HttpSession, CycleCounterImpl> implMap = new HashMap<HttpSession, CycleCounterImpl>();
public static synchronized CycleCounterImpl getImpl(ServletEndpointContext context) {
MessageContext mc = context.getMessageContext();
HttpSession session = HttpTransportUtils.getHttpServletRequest(mc).getSession(true);
CycleCounterImpl impl=implMap.get(session);
if (impl!=null) {
long time = timeoutMap.get(session);
if (System.currentTimeMillis()>time+timeout) {
// session timed out
implMap.remove(session);
}
}
if (impl==null) {
// new session
impl = new CycleCounterImpl();
implMap.put(session, impl);
timeoutMap.put(session, System.currentTimeMillis());
}
return impl;
}
}
The SessionManager class could be enhanced for better session management, particularly configuring timeout, and pooling service implementation instances.
Comments (2)
I'm missing something here.
What's wrong with using the HTTPSession directly?
?
I've done this in WLS JAX-RPC handlers before, and I see no reason it wouldn't work in your example. As well as not having to mess around with your own HashMaps, WebLogic will also manage the creation of a cookie which will be routed correctly. (The random cookie you are creating will not work correctly in a WebLogic Server cluster).
- Phil
Posted by Philip Aston | September 15, 2009 4:46 AM
Posted on September 15, 2009 04:46
You suggestion worked for me. I modified the content to reflect your suggestion. Thank you for the correction.
Posted by quan.wang@oracle.com
|
September 15, 2009 10:45 AM
Posted on September 15, 2009 10:45