Web Services Eventing with Apache Savan/C - Part 1

In this tutorial, Part 1 of a series by Damitha Kumarage, he describes Web services Eventing with Apache Savan/C. Damitha illustrates working with Apache Savan/C, an implementation of the WS- Eventing specification. This tutorial complies with the WS-Eventing Specification of August 2004.

Date: Tue, 29th Jan, 2008
Level: Intermediate
Reads: 3895 Comments: 0 | Login or register to post comments
Damitha Kumarage
Technical Lead and Product Manager
WSO2 Inc.
damitha's picture

Introduction

First, let's be clear on the terminology used in this tutorial.

Web Services Eventing is about using the Web services framework for implementing a Subscriber-Publisher model. A client will send a request message for a subscription to an Event Publishing Service (EPS), with information as to who it is and from where it can receive notifications from the server . The Publishing Service publishes its data, as and when available, to all client endpoints given by respective subscribers when making subscription requests. These endpoints can be an application running on the same machine as the client application (subscriber) or, it can be an application running on a different machine.
Data Source and Data Sink
In accordance with the Web Services Eventing Specification, a Publishing Service is referred to as a 'data source' and a client requesting subscription is reffered to as a 'subscriber'. A Notification Endpoint provided by a Subscriber is a 'data sink'. At any point after the initial subscription a subscriber can renew, get status or unsubscribe from a given subscription. That mediator that handles the status of a given subscription could be the data source itself or a delegated someone else. That someone else is called a Subscription Manager, a separate Web service from the one we referred to as the data source .

 

Applies To

WSF/C 1.1.0 - 1.2.0
Savan/C 0.90
Environment Linux - Debian Etch/Lenny, Ubuntu, Fedora

 

 

Table of Contents

 

To start off, you need to be familiar with the Apache Axis2/C Web service platform environment. The article The Apache Axis2/C - Web Services Engine is a good place to start.

Let's understand Savan/C using a simple scenario where we have a data source, a subscriber client and an event sink.

 

The Savan Module

Now that the big picture is clear, I will go into details of how this is implemented in the Apache Axis2 C Web services platform.

To extend the core functionality of the Axis2/C engine, you can write a module which contains a dynamically loadable library and an XML configuration file. Savan/C is such a module written to implement the functionality described in the previous paragraph.

First, let us look at the configuration file within the Savan Module:

<module name="savan" class="mod_savan">
<parameter name="SubscriptionMgrURL" locked="xsd:false">http://localhost:9090/axis2/services/subscription</parameter>
<!-- Database connection parameters -->
<parameter name="savan_db" locked="false">/axis2c/deploy/savan_db</parameter>
<inflow>
   <handler name="SavanInHandler" class="mod_savan">
    <order phase="SavanPhase"/>
  </handler>
</inflow>
<operation name="Subscribe">
    <parameter name="wsamapping" >http://schemas.xmlsoap.org/ws/2004/08/eventing/Subscribe</parameter>
</operation>
<operation name="Renew">
    <parameter name="wsamapping" >http://schemas.xmlsoap.org/ws/2004/08/eventing/Renew</parameter>
</operation>
<operation name="Unsubscribe">
    <parameter name="wsamapping" >http://schemas.xmlsoap.org/ws/2004/08/eventing/Unsubscribe</parameter>
</operation>
<operation name="GetStatus">
    <parameter name="wsamapping">http://schemas.xmlsoap.org/ws/2004/08/eventing/GetStatus</parameter>
</operation>
</module>

SubscriptionMgrURL - This is the URL of the subscription manager. If not provided, it is assumed that the subscription manager is deployed in the same Axis2/C engine as the data source.

Inflow - This element allows us to place the Savan module specific handler in the Inflow Savan phase named SavanPhase. SavanPhase, at this point, must be defined in the axis2.xml as:

