Skip to main content

Maintaining Session With JAX-WS

Posted by ramapulavarthi on June 7, 2006 at 10:26 AM PDT

Web Services are stateless by default because of the underlying HTTP protocol. The server processes each web service request as a new interaction even though it is from the same client. To have a knowledge about previous requests, Server would need to maintain state about the client through some sort. Maintaining state/session would have extra load on the client/server in terms of time and memory. Even then, sometimes stateful web services can be useful for conversational message exchange patterns, where multiple message exchanges are required between client and server.

By default JAX-WS Web Services and Clients are stateless. When a client makes a request, the server responds and sets a cookie on the connection, if it participates in a session. But, the JAX-WS client ignores that cookie and the server treats subsequent requests as new interaction. When the session is enabled, JAX-WS client sends the same cookie with each subsequent request so that server can keep track of the client session.

Lets start off with a simple Counter Web Service which tracks the user requests. Each time client calls getCounter(), the service returns the counter after incrementing by 1.

@WebService
public class Hello {
    int counter = 0;
    public int getCounter() {
        // incorrect – not unique for each client session.
        return counter++;
    }
}

Enabling session support for your web service would require little effort on the server and client.

Accessing Session on Server:

After the service endpoint is instantiated, the runtime system is required to initialize the endpoint instance before any requests can be serviced. If you are familiar with JAX-RPC based Web Service, enabling session support would require the service to implement javax.xml.rpc.server.ServiceLifecycle interface and its lifecycle methods init() and destroy(). The JAX-RPC runtime would pass the ServletEndpointContext which gives access to the message context, session, servlet context associated with each method invocation.

JAX-WS uses some handy annotations defined by Common Annotations for the Java Platform (JSR 250), to inject the Web Service context and declaring lifecycle methods. Web ServiceContext holds the context information pertaining to a request being served. You don’t need to implement javax.xml.rpc.server.ServiceLifecycle. With JAX-WS Web Service all you need to do is mark a field or method with @Resource. The type element MUST be either java.lang.Object (the default) or javax.xml.ws.WebServiceContext. If the former, then the resource will be injected into a field or a method. In this case, the type of the field or the type of the JavaBeans property defined by the method MUST be javax.xml.ws.WebServiceContext. From the WebServiceContext, message context pertaining to the the current request can be accessed. For more information on how message context can be used to share metadata is explained in this article. The following snippet from Hello Service shows the usage of annotations.

@WebService
public class Hello {
    @Resource
    private WebServiceContext wsContext;
    public int getCounter(){
        MessageContext mc = wsContext.getMessageContext();
        HttpSession session = ((javax.servlet.http.HttpServletRequest)mc.get(MessageContext.SERVLET_REQUEST)).getSession();
        // Get a session property "counter" from context
        if (session == null)
            throw new WebServiceException("No session in WebServiceContext");
        Integer counter = (Integer)session.getAttribute("counter");
        if (counter == null) {
            counter = new Integer(0);
            System.out.println("Starting the Session");
        }
        counter = new Integer(counter.intValue() + 1);
        session.setAttribute("counter", counter);
        return counter;

    }
}

JSR-250 also defines annotations for lifecycle methods, @PostConstruct and @PreDestroy. These lifecycle annotations (methods) can be used for effectively managing memory resources. After the resource injection is done, methods marked with @PostConstruct (similar to init method in JAX-RPC) are invoked before servicing any requests. Similarly methods marked with @PreDestroy are invoked before the service is destroyed.

Enabling Session on Client:

Session can be maintained just by setting the property “MessageContext.SESSION_MAINTAIN_PROPERTY” to true in the request context of the proxy/dispatch instance. For more information about setting properties in request context refer to this article.

Hello proxy = new HelloService().getHelloPort();
((BindingProvider)proxy).getRequestContext().put(BindingProvider.SESSION_MAINTAIN_PROPERTY,true);
int result = proxy.getCounter();
System.out.println(result);
result = proxy.getCounter();
System.out.println(result);

The above snippet from the HelloClient, prints 1 and 2 respectively.As shown above maintaining session with JAX-WS is easy.

Related Topics >>

Comments

Hi, your article is very

Hi,
your article is very interesting, I do have one question though...
There's one concept that I'm still failing to understand, since the wsContext field is an instance field and since we have only one webservice class I would expect having race conditions when trying to retrieve session data from the field...
my question is practically, how is this achieved ? if two requests of two different sessions are retrieved at the server and both threads handling these requests perform the lines:

MessageContext mc = wsContext.getMessageContext();
HttpSession session = ((javax.servlet.http.HttpServletRequest)mc.get(MessageContext.SERVLET_REQUEST)).getSession();
whilch session do we get ? do we get two different sessions for each thread ?
thanks,
Gil.

Hi, You do not have to worry about the synchronization/race ...

Hi,
You do not have to worry about the synchronization/race condition for WebServiceContext object. Implementation will take care the of this, basically implementation will use thread local to make it thread safe.

Thanks,
Prabir

Your example looks definitely

Your example looks definitely easy.
Do you think it would also so easy for a .NET client to enable session when calling a conversational java jax-ws web service ?
How would a c# snippet look like ?