OracleAS Web Services Runtime provides a support for stateful Web Services that is based on HTTP /Servlet session. Some people will probably say that Web Services should not be stateful, or at least not based on the protocol... However, today most of Web Services are using HTTP, and in some specific cases it is very useful to be able to have a state.
In this post, I am not explaining how to enable stateful services and clients, since it is documented in the Java Classes and Stateful Web Services chapter of the developer guide. Here I am show you how you can using client side programming share the same state (session) between different web services calls (even different services running in the same server side application).
The tip used here is about the association of cookies to the client instance (JAX-WS Stub or Call object). Here the code you have to write to do that using DII, will be very similar when using static Stub
1. Enable the state management
...
Service service = sf.createService(qName);
QName port = new QName("CartService");
Call call = service.createCall(port);
call.setProperty(Stub.SESSION_MAINTAIN_PROPERTY, Boolean.valueOf(true)); ...
2. Create a Map that contains the Cookies and assign it to the call (or Stub)
... Map cookieMap = new HashMap();
call.setProperty(ClientConstants.COOKIE_MAP, cookieMap);
...
This specific step associates a map that will contains all the cookie with the call/stub instance. You will be able then to manipulate the Map to get or set the cookies.
3. How to get the JSESSION cookie
private Cookie getJSessionCookie(Call call) {
Map cookies = (Map)call.getProperty(ClientConstants.COOKIE_MAP);
if (cookies != null && !cookies.isEmpty()) {
Iterator it = cookies.values().iterator();
while (it.hasNext()) {
Cookie cookie = (Cookie)it.next();
if (cookie.getName().equals("JSESSIONID")) {
return cookie;
}
}
}
return null;
}
Note that the Cookie object is an instance of Oracle HTTPClient.Cookie.
4. Utilizing the Cookie
So now you have all the information to be able to get the Session information when the stateful conversation has started;
In this example each time the call.invoke() is done, a counter is incremented on the server.
Call call = service.createCall(port);
call.setProperty(Stub.SESSION_MAINTAIN_PROPERTY, Boolean.valueOf(true)); Map cookieMap = new HashMap();
call.setProperty(ClientConstants.COOKIE_MAP, cookieMap);
... call.invoke(...);
... Cookie mySession = getJSessionCookie(call)
...
You can now use the cookie in another call using the following code:
mySession .. ...Call myNewCall = service.createCall(port);
myNewCall.setProperty(Stub.SESSION_MAINTAIN_PROPERTY, Boolean.valueOf(true)); Map cookieMap = new HashMap();
cookieMap.put(mySession,mySession);myNewCall.setProperty(ClientConstants.COOKIE_MAP, cookieMap);
...
myNewCall.invoke; ...
Using this sample you have 2 instances of a client calling a service and reusing the same session -state-. You can also use the same approach to have 2 different clients talking to different services and share the same session. To do that you will have on the server side to use the HTTP Session directly to store your data between calls, and share it between services.