Web services are in high demand and a large number of
players have entered the web service arena. As a result
of this, users are looking for more and more features,
and they are trying to do everything by using Web services.
By design, Web services are said to be stateless. There
was no notion of managing sessions in the Web service
world, but now this has changed and users cannot develop
an advanced application without managing state. A good
example would be banking applications where you log
in into the system, withdraw money, and log, out.
If we try to map that into a Web service:
First, the user logs in into your account (invoking
a login method)
The user withdraws money (invoking some operation
on his account)
The user logs out (completing the transaction).
You easily can understand that the three operations
stated above are interrelated, and the same user does
all three invocations. So, it means that someone needs
to keep track of the user, and another has to keep
track of the user data throughout methods invocation.
This implies the need for session management.
When it comes to advanced applications, we have to
break the rules; otherwise, no one can implement real
Web applications. As a result, even though Web services
are stateless by nature, upi need to add a layer above
it to provide session management.
The Stateless Nature of Axis2
One of the good design principles of Axis2 is that
it keeps logic and states separately, so none of its
components are needed to maintain session and they
don't maintain sessions. In Axis2 handlers, transports
and even AxisEngine are said to be stateless; therefore,
there is no difference between having multiple instances
or one instance of them.
As a best practice, a handler or transport should
not keep any instance variable (if it is likely to
be changed), because that breaks the stateless nature
of Axis2. So, if the handler or transport wants to
act in a stateful manner, the correct way is to store
the state and Axis2 state hierarchy and use it whenever
necessary, rather than keeping instance variable.
Types of sessions in Axis2
As mentioned above, an enterprise web service cannot
sustain itself unless the session concept burns into
Web service engines. In other words, it is wrong to
say that each and every SOAP web service engine should
maintain sessions because you can have services that
do not require maintaining sessions. A good example
could be a Google search service and a Google spell
checker service.
Managing sessions directly causes an increase of
the memory footprint and to slow down performance,
but you need to have a compromise: whether or not
you support the session and provide state full service
development. Axis2 is meant to be an enterprise Web
service engine, so it has to support session management.
When sessions are considered, there can be different
types of sessions as well, and the lifetime of the
session may vary from one to another. Some sessions
last a few seconds whereas others last the system
lifetime. Axis2 architecture has been designed to
support four types of sessions. There are a few differences
from one to another; hopefully you can develop any
kind of Web service by using the following four types
of session scope.
Request
SOAPSession
Application
Transport
Axis2 context hierarchy
It is useful to understand the types of contexts in
Axis2 before discussing types of session in depth.
As mentioned above, Axis2 keeps logic and states separately,
so contextS are there to store the states. There are
five types of
contexts in Axis2:
ConfigurationContext: The runtime representation
of THE whole system, to start Axis2 system you need
to have A configuration context. The lifetime of configuration
context will be the lifetime of the system, so if
you store some state (a property) it will last forever
(until system shutdown).
ServiceGroupContext: In Axis2, you can deploy multiple
services together as a service group. At runtime,
there will be one or more service group contexts (depending
on the session scope of the group) to keep states
of the group throughout the session.
ServiceContext:
Will represent the runtime of one service; the context
lifetime will be the lifetime of the session. There
can be one or many service contexts in the system
depending on the session scope of the corresponding
service.
OperationContext:
This context represents the lifetime of a MEP (Message
Exchange Patterns). The lifetime of the operation
context is usually less than the lifetime of the service
context.
MessageContext:
The lifetime of an incoming message is represented
by the message context. If two handlers in a given
execution chain want to share data, the best way is
to store them in message context. One operation context
may have many message contexts.
Irrespective of the session scope, when the session
start up and when it finishes, Axis2 will notify the
service implementation class, but you have to add
two additional methods to your service implementation
class.
public void init(ServiceContext serviceContext) {
}
public void destroy(ServiceContext serviceContext)
{
}
In addition to that, whenever a service receives
a request, it will notify by passing the corresponding
OperationContext as an argument. So, if the service
wants to access an incoming message's context or an
incoming SOAPMessage, he can do that by just adding
the following method to the service implementation
class; this method will be called before the actual
method is called.
public void setOperationContext(OperationContext
operationContext) {
}
Request session scope
Request session scope is the default session in Axis2.
When you deploy a service without knowing anything
about session management, your service will be deployed
in the requested session scope. The lifetime of this
session is limited to the method invocation's lifetime,
or the request processing time. So, when you deploy
a service in request scope, you don't have a way to
manage session; it is the same as though you don't
have a session at all.
Once you deploy a service in request session scope
for each and every invocation service, the implementation
class will be created. Say you have deploy 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 you want to
specify the scope explicitly, you still can do that
by adding a scope attribute to the service element
in services.xml as follows:
<service name="foo" scope=" request">
</service>
Even if you deploy a service in a request scope,
there are many ways of managing sessions in Axis2.
One way is to store the state in Axis2' global runtime
(configuration context) and retrieve it whenever necessary.
SOAP Session Scope
SOAP session scope has a slightly longer lifetime
than a request session, and deploying a service in
a SOAP session is required to change services.xml.
Managing a SOAP session requires both the client and
service to aware of the sessions; in other words,
the client has to send the session-related data if
he wants to access the same session and the service
has to validate the user by using session-related
data.
To manage a SOAP session, a client has to send an
addition reference parameter in the SOAP header; it
is named the serviceGroupId parameter. The SOAP session
provides a way to manage the session not only for
a single service invocation but also for multiple
services in a service group. As long as you are in
the same SOAP session, you can manage service-related
data in a service context; if you want to share data
across other services in the group, you can use serviceGroupContext.
When you deploy a service in SOAP session and when
a client tries to access the service in the first
time, Axis2 will generate serviceGroupId and send
that to the client as a reference parameter in wsa:ReplyTo,
as shown below:
<wsa:ReplyTo>
<wsa:Address>
http://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 the client wants to live in the same session,
he has to copy that reference parameter and send it
back to the server when he invokes the service the
second time. 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 a request session,
a SOAP session has a default timeout period, so if
the client does not touch the service for 30 seconds,
the session will expire, and if the client sends the
old serviceGroupId, he will get an AxisFault too.
Managing a SOAP session requires you to engage addressing
modules on both the server side and client side. Deploying
a service in a SOAP session requires you to change
services.xml as follows:
<service name="foo" scope=" soapsession">
</service>
Transport session scopeIn the case of a Transport
session, Axis2 uses transport-related session management
techniques to manage session. As an example, in the
case of HTTP, it uses HTTP cookies to manage the session.
The lifetime of the session is controlled by the transport,
not by Axis2; Axis2 stores the service context and
serviceGroupContext in the transport session object
so thatthe service can access those contexts as long
as the session lives.One of the key advantages of
the Transport session over othersessions is that you
can talk to multiple service groups within one transport
session. In a SOAP session, you don't have a way to
communicate between two service groups, but with the
transport session you have that capability. In this
case, the number of service instances created depends
on the number of transport sessions created.Deploying
a service in a transport session requires you tochange
services.xml as follows:<service name="foo"
scope=" transportsession">
</service>
If you are using Axis2 nightly builds or planning
to use them thenext version,deploying a service in
a transport session requires additional changes to
axis2.xml.That is mainlyto improve the memory usage;
otherwise, whether you deploy the service in a transport
session or not Axis2 tries to create a session objectat
the transport level; with these changes, it will not
create unnecessary objects. To manage the transport-level
session, you need to set the manageTransportSession
parameter value to true in axis2.xml: <parameter
name="manageTransportSession"
locked="false">true</parameter>
Application scopeApplication scope has the longest
lifetime compared to others; the lifetime of the application
session is equal to the lifetimeof the system. If
you deploy a servicein application scope, there will
be only one instance of that service and obviously
there will be only one service context for that service.
In the Axis2 world, if you consider the memory footprintand
if you don't want to manage the session, the good
candidate is to deploy the service in application
scope.When you deploy a service in application scope,
a client does notneed to send any additional data
to use the same session.To deploy a service in application
scope, you need to change axis2.xml as shown below:<service
name="foo" scope=" application">
</service>
Managing the session using the service clientManaging
the session on the client side involves bit of a work.As
mentioned above, both in a SOAP session and Transport
session a client has to send the session-related data
if he wants to live in the same session. Maybe he
can do that for a SOAP session by coping with required
reference parameters, but with a Transport session
a user must get access to the transportto copy and
send cookies.To make life easier, Axis2 has the built-in
capability of managing sessions in the client session
by just setting a flag. Then, depending on the service
side session,it will send the corresponding data as
long as you use the same service client. So, the main
requirement is to use the same service client to invoke
the service if you wantto live in the same session.If
you want to live in the same session,you can create
service client as shown below and re-use the created
service client object to invoke the service.Options
options = new Options();
options.setManageSession(true);
ServiceClient sender = new ServiceClient();
sender.setOptions(options);
Once you create the service client as shown above,
if the service deploys in a SOAP session it will copy
the serviceGroupId and send that from the second invocation
onwards. If the server sends thesession id, such as
HTTP cookies, it will copy that to the service context
(on the client side) and send it backto the server
when the client invokes the service for a second time.SummaryThe
stateless nature is one of the main characteristics
of Web services, but it is a limitation for advanced
Web servicesdevelopers. Developing an enterprise-level
application using Web servicesis not easy unless you
have a session management layer. Axis2 has four levels
of sessions to address enterprises-level Web service
development issues.