You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by John McLaughlin <jm...@gmail.com> on 2007/09/18 19:15:24 UTC

Sharing session with multiple services

Hi,

	I've just started to look at CXF, and have successfully managed to 
quickly develop/deploy.

	The scenario I have is that I will have multiple web services running 
in Tomcat, and I want to maintain a session across them. I'm defining 
the services using JAX-WS (newbie here too!)

	I can set BindingProvider.SESSION_MAINTAIN_PROPERTY on the client side 
to true, and this works fine on an individual proxy with JSESSIONID sent 
received, and I can access the appropriate session on the server side. 
However, when I call a second service it results in another session 
being started.

	I've been trawling through APIs and the mail archives all afternoon, 
but haven't come up with any answers. Is it possible to retrieve the 
JSESSIONID from the first service and stuff it into the second service? 
I'm guessing an Interceptor on the client would be the way to go, but I 
haven't been able to find any examples. Failing all that, would it be a 
valid approach to add an Interceptor which would add/extract a header on 
messages?

	I'd prefer to go with the JSESSIONID as I can let Tomcat take care of 
the session management, so if anybody can point me in the right 
direction, I'd much appreciate it!

Thanks,

John

Re: Sharing session with multiple services

Posted by Willem Jiang <ni...@iona.com>.
Hi,

I don't think it can be done by adding the interceptor now , because CXF 
HttpConduit [1] just holds the cookies  as  it's  member variable.
And for each Client proxy, CXF will set up a different HttpConduit for 
the http connection.
If you want to accomplish the task, you need do some extract work on 
HttpConduit.
I will see if you can set the http header some place and let the 
HttpConduit consumer it later today.

[1]https://svn.apache.org/repos/asf/incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java

Willem.
John McLaughlin wrote:
> Hi,
>
>     I've just started to look at CXF, and have successfully managed to 
> quickly develop/deploy.
>
>     The scenario I have is that I will have multiple web services 
> running in Tomcat, and I want to maintain a session across them. I'm 
> defining the services using JAX-WS (newbie here too!)
>
>     I can set BindingProvider.SESSION_MAINTAIN_PROPERTY on the client 
> side to true, and this works fine on an individual proxy with 
> JSESSIONID sent received, and I can access the appropriate session on 
> the server side. However, when I call a second service it results in 
> another session being started.
>
>     I've been trawling through APIs and the mail archives all 
> afternoon, but haven't come up with any answers. Is it possible to 
> retrieve the JSESSIONID from the first service and stuff it into the 
> second service? I'm guessing an Interceptor on the client would be the 
> way to go, but I haven't been able to find any examples. Failing all 
> that, would it be a valid approach to add an Interceptor which would 
> add/extract a header on messages?
>
>     I'd prefer to go with the JSESSIONID as I can let Tomcat take care 
> of the session management, so if anybody can point me in the right 
> direction, I'd much appreciate it!
>
> Thanks,
>
> John
>

Re: Sharing session with multiple services

Posted by Pierre Buyle <pi...@irislink.com>.
Hi,

I did it with a CFX Interceptor. The code looks a lot like my JAX-WS
Handler. The headers Map is retrieved with
message.get(Message.PROTOCOL_HEADERS). And
message.get(Message.INBOUND_MESSAGE) is used as test to select between
handleInMessage and handleOutMessage.

I had to try several phases. None of (PRE/USER/POST)_PROTOCOL did work, but
PRE_LOGICAL does.

According to the documentation, JAX-WS Handlers are in one of the
(PRE/USER/POST)_PROTOCOL phase. If Interceptors cannot add HTTP headers in
this phase, I understand why my handler didn't work. But it doesn't seems
right to me since JAX-WS Handlers should be able to do it.


Pierre Buyle wrote:
> 
> I've the same requirements for my services. A session is initialized on
> the first call to a services and should be shared with others. On the
> server side, I've written Interceptors to fetch and store the session data
> in message.getExchange().getSession().
> 
> Using soapUI I can manually set the JSESSIONID cookie in the HTTP Header
> nad the session is effectivly maintained across services.
> 
> Since I don't want client code to care about the session, I'm trying to
> implement session handling in a JAX-WS Handler. Here is my code
> [...]
> As you can see, it simply store the JSESSIONID cookie in a static field
> when found in a in-message and put it back in out-messages.
> 
> This handler is added to the handler chain of each of my JAX-WS Proxy like
> this:
> 	...
> 
> ((BindingProvider)client).getRequestContext().put(BindingProvider.SESSION_MAINTAIN_PROPERTY,
> true);
> 	List<Handler> handlers =
> ((BindingProvider)client).getBinding().getHandlerChain();
> 	handlers.add(sessionHandler);
> 	...
> 
> But it doesn't work. Even if the "cookie.add(sessionCookie);" line is
> executed with the right value, I don't see any "Cookie" header in tcpmon.
> 
> Does someone have any idea why it doesn't work ?
> 
> 
> dkulp wrote:
>> 
>> 
>> On the client side, you should be able to get the transport headers from 
>> the response context.   From there, you could pull the Cookie header out 
>> and do the cooking processing yourself.    On the second proxy, you 
>> would set the request headers into the request context.   There wouldn't 
>> need to be any interceptor involved.
>> 
> 
> 

