Announcement Announcement Module
Collapse
No announcement yet.
JSESSIONID and setting cookie for WebServiceTemplate Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • 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

  • #2
    I had another play around with this today, and got it to work by extending the CommonsHttpMessageSender as follows:

    public class CommonsHttpMessageSender extends org.springframework.ws.transport.http.CommonsHttpM essageSender
    {

    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;
    }
    }

    The cookie is now set when the request is sent from the WebServiceTemplate's marshalSendAndReceive(...) method. The doService on MessageDispatcherServlet now has access to the cookie, and the correct (already authenicate) HttpSession is being returned from the HttpServletRequest.getSession() rather than a new one created...


    code on the client side before the marshalSendAndRecieve() is the same as I had before subclassing CommonsHttpMessageSender:

    WebServiceMessageSender[] senders = template.getMessageSenders();

    CommonsHttpMessageSender commons = (CommonsHttpMessageSender) senders[0];
    HttpServletRequest srequest = (HttpServletRequest) ((this.getPageContext()).getRequest());
    javax.servlet.http.Cookie cookies[] = srequest.getCookies();


    HttpClient client = (HttpClient) SpringAppContextMgr.getWebServiceBean("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.httpclien t.cookie.CookiePolicy.COMPATIBILITY);


    client.setState(state);
    commons.setHttpClient(client);

    Comment


    • #3
      Hello,

      i want to do something similar. At first time, when client connects to service it has no JSESSIONID. Server creates session, and responses with JSESSIONID stored in response cookie. Next calls to web services are identified using created JSESSIONID.

      I created custom MessageSender like you. My question is, where to put this code:

      Code:
      WebServiceMessageSender[] senders = template.getMessageSenders();
      
      CommonsHttpMessageSender commons = (CommonsHttpMessageSender) senders[0];
      HttpServletRequest srequest = (HttpServletRequest) ((this.getPageContext()).getRequest());
      javax.servlet.http.Cookie cookies[] = srequest.getCookies();
      
      
      HttpClient client = (HttpClient) SpringAppContextMgr.getWebServiceBean("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.httpclien t.cookie.CookiePolicy.COMPATIBILITY);
      
      
      client.setState(state);
      commons.setHttpClient(client);
      Thanks

      Comment


      • #4
        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

        Comment


        • #5
          Hi Dom,

          thx for answer, it is clear to me now what u meaned. In meanwhile i figured what i wanted. I wanted to create session for ws client. I did it by subclassing MessageDispatcherServlet and opening a session on accepted request in servlet's doService method. Now when the client connects to the service for the first time, server creates session for him, and when i use more calls with the same client, the cookie JsessionId is set By the way, i used CommonsHttpMessageSender and he sends all cookies that have been set. I only needed to setMessageSender into my client. Your code will be needed for authenticating different instances of clients in the same session.

          Thanks

          Gravy

          Comment


          • #6
            Hi gravy,

            How do you access the session id from within the service end point?

            Comment


            • #7
              I do not access it in the endpoint, i can access it in the DispatcherServlet's doService method. I don't know if/how it can be accessed in the endpoint.

              Gravy

              Comment


              • #8
                Hey Gravy,

                After opening a session in the doService method, how did you reference it or get a handle to it in your Endpoint class?

                thanks

                Comment


                • #9
                  ok, I think I know what u did. thanks.

                  Comment


                  • #10
                    Ok, im happy

                    Comment


                    • #11
                      Code on the server side

                      Hi Guys,

                      I am too working with cookies for my Spring webservices. Please can you show me the code tha you use on the Server side to generate a cookie and store the data in the cookie and send it back to the client.

                      Cheers,
                      Sanjay Patil

                      Comment


                      • #12
                        This is my servlet code:

                        Code:
                        package org.foo;
                        
                        import javax.servlet.http.HttpServletRequest;
                        import javax.servlet.http.HttpServletResponse;
                        import javax.servlet.http.HttpSession;
                        
                        import org.springframework.ws.transport.http.MessageDispatcherServlet;
                        
                        public class MyMessageDispatcherServlet extends MessageDispatcherServlet {
                            @Override
                            protected void doService(HttpServletRequest httpServletRequest,
                                    HttpServletResponse httpServletResponse) throws Exception {
                                HttpSession session = httpServletRequest.getSession();
                                super.doService(httpServletRequest, httpServletResponse);
                            }
                        }
                        You need to change web.xml for your server to configure web services:

                        Code:
                        <!-- Spring-WS Servlet -->
                        <servlet>
                             <servlet-name>WebServices</servlet-name>
                             <servlet-class>org.foo.MyMessageDispatcherServlet</servlet-class>
                             ...
                        </servlet>

                        Comment


                        • #13
                          Accessing HttpServletRequest in POJO class

                          Hi,

                          Thanks for the response. I do have some more queries now.

                          1. I want to call the webservices from a service class which is a POJO class, not from jsp or Servlet as shown above. So is there any Spring utility class I can use to get a handle to HttpServletRequest. I can see you guys have used below code for the same, which i guess is in a jsp file.

                          HttpServletRequest srequest = (HttpServletRequest) ((this.getPageContext()).getRequest());

                          I have not tried below code yet which I found on another forum log. I presume this will work only if I have server connection which is not the case for me.

                          TransportContext context = TransportContextHolder.getTransportContext();
                          HttpServletConnection connection = (HttpServletConnection) context.getConnection();
                          HttpServletRequest request = connection.getHttpServletRequest();


                          Cheers,
                          Sanjay Patil

                          Comment


                          • #14
                            My Java code

                            Hi,

                            Sorry, I forgot to attach my code. Please find the same below.

                            Code:
                            package com.sample.webservice;
                            
                            import java.io.IOException;
                            import java.net.URI;
                            import java.net.URISyntaxException;
                            
                            import javax.servlet.http.HttpServletRequest;
                            import javax.xml.transform.TransformerException;
                            
                            import org.apache.commons.httpclient.Cookie;
                            import org.apache.commons.httpclient.HttpClient;
                            import org.apache.commons.httpclient.HttpState;
                            import org.apache.commons.httpclient.methods.PostMethod;
                            import org.springframework.ws.WebServiceMessage;
                            import org.springframework.ws.client.core.WebServiceMessageCallback;
                            import org.springframework.ws.client.core.WebServiceTemplate;
                            import org.springframework.ws.pox.dom.DomPoxMessageFactory;
                            import org.springframework.ws.transport.WebServiceConnection;
                            import org.springframework.ws.transport.WebServiceMessageSender;
                            import org.springframework.ws.transport.context.TransportContext;
                            import org.springframework.ws.transport.context.TransportContextHolder;
                            import org.springframework.ws.transport.http.CommonsHttpConnection;
                            import org.springframework.ws.transport.http.CommonsHttpMessageSender;
                            import org.springframework.xml.transform.StringResult;
                            import org.springframework.xml.transform.StringSource;
                            
                            public class WebServiceAgent {
                            
                            	private WebServiceTemplate webServiceTemplate;
                            	
                            	private class MyCommonsHttpMessageSender extends org.springframework.ws.transport.http.CommonsHttpMessageSender {
                            
                            		public WebServiceConnection createConnection(URI uri) throws IOException {
                            			CommonsHttpConnection connection = (CommonsHttpConnection) super.createConnection(uri);
                            			PostMethod pm = connection.getPostMethod();
                            
                            			Cookie[] cookies = getHttpClient().getState().getCookies();
                            			int numberOfCookies = cookies.length;
                            			for (int i = 0; i < numberOfCookies; i++) {
                            				pm.addRequestHeader("Cookie", cookies[i].toString());
                            			}
                            			return connection;
                            		}
                            
                            		public boolean supports(URI arg0) {
                            			// TODO Auto-generated method stub
                            			return false;
                            		}
                            
                            	}
                            
                            	
                            	class MyWebServiceMessageCallback implements WebServiceMessageCallback {
                            	    public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {
                            	        TransportContext transportContext = TransportContextHolder.getTransportContext();
                            	        WebServiceConnection connection = transportContext.getConnection();
                            	        
                            	        /**/
                            	        
                            	    }
                            	}
                            	
                            	public static void main(String[] args) {
                            
                            		WebServiceAgent webServiceTest = new WebServiceAgent();
                            
                            		webServiceTest.doSomething();
                            	}
                            
                            	public void doSomething() {
                            
                            		StringSource stringSource = new StringSource("..... INPUT XML ......");
                            		StringResult stringResult = new StringResult();
                            
                            		// initializing the webservicetemplate in place of using application context xml.
                            		
                            		webServiceTemplate = new MyWebServiceTemplate(new DomPoxMessageFactory());
                            		MyCommonsHttpMessageSender messageSender = new MyCommonsHttpMessageSender();		
                            		try {
                            			messageSender.createConnection(new URI("http://localhost:9081/webserviceURL"));
                            		} catch (IOException e) {
                            			// TODO Auto-generated catch block
                            			e.printStackTrace();
                            		} catch (URISyntaxException e) {
                            			// TODO Auto-generated catch block
                            			e.printStackTrace();
                            		}
                            		webServiceTemplate.setMessageSender(messageSender);
                            
                            		webServiceTemplate.setDefaultUri("http://localhost:9081/webserviceURL");
                            		
                            		// end of webservice initialization
                            		
                            		WebServiceMessageSender[] senders = webServiceTemplate.getMessageSenders();
                            		CommonsHttpMessageSender commons = (CommonsHttpMessageSender) senders[0];
                            
                            		HttpClient client = new HttpClient();
                            
                            		HttpState state = new HttpState();
                            		
                            //		 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();
                            		
                            		
                            		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);
                            			}
                            		}
                            		
                            
                            		client.setState(state);
                            		commons.setHttpClient(client);
                            		
                            		webServiceTemplate.sendSourceAndReceiveToResult(stringSource, new MyWebServiceMessageCallback(), stringResult);
                            
                            	}
                            
                            
                            }

                            Comment


                            • #15
                              So you need to obtain JSESSIONID from somewhere to identify yourself with the webservice.

                              You need to store JSESSIONID which server generates at first HttpRequest, and then somehow pass it to the client code, so it can authenticate itself with same JSESSIONID as the code you posted shows. I don't know which technologies are you using, and what is the scenario of communication through WS. But when you have no previous Http communication with server, then you cant have any JSESSIONID. Dont know if i put this straight

                              Comment

                              Working...
                              X