JSESSIONID and setting cookie for WebServiceTemplate
Our existing application (Documentum CMS) Web App, has it's own authenication system which authenticates users; after the initial login the JSESSIONID in the cookie is the key way in which it authenticates users. We can then work with the CMS as that user.
What I'm trying to do is call a Spring Web Service (within the same webapp), from a Page within the Documentum Web App. The Web Service I'm calling is a simple service that returns content from the CMS to the user. In order to obtain the content; we need to obtain the JSESSIONID.
However, I cannot figure out how to set the JSESSIONID in a cookie on the WebServiceTemplate's MessageSender.
The message sender is of type CommonsHttpMessageSender, on which I've obtained the HttpClient and set on the HttpState the cookies from the original request (including the JSESSIONID).
However, when the doService(...) of MessageDispatcherServlet, the request object it has access to hasn't got any cookies set on it; and the HttpSession is new, and not the session that the JSESSIONID from the originating request references.
Basically the HttpServletRequest of the MessageDispatcherServlet I which to have the same HttpSession as the one the WebServiceTemplate's marshalSendAndReceive is called from.
I'm a bit stumped on how to do it. Can anyone help?
Using Tomcat 5.5, Spring 2.5, Spring WS 1.02, Apache Http Commons 3.1
Thanks Dom
Apologies, I'll try to clear up any misunderstandings
Hi gravy, nyrose.
First I'll try to describe what I have:
A web application 'wp' which serves up XML content (from a CMS [Content Management System]), via a spring webservice, on the url http://cmcdev2018/wp/soapservices. This is the server. In order to obtain content from the CMS I need a valid session, which is obtained via a JSESSIONID cookie.
I have a secondary web application on my local machine, which wishes to talk to the above webapp to obtain xml content. This is the client. The client has previously authenicated itself with the web application 'wp' on cmcdev2018. In order to call the web service, I need to pass info that says I've authenticated myself. This done by passing the authenicated JSESSION id; via a cookie. Unfortunately, the spring CommonsHttpMessageSender doesn't read the cookies set on a the HttpClient it uses; so I extended the spring CommonsHttpMessageSender; to do this:
Code:
package com.bbc.cmc.services.spring;
import org.apache.commons.httpclient.methods.PostMethod;
import org.springframework.ws.transport.http.CommonsHttpConnection;
import org.springframework.ws.transport.WebServiceConnection;
import org.springframework.ws.transport.http.CommonsHttpConnection;
import java.io.IOException;
import org.apache.commons.httpclient.Cookie;
/**
*
* @author tooted31
*/
public class CommonsHttpMessageSender extends org.springframework.ws.transport.http.CommonsHttpMessageSender
{
public WebServiceConnection createConnection(String uri) throws IOException
{
CommonsHttpConnection conn = (CommonsHttpConnection)super.createConnection(uri);
PostMethod pm = conn.getPostMethod();
Cookie[] cookies = getHttpClient().getState().getCookies();
int numberOfCookies = cookies.length;
for(int i = 0;i<numberOfCookies;i++)
{
pm.addRequestHeader("Cookie",cookies[i].toString());
}
return conn;
}
}
In the client's application context I have the following configuration:
Code:
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<property name="messageFactory">
<bean class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"/>
</property>
<property name="messageSender" ref="urlMessageSender"/>
<property name="marshaller" ref="getcontent_unmarshaller"/>
<property name="unmarshaller" ref="getcontent_marshaller"/>
<property name="defaultUri" value="http://cmcdev2018/wp/soapservices"/>
</bean>
<bean id="urlMessageSender" class="com.bbc.cmc.services.spring.CommonsHttpMessageSender"/>
<bean id="httpclient" class="org.apache.commons.httpclient.HttpClient" scope="prototype"/>
You can see from this client configuration. The webServiceTemplate is given the customized CommonsHttpMessageSender.
In the client's code which calls the web service on cmcdev2018's webapp 'wp'. I obtain the 'webServiceTemplate' from the application context, which is using my customized CommonsHttpMessageSender. I need set on the HttpClient, that the CommonsHttpMessageSender uses, the JSESSIONID cookie; before I call the web service via the template.marshalSendAndReceive(..). This is what the following code is doing:
Code:
WebServiceTemplate template = (WebServiceTemplate) context.getBean("webServiceTemplate");
// get the custom CommonsHttpMessageSender, of which I know there is only 1 set, and it is my custom CommonsHttpMessageSender
WebServiceMessageSender[] senders = template.getMessageSenders();
CommonsHttpMessageSender commons = (CommonsHttpMessageSender) senders[0];
// Build the JSESSIONID cookie I need to send to my web service
HttpServletRequest srequest = (HttpServletRequest) ((this.getPageContext()).getRequest());
javax.servlet.http.Cookie cookies[] = srequest.getCookies();
//Obtain a org.apache.commons.httpclient.HttpClient. And set the JSESSIONID cookie on a HttpState object.
HttpClient client = (HttpClient) context.getBean("httpclient");
HttpState state = new HttpState();
for (int i = 0; i < cookies.length; i++) {
javax.servlet.http.Cookie c = cookies[i];
if (c.getName().equals("JSESSIONID")) {
org.apache.commons.httpclient.Cookie newCookie = new org.apache.commons.httpclient.Cookie();
newCookie.setDomain(c.getDomain());
newCookie.setPath(c.getPath());
newCookie.setName(c.getName());
newCookie.setValue(c.getValue());
state.addCookie(newCookie);
}
}
state.setCookiePolicy(org.apache.commons.httpclient.cookie.CookiePolicy.COMPATIBILITY);
client.setState(state);
commons.setHttpClient(client);
After the above code on the client I just call the WebServiceTemplate.marshallSendAndRecieve(..) method to call the webservice.
All the above code to Set the cookie on a the HttpClient object used by the CommonsHttpMessageSender should really be made into a utility/factory method.
I hope that makes it easier to understand.
/dom