-- 
View this message in context: http://www.nabble.com/Sharing-session-with-multiple-services-tf4475754.html#a13750532
Sent from the cxf-user mailing list archive at Nabble.com.


Re: Sharing session with multiple services

Posted by Pierre Buyle <pi...@irislink.com>.
I've the same requirements for my services. A session is initialized on the
first call to a services and should be shared with others. On the server
side, I've written Interceptors to fetch and store the session data in
message.getExchange().getSession().

Using soapUI I can manually set the JSESSIONID cookie in the HTTP Header nad
the session is effectivly maintained across services.

Since I don't want client code to care about the session, I'm trying to
implement session handling in a JAX-WS Handler. Here is my code
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.ws.handler.Handler;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPMessageContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class SessionHandler implements Handler<SOAPMessageContext>
{
	private static String sessionCookie = null;
	private static final String SET_COOKIE = "Set-Cookie";
	private static final String COOKIE = "Cookie";
	private static final String JSESSIONID = "JSESSIONID";
	private static Pattern cookiePattern =
Pattern.compile("([^\\p{Cntrl}\\s]+)=(\\w+|\".*\").*");
	
        private Log log =  LogFactory.getLog(SessionHandler.class);
	
	public void close(MessageContext messageContext)
	{

	}

	public boolean handleFault(SOAPMessageContext messageContext)
	{
		return false;
	}

	public boolean handleMessage(SOAPMessageContext messageContext)
	{
		if(((Boolean)
messageContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY)))
			return handleOutMessage(messageContext);
		else
			return handleInMessage(messageContext);
	}
	
	private boolean handleOutMessage(SOAPMessageContext messageContext)
	{
		@SuppressWarnings("unchecked")
		Map<String, List<String>> headers = (Map<String, List<String>>)
messageContext.get(MessageContext.HTTP_REQUEST_HEADERS);
		if(sessionCookie!=null)
		{
			if(headers==null)
			{
				headers = new HashMap<String, List<String>>();
				messageContext.put(MessageContext.HTTP_REQUEST_HEADERS, headers);
			}
			List<String> cookie = headers.get(COOKIE);
			if(cookie==null)
			{
				cookie = new ArrayList<String>();
				headers.put(COOKIE, cookie);
			}
			cookie.add(sessionCookie);
			log.debug("Cookie added to HTTP Header: " + sessionCookie);
		}
		return true;
	}

	private boolean handleInMessage(SOAPMessageContext messageContext)
	{
		@SuppressWarnings("unchecked")
		Map<String, List<String>> headers = (Map<String, List<String>>)
messageContext.get(MessageContext.HTTP_RESPONSE_HEADERS);
		if(headers!=null)
		{
			List<String> setCookie = headers.get(SET_COOKIE);
			if(setCookie!=null)
			{
				for(String cookie: setCookie)
				{
					Matcher cookieMatcher = cookiePattern.matcher(cookie);
					if(cookieMatcher.find())
					{
						String name = cookieMatcher.group(1);
						String value = cookieMatcher.group(2);
						if(name.toUpperCase().equals(JSESSIONID))
						{
							sessionCookie = name + '=' + value;
							log.debug("Cookie retrieved from HTTP Header:" + sessionCookie);
						}
					}
				}
			}
		}
		return true;
	}
}
As you can see, it simply store the JSESSIONID cookie in a static field when
found in a in-message and put it back in out-messages.

This handler is added to the handler chain of each of my JAX-WS Proxy like
this:
	...

((BindingProvider)client).getRequestContext().put(BindingProvider.SESSION_MAINTAIN_PROPERTY,
true);
	List<Handler> handlers =
((BindingProvider)client).getBinding().getHandlerChain();
	handlers.add(sessionHandler);
	...

But it doesn't work. Even if the "cookie.add(sessionCookie);" line is
executed with the right value, I don't see any "Cookie" header in tcpmon.

Does someone have any idea why it doesn't work ?


