2009/01/04
4 Jan, 2009

Axis2 Session Management: Part 2

  • Deepal Jayasingha
  • - WSO2

Request Session Scope

Request session scope is the default session scope in Axis2. When we deploy a service without knowing anything about session management, then our service will be deployed in request session scope; this is much like using no session management at all. The lifetime of this session is limited to method invocation lifetime, or the request processing time.

Once we deploy a service in request session scope, for each individual invocation a new service implementation class will be created. Let's say we have deployed a service called "Foo" in request scope. If a client invokes the service 10 times, there will be 10 instances of the service implementation class.

If we want to specify the scope explicitly, we can still do that by adding scope attribute to service element in services.xml as follows:

 <service name="Foo"  scope="request">  </service>  

To get a better understanding of request scope, create a service using the following service class, deploy it and invoke:

 public class MyService implements Lifecycle {      public void init(ServiceContext context) throws AxisFault {         System.out.println("I'm inside init method ");     }      public void destroy(ServiceContext context) {         System.out.println("I'm inside destroy method");     }      public String foo(String foo) {         return foo;     } } 

Note: To invoke the service, we simply type the following in the browser:

https://localhost:8080/axis2/services/MyService/foo?foo=foo

Then we will see the following in the server console:

I'm inside init method

If we continue to do so, we will see this statement printed every time we invoke the service.

It should be noted here that even if we deploy a service in a request scope, there are many ways of keeping our service as a state full service. One approach is to store the state in Axis2 global run time (ConfigurationContext) and retrieve whenever necessary.

SOAP Session Scope

The purpose of SOAP session is to have a transport-independent way of managing sessions between two SOAP nodes, the client and the server. Here Axis2 uses SOAP headers in order to manage the session. SOAP session scope has a slightly longer lifetime than request session scope; deploying a service in SOAP session is required to change services.xml as well. Managing SOAP session requires both the client and service to be aware of the sessions. This means that the client has to send the session-related data if he wants to access the same session, while the service has to validate the user using session-related data.

In order to manage SOAP session, a client has to send additional reference parameters in the SOAP header, which is named serviceGroupId (this will be sent to the client when he invokes a service that deploys in SOAP session for the first time). In the meantime, SOAP session provides a way to manage sessions across single service invocations, as well as for multiple services within a service group. As long as we are in the same SOAP session, we can manage service-related data in ServiceContext; if we want to share data across other services in the group, we can use ServiceGroupContext to store the session-related data.

When a client tries to access a service that we have deployed in SOAP session for the first time, Axis2 will generate serviceGroupId and send that to the client as a reference parameter in wsa:ReplyTo, as shown below. However, it should be mentioned that the server has to have WS-addressing support for SOAP session support to be available to both the client and the server.

 <wsa:ReplyTo>        <wsa:Address>https://www.w3.org/2005/08/addressing/anonymous</wsa:Address>             <wsa:ReferenceParameters> <axis2:ServiceGroupId xmlns:axis2="http://ws.apache.org/namespaces/axis2">urn:uuid:65E9C56F702A398A8B11513011677354</axis2:ServiceGroupId>             </wsa:ReferenceParameters>  </wsa:ReplyTo> 

If a client wants to live in the same session, then he has to copy that reference parameter and send it back to the server when he invokes the service in the second instance. As long as a client sends the valid serviceGroupId, he can use the same session and the service can maintain the session-related data. Unlike request session, SOAP session has a default timeout period; if the client does not touch the service for a period of 30 seconds, the session will expire. In this situation, a client that sends the old serviceGroupId will get an AxisFault. We can change the default timeout period by changing the server's axis2.xml as follows:

 <parameter name="ConfigContextTimeoutInterval">30000</parameter>

By changing the parameter value, we can obtain the desired timeout interval.

As mentioned earlier, deploying a service in SOAP session requires us to change services.xml as follows:

 <service name="MyService"  scope="soapsession"> </service>  

It should be noted here that, although we are required to copy the references parameter, once we use the Axis2 client we can configure it to copy the parameter automatically.

To get an idea about SOAP session management, let's write the following service class and deploy it. The service class adds the current passed value to the previous value and sends the result, so we should see the incremental values changing. First, write the service and deploy it in SOAP session, completing the necessary changes to services.xml

 public class MyService {     public int add(int value) {         MessageContext messageContext = MessageContext.getCurrentMessageContext();         ServiceContext sc = messageContext.getServiceContext();         Object previousValue = sc.getProperty("VALUE");         int previousIntValue = 0;         if (previousValue != null) {            previousIntValue = Integer.parseInt((String)previousValue);         }         int currentValue = previousIntValue + value;         sc.setProperty("VALUE","" + currentValue);         return currentValue;     } } 