<phaseOrder type="inflow">
    <!--System pre defined phases-->
    <phase name="Transport"/>
    <phase name="PreDispatch"/>
    <phase name="Dispatch"/>
    <phase name="PostDispatch"/>
  <!--End system pre defined phases-->
    <!--After PostDispatch phase, module or service author can add any phase as required-->
    <!--User defined phases could be added here-->
    <!--phase name="RMPhase"/-->
    <phase name="SavanPhase">
</phaseOrder>

 

The idea behind placing a Savan specific input handler in the inflow is to ensure only messages of the types given in the table below are processed. By making this phase a user phase, you are making sure that only the requests for Savan enabled services are passed through this phase. For more information on phases see Flows, Phases, Handlers, and Modules.


Savan Message Type Description
SAVAN_MSG_TYPE_SUB A subscription message
SAVAN_MSG_TYPE_UNSUB An unsubscribe message
SAVAN_MSG_TYPE_RENEW A renew message
SAVAN_MSG_TYPE_GET_STATUS A status query message
SAVAN_MSG_TYPE_UNKNOWN This is an unknown message type. So the input handler lets it go unhandled

savan_db - This parameter is where the savan database is created. If unspecified, the database is created in the current folder. Savan uses an embedded sqlite database to store subscriber information.

The operation parameters Subscribe, Unsubscribe, Renew and GetStatus are used to map the wsa action to the corresponding subscription manager service operations.

Once the message passes the Savan input handler, it is hit by the Savan specific message receiver. This is where the response to the incoming message is built and passed to the response path. A savan enabled service does not do anything particular with the request message of any of the above types. It is the Savan message receiver's responsibility to handle the Savan specific message.

 

Data Source

A data source is implemented as an Apache Axis2/C Web service. A service can be loaded for serving subscriber requests and publishing them at the time of loading the Axis2/C engine itself or to be loaded at the very first request for a subscription.

First, let's look at the data source. Here is the configuration file for the service:

1 <service name="publisher">
2 <module ref="savan"/>
3     <parameter name="ServiceClass" locked="xsd:false">publisher</parameter>
4     <parameter name="loadServiceAtStartup" locked="xsd:false">true</parameter>
6    <operation name="start">
7         <parameter name="wsamapping" >http://ws.apache.org/axis2/c/savan/samples/pubilsher/notify</parameter>
8    </operation>
9 </service>

The 2nd line tells Axis2/C that this service wishes to be engaged to the Savan module for correct functioning.
The 3rd line specifies the service (data source) name.
The 4th line tells Axis2/C to load this data source service at the start up of the engine.

With this example, what the data source does is to start a separate thread at the time of loading the service, that will push a few sample data to the subscribers of the data source.

int AXIS2_CALL
publisher_init_with_conf(
    axis2_svc_skeleton_t *svc_skeleton,
    const axutil_env_t *env,
    axis2_conf_t *conf)
{
    publisher_init(svc_skeleton, env);
    start_publisher_thread(env, conf);
    return AXIS2_SUCCESS;
}

 

Subscription Handling

Now, let's look at the subscribing client. First, set the address of the data source, to the Axis2/C client:

address = "http://localhost:9090/axis2/services/publisher";
    endpoint = axsi2_endpoint_create(env, address);
    axis2_options_set_to(options, env, endpoint);

Now, engage the Savan module to the service client:

axis2_svc_client_engage_module(svc_client, env, "savan");

Then create a Savan options map and add the URL of the notification endpoint (data sink):

savan_options = axutil_hash_make(env);
axutil_hash_set(savan_options, SAVAN_OP_KEY_NOTIFY_EPR, AXIS2_HASH_KEY_STRING,"http://localhost:9090/axis2/services/listener");

Now, create a Savan client instance and call the subscribe function passing savan_client and savan_options. When Savan is installed libsavan_client.so is installed into $AXIS2C_HOME/lib. Confirm that it is in the library path of your system.

