Hi,

I have found a flaw in the HTTP-Session Handling I implemented some time ago:

If all the endpoints supporting HTTP-Session Handling are called in a multicast 
and the scope of the session is supposed to be the exchange, this will not work 
as expected.

See the following examples:
                from("direct:exchange")
                    .to(getTestServerEndpointSessionUrl() + 
"?cookieHandler=#exchangeCookieHandler")
                    .to(getTestServerEndpointSessionUrl() + 
"?cookieHandler=#exchangeCookieHandler")
                    .to("mock:result");

                from("direct:exchangeWithHandlerBeforeMulticast")
                    .streamCaching()
                    .to(getTestServerEndpointSessionUrl() + 
"?cookieHandler=#exchangeCookieHandler")
                    .multicast(new SimpleConcatenationStrategy())
                        .to(getTestServerEndpointSessionUrl() + 
"?cookieHandler=#exchangeCookieHandler")
                        .to(getTestServerEndpointSessionUrl() + 
"?cookieHandler=#exchangeCookieHandler")
                    .end()
                    .to("mock:result");

                from("direct:exchangeWithMulticast")
                    .streamCaching()
                    .multicast(new SimpleConcatenationStrategy())
                        .to(getTestServerEndpointSessionUrl() + 
"?cookieHandler=#exchangeCookieHandler")
                        .to(getTestServerEndpointSessionUrl() + 
"?cookieHandler=#exchangeCookieHandler")
                    .end()
                    .to("mock:result");

The first two examples work, the third does not work. The reason for that is 
that the ExchangeCookieHandler will store the HTTP session cookies in an 
exchange property. In the first example there is only one single exchange, so 
we have no issues there. In the second example the exchange is copied for the 
multicast branches, but as there is an endpoint supporting cookies before the 
multicast all these copied exchanges will get the exchange property with the 
reference to the cookie store and work as expected. In the third example each 
of the multicast branches will get a new exchange without a cookie store and 
will create a (separate) new ones, so the two calls cannot share a session.

A workaround for the issue would be the following change in the route:
                from("direct:exchangeWithMulticast")
                    .streamCaching()
                    .setProperty("dummy").method("exchangeCookieHandler", 
"getCookieStore")
                    .multicast(new SimpleConcatenationStrategy())
                        .to(getTestServerEndpointSessionUrl() + 
"?cookieHandler=#exchangeCookieHandler")
                        .to(getTestServerEndpointSessionUrl() + 
"?cookieHandler=#exchangeCookieHandler")
                    .end()
                    .to("mock:result");

calling the getCookieStore method in the exchangeCookieHandler (with the 
initial exchange as a parameter) will create an empty cookie store and set it 
to the exchange property. This store reference is copied to the exchanges used 
in the multicast and both exchanges can share the session again.

How do we handle this now. I see the following theoretical options:

1.       One option would be to fix this in the code of the 
ExchangeCookieHandler, but I see no way how an entity running in a copied 
exchange could access the exchange it was copied from. Is there some way for 
that?

2.       If the first option is not feasible, we should at least document this 
behavior (and provide a solution how to create the cookie store exchange 
property). The method of setting a dummy exchange property with a bean method 
expression looks a bit ugly to me. The same could also be done with a processor 
(doing some ExchangeCookieHandler.getCookieStore(exchange) call). What would be 
the most elegant way to do so?

What would be the best approach to proceed?

Best regards
Stephan

Reply via email to