Now let's use the following code to invoke the service. As you can see, we have engaged the addressing module, but we have not done anything to manage the sessions.

         ServiceClient sc = new ServiceClient();         sc.engageModule("addressing");         Options opts = new Options();         opts.setTo(new EndpointReference(                 "https://127.0.0.1:8080/axis2/services/MyService"));         opts.setAction("urn:add");         sc.setOptions(opts);         OMElement ele = sc.sendReceive(createPayLoad(10));         System.out.println(ele.getFirstElement().getText());         ele = sc.sendReceive(createPayLoad(10));         System.out.println(ele.getFirstElement().getText());  

createPayLoad method is shown below:

 public static OMElement createPayLoad(int intValue) {         OMFactory fac = OMAbstractFactory.getOMFactory();         OMNamespace omNs = fac.createOMNamespace(                 "http://ws.apache.org/axis2", "ns1");         OMElement method = fac.createOMElement("add", omNs);         OMElement value = fac.createOMElement("args", omNs);         value.setText("" + intValue);         method.addChild(value);         return method;  }  

Once we run the code, we will see the following output in the client side:

10
10

That means that although we have invoked the service twice, we have gotten the same output. Now let's change our client code a bit and see what results we get. Just add the following line of code and run the client again.

   opts.setManageSession(true);   sc.setOptions(opts); 

Now you should see the following output in the client side.

10
20

So that simply tells us that we have invoked the service in a session-aware manner.

It should be mentioned that you will need to engage the addressing module in both the client side and the server side in order to get SOAP session working.

Transport Session Scope

In the case of Transport session, Axis2 uses transport-related session management techniques to manage sessions. For example, in the case of HTTP, HTTP cookies are used to manage session. The lifetime of the session is controlled by the transport, not by Axis2; Axis2 simply stores service context and ServiceGroupContext in the transport session object so that service can access those contexts as long as session lives.

One of the key advantages of Transport session over other sessions is that we can talk to multiple service groups within one transport session. In SOAP session, we don’t have a way to communicate between two service groups, but with the transport session we have that capability. In this case, the number of service instances created depends on the number of transport sessions created.

Deploying a service in transport session requires us to change services.xml as follows:

 <service name="MyService"  scope="transportsession">  </service>  

Now, let's change our previous sample to have the scope as transport and redeploy the service. Let's also try to invoke the service in the following ways:

Option 1 : Using the browser.

https://localhost:8000/axis2/services/MyService/add?value=10

If we keep on typing that, then we will get the output as 10 , 20 , 30 etc.

Option 2 : Using the service client. To use the service client, we must first set the session management flag to true so that it will send back the transport cookie. So if we run the following code, we will see this outcome:

         ServiceClient sc = new ServiceClient();         Options opts = new Options();         opts.setTo(new EndpointReference(                 "https://127.0.0.1:8000/axis2/services/MyService"));         opts.setAction("urn:add");         opts.setManageSession(true);         sc.setOptions(opts);         OMElement ele = sc.sendReceive(createPayLoad(10));         System.out.println(ele.getFirstElement().getText());         ele = sc.sendReceive(createPayLoad(10));         System.out.println(ele.getFirstElement().getText()); 
10
20

This simply tells us that we have invoked the service deployed in the transport session in a session-aware manner. In this case we do not need to have addressing module.

Application scope

Application scope has the longest lifetime compared to others; the lifetime of the application session is equal to the lifetime of the system. If we deploy a service in application scope there will be only one instance of that service, and there will be only one service context for that service. In the Axis2 world, if we consider the memory footprint and if we do not want to manage session, then a good option is to deploy the service in application scope.

When we deploy a service in application scope, a client does not need to send any additional data to use the same session.

To deploy a service in application scope we need to change axis2.xml as shown below:

 <service name="foo"  scope="application">  </service>  

Managing Sessions Using ServiceClient

As we know by now, managing sessions in the client side involves bit of a work. In both SOAP session and Transport session, a client has to send the session-related data if he wants to live in the same session. He might be able to do this for SOAP session by copying the required reference parameters. However, with Transport session, a user cannot obtain access to transport to copy and send cookies.

To make the user experience easier, Axis2 has the built-in capability of managing sessions within the client session by just setting a flag (which we have used already). Then, depending on the service side session, it will send the corresponding data as long as we use the same service client.

If we want to live in the same session then we can create a service client as shown below, then reuse the created service client object to invoke the service.

 	  Options options = new Options(); 	  options.setManageSession(true); 	  ServiceClient sender = new ServiceClient(); 	  sender.setOptions(options); 

Once we create ServiceCient as shown above, if the service is deployed in SOAP session it will copy the serviceGroupId and send that from the second invocation onwards. If the server sends the session id, such as http cookies, it will copy that to ServiceContext (in the client side) and send it back to server when the client invokes the service for the second time.

Conclusion

Stateless nature is one of the main characteristics of Web services, but that is a limitation for advanced web services developers. Developing an enterprise level application using Web services is not easy unless we have a session management layer. Axis2 has four levels of sessions to address enterprise Web service development issues.

References

Author

[Deepal Jayasinghe, Tech lead, WSO2, deepal +AT+ wso2 +dot+ com]

 

About Author

  • Deepal Jayasingha
  • WSO2 Inc.