savan_client = savan_client_create(env);
status  = savan_client_subscribe(savan_client, env, svc_client, savan_options);

This will send a Savan subscription request SOAP message to the server.

POST /axis2/services/publisher HTTP/1.1
    User-Agent: Axis2/C
    Content-Length: 702
    Content-Type: application/soap+xml;charset=UTF-8
    Host: 127.0.0.1:9090

   <soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
   <soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
      <wsa:To>http://localhost:9090/axis2/services/publisher</wsa:To>
      <wsa:Action>http://schemas.xmlsoap.org/ws/2004/08/eventing/Subscribe</wsa:Action>
      <wsa:MessageID>afefdaca-6761-1dc1-22e7-0012f091a9ac</wsa:MessageID>
   </soapenv:Header>
   <soapenv:Body>
      <wse:Subscribe xmlns:wse="http://schemas.xmlsoap.org/ws/2004/08/eventing">
         <wse:EndTo/>
         <wse:Delivery>
            <wse:NotifyTo>http://localhost:9090/axis2/services/listener</wse:NotifyTo>
         </wse:Delivery>
         <wse:Expires/>
         <wse:Filter Dialect="http://www.w3.org/TR/1999/REC-xpath-19991116"/>
      </wse:Subscribe>
   </soapenv:Body></soapenv:Envelope>

Here, the To addressing header contains the URLof the data source. In the SOAP body, we have the subscription request message. In the EndTo element, we usually put the endpoint address where the response to a subscription message should be sent to. Any fault messages from the eventing server, if it cannot honor the subscription request, will also be sent to this endpoint. In this particular message, it is empty- indicating that the HTTP back channel will be used to send back the subscriber response message. Under the Delivery element, the NotifyTo URL is included. This is the URL for the data sink provided by the subscriber client. There is another element called Expires under the Delivery element. The purpose of this element is to indicate to the server, the preferred duration for the subscription. According to the WS-Eventing specification, it is not guaranteed to be honoured by the server.

Following is the response message generated by the server for the above request:

HTTP/1.1 200 OK
Content-Type: application/soap+xml;charset=UTF-8
Content-Length: 1043

<s12:Envelope xmlns:s12="http://www.w3.org/2003/05/soap-envelope">
   <s12:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
      <wsa:Action>http://schemas.xmlsoap.org/ws/2004/08/eventing/SubscribeResponse</wsa:Action>
      <wsa:From>
         <wsa:Address>http://localhost:9090/axis2/services/publisher</wsa:Address>
      </wsa:From>
      <wsa:MessageID>1ba3a33e-697c-1dc1-3c38-001125b4c0fc</wsa:MessageID>
      <wsa:RelatesTo wsa:RelationshipType="http://www.w3.org/2005/08/addressing/reply">1b5921ba-697c-1dc1-31c5-001125b4c0fc</wsa:RelatesTo>
   </s12:Header>
   <s12:Body>
      <wse:SubscribeResponse xmlns:wse="http://schemas.xmlsoap.org/ws/2004/08/eventing">
         <wse:SubscriptionManager>
            <wsa:Address xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">http://localhost:9090/axis2/services/publisher</wsa:Address>
            <wsa:ReferenceParameter xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
               <wse:Identifier>1b99f3fc-697c-1dc1-3c37-001125b4c0fc</wse:Identifier>
            </wsa:ReferenceParameter>
         </wse:SubscriptionManager>
         <wse:Expires/>
      </wse:SubscribeResponse>
   </s12:Body></s12:Envelope>

Under the wse:SubscriptionManager element, we have the wsa:Address element which tells the subscriber the URL of the server which further handles the status of his subscription. Under the wsa:ReferenceParameter element, we have the wse:Identifier, the subscription ID assigned to this subscriber by the server. This is the ID that should be used for any further communication with the subscription handling server.

Once the subscription is handled successfully, the data source can publish its data to the subscriber's endpoint (data sink).