dkulp wrote:
> 
> 
> On the client side, you should be able to get the transport headers from 
> the response context.   From there, you could pull the Cookie header out 
> and do the cooking processing yourself.    On the second proxy, you 
> would set the request headers into the request context.   There wouldn't 
> need to be any interceptor involved.
> 
> In pseudo code:
> 
> port.makeACallToTheService(....);
> BindingProvider bp = (BindingProvider)port;
> Map<String, List<String>> headers = bp.getResponseContext().
>    get("javax.xml.ws.http.response.headers");
> 
> ...   get the cookie from it .....
> 
> bp = (BindingProvider)port2;
> Map<String, List<String>> headers = bp.getRequestContext().
>    get("javax.xml.ws.http.request.headers");
> if (headers == null) {
>     headers = new HashMap<String, List<String>>();
>     bp.getRequestContext().put("javax......", headers);
> }
> headers.put("cookie stuff"....);
> port2.makeSecondCall(...);
> 
> 
> Dan
> 
> 
> 
> On Tuesday 18 September 2007, John McLaughlin wrote:
>> Hi,
>>
>> 	I've just started to look at CXF, and have successfully managed to
>> quickly develop/deploy.
>>
>> 	The scenario I have is that I will have multiple web services running
>> in Tomcat, and I want to maintain a session across them. I'm defining
>> the services using JAX-WS (newbie here too!)
>>
>> 	I can set BindingProvider.SESSION_MAINTAIN_PROPERTY on the client
>> side to true, and this works fine on an individual proxy with
>> JSESSIONID sent received, and I can access the appropriate session on
>> the server side. However, when I call a second service it results in
>> another session being started.
>>
>> 	I've been trawling through APIs and the mail archives all afternoon,
>> but haven't come up with any answers. Is it possible to retrieve the
>> JSESSIONID from the first service and stuff it into the second
>> service? I'm guessing an Interceptor on the client would be the way to
>> go, but I haven't been able to find any examples. Failing all that,
>> would it be a valid approach to add an Interceptor which would
>> add/extract a header on messages?
>>
>> 	I'd prefer to go with the JSESSIONID as I can let Tomcat take care of
>> the session management, so if anybody can point me in the right
>> direction, I'd much appreciate it!
>>
>> Thanks,
>>
>> John
> 
> 
> 
> -- 
> J. Daniel Kulp
> Principal Engineer
> IONA
> P: 781-902-8727    C: 508-380-7194
> daniel.kulp@iona.com
> http://www.dankulp.com/blog
> 
> 

-- 
View this message in context: http://www.nabble.com/Sharing-session-with-multiple-services-tf4475754.html#a13730346
Sent from the cxf-user mailing list archive at Nabble.com.


Re: Sharing session with multiple services

Posted by Daniel Kulp <dk...@apache.org>.
On the client side, you should be able to get the transport headers from 
the response context.   From there, you could pull the Cookie header out 
and do the cooking processing yourself.    On the second proxy, you 
would set the request headers into the request context.   There wouldn't 
need to be any interceptor involved.

In pseudo code:

port.makeACallToTheService(....);
BindingProvider bp = (BindingProvider)port;
Map<String, List<String>> headers = bp.getResponseContext().
   get("javax.xml.ws.http.response.headers");

...   get the cookie from it .....

bp = (BindingProvider)port2;
Map<String, List<String>> headers = bp.getRequestContext().
   get("javax.xml.ws.http.request.headers");
if (headers == null) {
    headers = new HashMap<String, List<String>>();
    bp.getRequestContext().put("javax......", headers);
}
headers.put("cookie stuff"....);
port2.makeSecondCall(...);


Dan



On Tuesday 18 September 2007, John McLaughlin wrote:
> Hi,
>
> 	I've just started to look at CXF, and have successfully managed to
> quickly develop/deploy.
>
> 	The scenario I have is that I will have multiple web services running
> in Tomcat, and I want to maintain a session across them. I'm defining
> the services using JAX-WS (newbie here too!)
>
> 	I can set BindingProvider.SESSION_MAINTAIN_PROPERTY on the client
> side to true, and this works fine on an individual proxy with
> JSESSIONID sent received, and I can access the appropriate session on
> the server side. However, when I call a second service it results in
> another session being started.
>
> 	I've been trawling through APIs and the mail archives all afternoon,
> but haven't come up with any answers. Is it possible to retrieve the
> JSESSIONID from the first service and stuff it into the second
> service? I'm guessing an Interceptor on the client would be the way to
> go, but I haven't been able to find any examples. Failing all that,
> would it be a valid approach to add an Interceptor which would
> add/extract a header on messages?
>
> 	I'd prefer to go with the JSESSIONID as I can let Tomcat take care of
> the session management, so if anybody can point me in the right
> direction, I'd much appreciate it!
>
> Thanks,
>
> John



-- 
J. Daniel Kulp
Principal Engineer
IONA
P: 781-902-8727    C: 508-380-7194
daniel.kulp@iona.com
http://www.dankulp.com/blog