You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Arnaud DSA <ar...@gmail.com> on 2010/06/26 00:47:29 UTC

Maintaining session in multi threaded application for Spring jaxws client

Hi,

I used the cxf+spring sample :
http://cxf.apache.org/docs/writing-a-service-with-spring.html

And I need to:
- share a the proxy amongst different threads
- maintain sessions for each thread as I need to call three functions in
sequence: login/execute/logout

But I see in the doc
(http://cxf.apache.org/faq.html#FAQ-AreJAXWSclientproxiesthreadsafe?) that
the proxy is not thread safe in this case:
-----
*  Session support - if you turn on sessions support (see jaxws spec), the
session cookie is stored in the conduit. Thus, it would fall into the above
rules on conduit settings and thus be shared across threads.
For the conduit issues, you COULD install a new ConduitSelector that uses a
thread local or similar. That's a bit complex though.
-----
The doc mentions a "complex" solution but I could not fin more information
on this.


I tried to manually handle the cookie by fetching it into a thread local and
putting it back on each request instead of using maintainSession, but I
could not get the session cookie from the client.

My client is loaded from spring like this:
-----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

    <jaxws:client id="helloClient"
                  serviceClass="demo.spring.HelloWorld"
                  address="http://localhost:9002/HelloWorld" />
</beans>
-----
ApplicationContext context = new
ClassPathXmlApplicationContext("client.xml");
HelloWorld client = (HelloWorld) context.getBean("helloClient");
-----

I can cast the client to a BindingProvider, but I did not find a way to
fetch the session cookie from here:
BindingProvider bp = (BindingProvider) client;

Could someone tell me how to fetch and set the session cookie from the
client, or point me to another solution?

Thanks in advance.
--
Arnaud
-- 
View this message in context: http://old.nabble.com/Maintaining-session-in-multi-threaded-application-for-Spring-jaxws-client-tp28997255p28997255.html
Sent from the cxf-user mailing list archive at Nabble.com.


Re: Maintaining session in multi threaded application for Spring jaxws client

Posted by Arnaud DSA <ar...@gmail.com>.
Thanks a lot Daniel,

with your reply, I was able do what I needed.

Here it is in case someone else needs it:
-----
			List<String> cookies = null;
			while(true) {
			
				// Send cookies if available
				if (cookies != null) {
					Map<String, List<String>> requestHeaders = new HashMap<String,
List<String>>();
					requestHeaders.put("Cookie", cookies);
				
((BindingProvider)client).getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS,
requestHeaders);
				}
				
				String result = client.sayHi("Hello");

				// Fetch cookies set by server
				Map<String, List<String>> responseHeaders = (Map<String, List<String>>)
((BindingProvider)client).getResponseContext().get(MessageContext.HTTP_RESPONSE_HEADERS);
				cookies = responseHeaders.get("Set-Cookie");
			}
-----

For this to work, the thread local request context must be activated:
((BindingProvider)client).getRequestContext().put("thread.local.request.context",
Boolean.TRUE);

Here are the results of my tests:
thread.local.request.context without  SESSION_MAINTAIN_PROPERTY -> every
request of each thread uses a new session
SESSION_MAINTAIN_PROPERTY without thread.local.request.context -> only one
session shared across all the requests of all the thread
SESSION_MAINTAIN_PROPERTY with thread.local.request.context -> idem, only
one session shared across all the requests of all the thread

I think the behavior I achieved (session shared across requests of same
thread) should be the one we get when setting both parameters
SESSION_MAINTAIN_PROPERTY and thread.local.request.context
The shared session across all threads behaviour should be applied for
SESSION_MAINTAIN_PROPERTY without thread.local.request.context

Does it make sense?

Thanks again
--
Arnaud