In our client, we can request to renew the duration of the subscription by sending a Renew Subscription message as given below:

/* Renewing the Subscription */
    address = savan_client_get_sub_url(savan_client);
    endpoint_ref = axis2_options_get_to(options, env);
    axis2_endpoint_ref_set_address(endpoint_ref, env, address);

    status = savan_client_renew(savan_client, env, svc_client, savan_options);

Else, we can request for a message including the status of the subscription.

subs_status = savan_client_get_status(savan_client, env, svc_client);

When we are no longer interested in receiving Datasource events at our data sink, we can send an unsubscribe request message.

status = savan_client_unsubscribe(savan_client, env, svc_client);

Once received, the subscription handling service will send an unsubscribe response message and the data source which will then not send any data source events to the data sink.

The complete source code for the above sample is available with the subscriber client sample available in the Savan source code.

 

A Separate Subscription Handler than the Data Source Itself

According to the WS-Eventing specification, the data source itself can handle the subscription requests or it can delegate the subscription handling to a separate subscription service.

Let's see how this can be achieved using Savan/C.

Data Source, Data Sink and Subscription Manager

image2

Suppose that our subscription handling service resides in an Axis2/C engine running in 192.168.1.3:9092 and the data source service resides in the localhost running at port 9090.

We need to add the following entry in the Savan module.xml running in the localhost:

<parameter name="SubscriptionMgrURL" locked="xsd:false">http://192.168.1.3:9092/axis2/services/subscription</parameter>

This tells the data source running in the localhost's Savan server, to delegate subscription handling to the URL mentioned in the code module above.

 

Filtering

When a subscriber subscribes for a data source the way we have illustrated above, the data source will send all his available data without any discrimination to the subscriber's endpoint. There can be a situation where this should not be the case. The subscriber may be interested only in certain data items available at the data source. In that case, the subscriber can send a filtering string with his subscription request message, as the following:

axutil_hash_set(savan_options, SAVAN_OP_KEY_FILTER, AXIS2_HASH_KEY_STRING,
        "//test3[@data='5']");
    axutil_hash_set(savan_options, SAVAN_OP_KEY_FILTER_DIALECT, AXIS2_HASH_KEY_STRING,
        DEFAULT_FILTER_DIALECT);

To honor this request, the server side must be built and run with filtering enabled. Currently, Savan/C supports only XPath filtering. If the server does not support the requested filtering dialect, it will send a fault response indicating that the requested filtering dialect is not supported. On the other hand, if it does support the requested filtering dialect, it will publish data satisfying the requested filtering criteria.

 

Summary

In this tutorial, our aim was to learn how to use Apache Savan/C for Web services eventing solutions. In part 2 of this tutorial, we will discuss a real application that uses Savan/C.

 

Resources

  1. Apache Axis2/C - is an Open Source framework for providing and cosuming Web services
  2. WSO2 WSF/C - WSO2 WSF/C is an Open Source framework for providing and consuming Web services
  3. Savan/C- Savan/C is an implementation of Web Services Eventing Specification
  4. WS Eventing Specification
  5. WS-Eventing Specification - August 2004

 

Author

Damitha Kumarage, Senior Software Engineer at wso2, committer Apache Software Foundation, damitha at wso2 dot com

library project main code
Learn Cloud
Learn
Cloud

The WSO2 Application Server is a reliable application server that can host your enterprise web applications. The WSO2 Application Server as a Service is offered in StratosLive, the WSO2 Platform as a Service. This article explains how a simple web application can be developed and deployed from Carbon Studio to the WSO2 Application Server...

Latest Webinar
Different groups within an organization need to monitor different Key Performance Indicators (KPIs) - An operations team will be interested in the response times of business services and loads of each service,..
Thursday, February 9th 2012, 09.00 AM (PST)

Thursday, February 9th 2012, 10.00 AM (GMT)