dkulp wrote:
> 
> 
> The BindingProvider has a getResponseContext() call that returns a Map. 
> In 
> the map should be a MessageContext.RESPONSE_HEADERS (or something like
> that) 
> that would be the HTTP headers for the response.   You would need to walk 
> through them and find the cookie and such.   To send it is just the
> reverse.   
> Create a map, set the headers in there, the set it in the
> getRequestContext() 
> of the BindingProvider. 
> 
> You MAY need to tell the conduit to not maintain the session.   Otherwise,
> it 
> may overwrite your cookie.   Since you are going to handle it, no point in 
> having it do it anyway.
> 
> Dan
> 
> 
> On Friday 25 June 2010 6:47:29 pm Arnaud DSA wrote:
>> Hi,
>> 
>> I used the cxf+spring sample :
>> http://cxf.apache.org/docs/writing-a-service-with-spring.html
>> 
>> And I need to:
>> - share a the proxy amongst different threads
>> - maintain sessions for each thread as I need to call three functions in
>> sequence: login/execute/logout
>> 
>> But I see in the doc
>> (http://cxf.apache.org/faq.html#FAQ-AreJAXWSclientproxiesthreadsafe?)
>> that
>> the proxy is not thread safe in this case:
>> -----
>> *  Session support - if you turn on sessions support (see jaxws spec),
>> the
>> session cookie is stored in the conduit. Thus, it would fall into the
>> above
>> rules on conduit settings and thus be shared across threads.
>> For the conduit issues, you COULD install a new ConduitSelector that uses
>> a
>> thread local or similar. That's a bit complex though.
>> -----
>> The doc mentions a "complex" solution but I could not fin more
>> information
>> on this.
>> 
>> 
>> I tried to manually handle the cookie by fetching it into a thread local
>> and putting it back on each request instead of using maintainSession, but
>> I could not get the session cookie from the client.
>> 
>> My client is loaded from spring like this:
>> -----
>> <?xml version="1.0" encoding="UTF-8"?>
>> <beans xmlns="http://www.springframework.org/schema/beans"
>>        xmlns:jaxws="http://cxf.apache.org/jaxws"
>>        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>>        xsi:schemaLocation="
>> http://www.springframework.org/schema/beans
>> http://www.springframework.org/schema/beans/spring-beans.xsd
>> http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
>> 
>>     <jaxws:client id="helloClient"
>>                   serviceClass="demo.spring.HelloWorld"
>>                   address="http://localhost:9002/HelloWorld" />
>> </beans>
>> -----
>> ApplicationContext context = new
>> ClassPathXmlApplicationContext("client.xml");
>> HelloWorld client = (HelloWorld) context.getBean("helloClient");
>> -----
>> 
>> I can cast the client to a BindingProvider, but I did not find a way to
>> fetch the session cookie from here:
>> BindingProvider bp = (BindingProvider) client;
>> 
>> Could someone tell me how to fetch and set the session cookie from the
>> client, or point me to another solution?
>> 
>> Thanks in advance.
>> --
>> Arnaud
> 
> -- 
> Daniel Kulp
> dkulp@apache.org
> http://dankulp.com/blog
> 
> 

-- 
View this message in context: http://old.nabble.com/Maintaining-session-in-multi-threaded-application-for-Spring-jaxws-client-tp28997255p29012789.html
Sent from the cxf-user mailing list archive at Nabble.com.


Re: Maintaining session in multi threaded application for Spring jaxws client

Posted by Daniel Kulp <dk...@apache.org>.
The BindingProvider has a getResponseContext() call that returns a Map.  In 
the map should be a MessageContext.RESPONSE_HEADERS (or something like that) 
that would be the HTTP headers for the response.   You would need to walk 
through them and find the cookie and such.   To send it is just the reverse.   
Create a map, set the headers in there, the set it in the getRequestContext() 
of the BindingProvider. 

You MAY need to tell the conduit to not maintain the session.   Otherwise, it 
may overwrite your cookie.   Since you are going to handle it, no point in 
having it do it anyway.

Dan


On Friday 25 June 2010 6:47:29 pm Arnaud DSA wrote:
> Hi,
> 
> I used the cxf+spring sample :
> http://cxf.apache.org/docs/writing-a-service-with-spring.html
> 
> And I need to:
> - share a the proxy amongst different threads
> - maintain sessions for each thread as I need to call three functions in
> sequence: login/execute/logout
> 
> But I see in the doc
> (http://cxf.apache.org/faq.html#FAQ-AreJAXWSclientproxiesthreadsafe?) that
> the proxy is not thread safe in this case:
> -----
> *  Session support - if you turn on sessions support (see jaxws spec), the
> session cookie is stored in the conduit. Thus, it would fall into the above
> rules on conduit settings and thus be shared across threads.
> For the conduit issues, you COULD install a new ConduitSelector that uses a
> thread local or similar. That's a bit complex though.
> -----
> The doc mentions a "complex" solution but I could not fin more information
> on this.
> 
> 
> I tried to manually handle the cookie by fetching it into a thread local
> and putting it back on each request instead of using maintainSession, but
> I could not get the session cookie from the client.
> 
> My client is loaded from spring like this:
> -----
> <?xml version="1.0" encoding="UTF-8"?>
> <beans xmlns="http://www.springframework.org/schema/beans"
>        xmlns:jaxws="http://cxf.apache.org/jaxws"
>        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>        xsi:schemaLocation="
> http://www.springframework.org/schema/beans
> http://www.springframework.org/schema/beans/spring-beans.xsd
> http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
> 
>     <jaxws:client id="helloClient"
>                   serviceClass="demo.spring.HelloWorld"
>                   address="http://localhost:9002/HelloWorld" />
> </beans>
> -----
> ApplicationContext context = new
> ClassPathXmlApplicationContext("client.xml");
> HelloWorld client = (HelloWorld) context.getBean("helloClient");
> -----
> 
> I can cast the client to a BindingProvider, but I did not find a way to
> fetch the session cookie from here:
> BindingProvider bp = (BindingProvider) client;
> 
> Could someone tell me how to fetch and set the session cookie from the
> client, or point me to another solution?
> 
> Thanks in advance.
> --
> Arnaud

-- 
Daniel Kulp
dkulp@apache.org
http://dankulp.com/blog