WSAS hidden SERVICES

WSO2 WSAS is an enterprise ready Web services engine powered by Apache Axis2. It is a lightweight, high performing platform for Service Oriented Architectures, enabling business logic and applications. Bringing together a number of Apache Web services projects, WSO2 WSAS provides a secure, transactional and reliable runtime for deploying and managing Web services.

WSAS comes with a set of admin services which are hidden from the user - since they are used internally for WSAS administration.

This post takes you through WSAS admin services - if you are to interact with WSAS at an API level its better you understand those.

Following extracts show each service with it's correspondig functionality - later we'll see how we could invoke GlobalAdmin service.
<!-- https://localhost:9443/services/ServerAdmin?wsdl -->
<wsdl:operation name="getServerStatus"> 
<wsdl:operation name="getServerVersion"> 
<wsdl:operation name="endMaintenance"> 
<wsdl:operation name="shutdownGracefully"> 
<wsdl:operation name="getServerData"> 
<wsdl:operation name="restart"> 
<wsdl:operation name="getServerDataAsString"> 
<wsdl:operation name="isAlive"> 
<wsdl:operation name="getStatus"> 
<wsdl:operation name="shutdown"> 
<wsdl:operation name="restartGracefully"> 
<wsdl:operation name="startMaintenance"> 
<!-- https://localhost:9443/services/LogViewAdmin?wsdl -->
<wsdl:operation name="clearLogs"> 
<wsdl:operation name="getLogs"> 
<wsdl:operation name="searchLog"> 
<wsdl:operation name="getLogsForSingleLogLevel"> 
<!-- https://localhost:9443/services/LoggingAdmin?wsdl -->
<wsdl:operation name="getAllLoggerData"> 
<wsdl:operation name="updateAllAppenderData"> 
<wsdl:operation name="updateSystemLog"> 
<wsdl:operation name="getAppenderData"> 
<wsdl:operation name="updateLoggerData"> 
<wsdl:operation name="restoreDefaults"> 
<wsdl:operation name="getLoggerData"> 
<wsdl:operation name="getSystemLog"> 
<wsdl:operation name="getStatus"> 
<!-- https://localhost:9443/services/UserAdmin?wsdl -->
<wsdl:operation name="removeUser"> 
<wsdl:operation name="editUserPassword"> 
<wsdl:operation name="assignRoleToUser"> 
<wsdl:operation name="getRoleNamesAndDescriptions"> 
<wsdl:operation name="getRoleNames"> 
<wsdl:operation name="editUserRole"> 
<wsdl:operation name="getUsers"> 
<wsdl:operation name="deleteUser"> 
<wsdl:operation name="addAdmin"> 
<wsdl:operation name="editAdmin"> 
<wsdl:operation name="deleteRoleFromUser"> 
<wsdl:operation name="getUserRoles"> 
<wsdl:operation name="deleteRoleCompletely"> 
<wsdl:operation name="addUser"> 
<wsdl:operation name="addRole"> 
<wsdl:operation name="getUserNames"> 
<wsdl:operation name="changeUserPassword"> 
<!-- https://localhost:9443/services/GlobalAdmin?wsdl -->
<wsdl:operation name="logout"> 
<wsdl:operation name="deployService"> 
<wsdl:operation name="isServerRegistered"> 
<wsdl:operation name="serverRegistered"> 
<wsdl:operation name="setPolicy"> 
<wsdl:operation name="deployModule"> 
<wsdl:operation name="ping"> 
<wsdl:operation name="login"> 
<wsdl:operation name="restoreDefaults"> 
<wsdl:operation name="listGlobalPhases"> 
<wsdl:operation name="listGlobalPhaseHandlers"> 
<wsdl:operation name="getDeclaredSystemParameters"> 
<wsdl:operation name="getPolicy"> 
<wsdl:operation name="setSystemParameter">
<!-- https://localhost:9443/services/ServiceGroupAdmin?wsdl -->
<wsdl:operation name="setServiceGroupParameter"> 
<wsdl:operation name="dumpAAR"> 
<wsdl:operation name="setPolicy"> 
<wsdl:operation name="listServiceGroup"> 
<wsdl:operation name="deleteServiceGroup"> 
<wsdl:operation name="setServiceGroupParameters"> 
<wsdl:operation name="getDeclaredServiceGroupParameters"> 
<wsdl:operation name="removeServiceGroupParameter"> 
<wsdl:operation name="getServiceGroupParameters"> 
<wsdl:operation name="configureMTOM"> 
<wsdl:operation name="removeServiceGroup"> 
<wsdl:operation name="getPolicy">
<wsdl:operation name="listServiceGroups"> 
<!-- https://localhost:9443/services/ServiceAdmin?wsdl -->
<wsdl:operation name="getNumberOfInactiveServices"> 
<wsdl:operation name="creatService"> 
<wsdl:operation name="getServiceInfo"> 
<wsdl:operation name="getDeclaredServiceParameters"> 
<wsdl:operation name="createAndDeploySpringBean"> 
<wsdl:operation name="removeSoap12BindingPolicy"> 
<wsdl:operation name="getServiceStatus"> 
<wsdl:operation name="removeServiceSpecificParameter"> 
<wsdl:operation name="createAndDeployEJBService"> 
<wsdl:operation name="setServiceParameter2"> 
<wsdl:operation name="getNumberOfActiveServices"> 
<wsdl:operation name="setSoap12BindingPolicy">
<wsdl:operation name="setHttpBindingPolicy"> 
<wsdl:operation name="setPolicy"> 
<wsdl:operation name="addTransportBinding"> 
<wsdl:operation name="listMethodsForClass"> 
<wsdl:operation name="setSoap11BindingPolicy"> 
<wsdl:operation name="exposeServiceOnlyViaTransports"> 
<wsdl:operation name="setServiceParameter3"> 
<wsdl:operation name="setServiceParameter"> 
<wsdl:operation name="getSchema"> 
<wsdl:operation name="getPolicies"> 
<wsdl:operation name="setServiceParameters"> 
<wsdl:operation name="getServiceUsers"> 
<wsdl:operation name="getServiceParameters"> 
<wsdl:operation name="getNumberOfFaultyServices"> 
<wsdl:operation name="getClassNames">
<wsdl:operation name="deleteFaultyServiceArchive"> 
<wsdl:operation name="getServiceUsersWithDescription"> 
<wsdl:operation name="getFaultyServiceArchives"> 
<wsdl:operation name="configureMTOM"> 
<wsdl:operation name="removeHttpBindingPolicy"> 
<wsdl:operation name="getSpringBeanNames"> 
<wsdl:operation name="getExposedTransports"> 
<wsdl:operation name="removeTransportBinding"> 
<wsdl:operation name="removePolicy"> 
<wsdl:operation name="getServiceRolesWithDescription"> 
<wsdl:operation name="stopService"> 
<wsdl:operation name="startService">
<wsdl:operation name="listServices"> 
<wsdl:operation name="removeSoap11BindingPolicy"> 
<wsdl:operation name="getServiceData"> 
<wsdl:operation name="removeServiceParameter"> 
<wsdl:operation name="getWSDL"> 
<wsdl:operation name="getPolicy">
<wsdl:operation name="createAndDeployService">
You can find rest of the services from following available end points.
https://localhost:9443/services/GeneralServices?wsdl
https://localhost:9443/services/STSAdmin?wsdl
https://localhost:9443/services/Sandesha2Admin?wsdl
https://localhost:9443/services/EJBProviderAdmin?wsdl
https://localhost:9443/services/DataServiceAdmin?wsdl
https://localhost:9443/services/SecurityScenarioConfigAdmin?wsdl
https://localhost:9443/services/AxisConfigAdmin?wsdl
https://localhost:9443/services/CryptoAdmin?wsdl
https://localhost:9443/services/TransportAdmin?wsdl
https://localhost:9443/services/LoggingService?wsdl
https://localhost:9443/services/ModuleAdmin?wsdl
https://localhost:9443/services/OperationAdmin?wsdl
Now lets try to login to WSAS through GlobalAdmin service.
final static String GLOBAL_SERVICE = "https://localhost:9443/services/GlobalAdmin";

GlobalAdminStub globalAdmin = null;
String path = null;
Options options = null;

try {
path = System.getProperty("user.dir");

// You can copy wso2wsas.jks from [WSAS_HOME]\conf
System.setProperty("javax.net.ssl.trustStore", path + "/src/wso2wsas.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "wso2wsas");

globalAdmin = new GlobalAdminStub(GLOBAL_SERVICE);
options = globalAdmin._getServiceClient().getOptions();
options.setManageSession(true);

// Login first
if (globalAdmin.login("admin", "admin")) {
globalAdmin.isServerRegistered();
}

} catch (Exception e) {
e.printStackTrace();
}

WSO2 WSF/PHP Screencast: How to Consume a Service Using WSF/PHP

This screencast by Dimuthu Gamage, demonstrates how to consume a weather service in the National Digital Forecasting database, using WSO2 WSF/PHP.

The screencast contains,

-Where to find the Service documentation + WSDL and what are the information available in there.
-How to generate the PHP client from the WSDL using wsdlphp tool.
-What is in the php file generated from the wsdl2php tool and how you select the required operations to invoke.
-How to fill the input parameter for the web service operation
-How to handle the response returned from the service.
-Finally It shows some different ways the data that you are extracting from the service, can be presented to your user.

Secure Conversation with STS

This post explains steps required in setting up a Secure Conversation between a client and a service with the aid of an STS[Secure Token Service].

Lets start with setting up the STS and configuring its security policy.

First, download WSAS from here.

WSO2 WSAS is an enterprise ready Web services engine powered by Apache Axis2 and it comes with a built in STS and a set of sample services[e.g. echo service] which we can use during this demonstration.

Download wso2wsas.jks from here and copy it to [WSAS_HOME]\conf - or basically replace the existing one. This is a work-around for this issue.

Start WSAS and login with admin/admin.

Select 'Services' and then 'wso2wsas-sts'[under 'Services' column].

Click on 'Manage Security Configuration' and select 'option - 3', that is 'Sign and encrypt - X509 Authentication'.

Keep 'wso2wsas.jks' as the private keystore.

Go back to Services\wso2wsas-sts and click on 'STS Configuration'.

Set,

Endpoint Address = http://localhost:9762/services/echo
Certificate Alias = wso2wsas


And apply.

Lets configure security policy for the echo service.

Select 'Services' and then 'echo'[under 'Services' column].

Click on 'Manage Security Configuration' and select 'option - 11', that is 'SecureConversation - Sign and Encrypt - Service as STS - Bootstrap policy - Sign and Encrypt , X509 Authentication'.

Keep 'wso2wsas.jks' as the private keystore.

All set, lets start with the client.

You can download the Eclipse project for the client from here and import it to a new Eclipse workspace.

Share the folder [CLIENT]\lib and map it to the network drive "W".

Refresh your workspace and it should build with no compile errors.

Build and run the client, you should see the out put on the console.

Lets get in to more details.

First, client will request a Security Context Token [SCT] from the STS.

Following code does it for you.
final static String STS_EPR = "http://localhost:9762/services/wso2wsas-sts";
final static String SERVICE_EPR = "http://localhost:9762/services/echo";

ServiceClient client = null;
ConfigurationContext ctx = null;
Policy stsPolicy = null;
STSClient stsClient = null;
Policy servicePolicy = null;
Token responseToken = null;
TokenStorage store = null;

ctx = ConfigurationContextFactory.createConfigurationContextFromFileSystem("repo","repo/conf/client.axis2.xml");

stsClient = new STSClient(ctx);
stsClient.setRstTemplate(getRSTTemplate());
stsClient.setAction(RahasConstants.WST_NS_05_02 + RahasConstants.RST_ACTION_SCT);

stsPolicy = loadPolicy("sts.policy.xml");
servicePolicy = loadPolicy("service.policy.xml"); 

responseToken = stsClient.requestSecurityToken(ervicePolicy,STS_EPR,stsPolicy,SERVICE_EPR);

// Store token
store = TrustUtil.getTokenStore(ctx);
store.add(responseToken);
You'll notice the following in the out-going SOAP request.
<wsa:To>http://localhost:9762/services/wso2wsas-sts
<wsa:ReplyTo>
<wsa:Address>
http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous
</wsa:Address>
</wsa:ReplyTo>
<wsa:MessageID>urn:uuid:E463557299CDEAE3B71225299469127</wsa:MessageID>
<wsa:Action>http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT</wsa:Action>
And following is a part of the SOAP message reponse from the STS.
<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
<wsa:MessageID>urn:uuid:292D5247502C9F172F1225299475624</wsa:MessageID>
<wsa:Action>http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue</wsa:Action>
<wsa:RelatesTo>urn:uuid:E463557299CDEAE3B71225299469127</wsa:RelatesTo>
Basically, SCT binding of WS-Trust defines how to use WS-Trust to request and return SCTs.

As you already noticed in the above two extracts when requesting and issuing security context tokens, following Action URIs are used.
<wsa:Action>http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT</wsa:Action>

<wsa:Action>http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue</wsa:Action>
Once received the SCT from STS, client is ready to talk to the service.
ServiceClient client = null;
Options options = null;

client = new ServiceClient(ctx, null);
client.engageModule("rampart");
client.engageModule("addressing");

options = new Options();
options.setAction("urn:echoOMElement");
options.setSoapVersionURI(SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI);
options.setProperty(RampartMessageData.KEY_RAMPART_POLICY, servicePolicy);
options.setProperty(RampartMessageData.SCT_ID, responseToken.getId());
options.setTo(new EndpointReference(SERVICE_EPR));

client.setOptions(options);
client.sendReceive(getPayload("Hello"));
The above code will generate two SOAP request/reponse message pairs in between client and the service.

Lets look at a part of the first SOAP request from the client to the service.
<wsa:To>http://localhost:9762/services/echo</wsa:To>
<wsa:ReplyTo>
<wsa:Address>
http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous
</wsa:Address>
</wsa:ReplyTo>
<wsa:MessageID>urn:uuid:E463557299CDEAE3B71225299475512</wsa:MessageID>
<wsa:Action>http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT</wsa:Action>
And following is an extract from the first response from the service.
<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
<wsa:MessageID>urn:uuid:292D5247502C9F172F1225299476906</wsa:MessageID>
<wsa:Action>http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/SCT</wsa:Action>
<wsa:RelatesTo>urn:uuid:E463557299CDEAE3B71225299475512</wsa:RelatesTo>
Once done with this initial step, client will invoke the services's business logic.
<wsa:To>http://localhost:9762/services/echo</wsa:To>
<wsa:MessageID>urn:uuid:E463557299CDEAE3B71225299475492</wsa:MessageID>
<wsa:Action>urn:echoOMElement</wsa:Action>

Nandana to present at IITC today

Nandana, will present today [29th Oct] at the 9th International Information Technology Conference (IITC 2008), on 'WSO2 WSAS -Web services Security in Practice'.

Live streaming of the event is available from here.

Abstract from Nandana's paper.

"“Complexity is the worst enemy of security”. Unfortunately, complexity in Web services security implementations has reached a point where, the learning curve for a Web services developer has become very steep. To use Web services security accurately and efficiently for achieving desired results, one must possess a deep understanding of dozens of WS – Security specifications, in addition to general security knowledge that's needed. WSO2 Web Service Application Server (WSAS),an enterprise ready Web services application server powered by Apache Axis2 together with other Web services projects, tries to address this issue by providing easy to use security configuration settings together with a set of security utilities, allowing Web services authors to configure security in an extremely user friendly and efficient manner. WSO2 WSAS security configuration options mainly focus on making it possible to implement the most commonly used security scenarios with least bit of effort."

OpenSSL on WINDOWS

This post explains all the steps you need to create your own CA.

Let me summarize what we intend to do here.

First we will create a public cert and a private key for CA.

Then we'll create a public/private key pair for the server [say WSAS].

Next step is to generate CSR [Certificate Signing Request] for the server and submit it to the CA.

CA signs the certificate.

Then we need to convert both CAs public cert as well as the server's signed cert from PEM to DER.

After the conversion, the server will import the CA's public cert and server's signed certificate to it's key store.

That's it and we are done.

Let's get started.

First you need to download Visual C++ 2008 Redistributables from here and install it locally.

Then download and install OpensSSL from here.

Also make sure you have added [JAVA_HOME]\bin to the PATH env variable.

Let's create the folder structure for our example.

Make sure you have the following folder structure.

[SAMPLE]\ca
[SAMPLE]\ca\certs
[SAMPLE]\ca\crl
[SAMPLE]\ca\newcerts
[SAMPLE]\ca\private
[SAMPLE]\ca\index.txt
[SAMPLE]\wsas

Copy [OPENSSL_HOME]\bin\openssl.cfg to [SAMPLE]\.

Copy [OPENSSL_HOME]\bin\PEM\demoCA\serial to [SAMPLE]\ca.

Lets edit [SAMPLE]\ca\openssl.cfg - add the following section to the end of the file - make sure you do not violate the existing file structure.

####################################################################
[ WSO2WSAS_CA ]

dir = ./ca
certs = $dir/certs
crl_dir = $dir/crl
database = $dir/index.txt
new_certs_dir = $dir/newcerts

certificate = $dir/cacert.pem
serial = $dir/serial
crlnumber = $dir/crlnumber

crl = $dir/crl.pem
private_key = $dir/private/cakey.pem
RANDFILE = $dir/private/.rand

x509_extensions = usr_cert


default_days = 365
default_crl_days = 30
default_md = sha1
preserve = no

policy = policy_anything

[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
Find the following section in [SAMPLE]\ca\openssl.cfg - and edit as below.

####################################################################
[ ca ]
#default_ca = CA_default
default_ca = WSO2WSAS_CA

####################################################################
Lets create public/private key pair for CA first. Once you are asked to input, do it approriately.

[SAMPLE]\>openssl req -x509 -newkey rsa:1024 -keyout ca\private\cakey.pem -out ca\cacert.pem -config openssl.cfg
Now we can create the public/private key pair for server and generate the CSR.

[SAMPLE]\>keytool -genkey -alias wso2wsas -keyalg RSA -keystore wsas\wso2wsas.jks

[SAMPLE]\>keytool -certreq -keystore wsas\wso2wsas.jks -alias wso2wsas -file wsas\wso2wsas.cert.req
Next, CA can sign the server cert.

[SAMPLE]\>openssl ca -config openssl.cfg -out wsas\wso2wsas.pem -infiles wsas\wso2wsas.cert.req
Now we need to convert both CAs public cert as well as the server's signed cert from PEM to DER.

[SAMPLE]\>openssl x509 -outform DER -in wsas\wso2wsas.pem -out wsas\wso2wsas.cert

[SAMPLE]\>openssl x509 -outform DER -in ca\cacert.pem -out wsas\wso2wsasca.cert
After the conversion, the server can import the CA's public cert and server's signed certificate to it's key store.

[SAMPLE]\>keytool -import -file wsas\wso2wsasca.cert -alias wso2wsasca -keystore wsas\wso2wsas.jks

[SAMPLE]\>keytool -import -file wsas\wso2wsas.cert -alias wso2wsas -keystore wsas\wso2wsas.jks
That's it and we are done.

SAVAN: Behind the scene

It's highly recommended that you read my previous post before going any further with this one.

Let me summarize a bit, what we did there.

We deployed a sample application with Axis2/Savan to demonstrate WS-Eventing.

The sample application had three components.

1. Event source[axis2-savan-event-source] - a stock quote service publishes stock prices iteratively

2. Event sink[axis2-savan-event-sink] - a stock quote consumer subscribes to the stock quote service to receive events

3. [axis2-savan-client] - initiates subscription for the stock quote consumer

Let's get started.

If you go through the services.xml of StockQuoteService, you'll find that we expose no operations there.
<!-- src/META-INF/services.xml -->
<service name="StockQuoteService" scope="application">

<module ref="savan" />
<module ref="addressing" />

<parameter name="ServiceClass" locked="false">
org.apache.ws.axis2.StockQuoteService
</parameter>

</service>
See whether following surprises you. Hit http://localhost:8080/axis2/services/ on your browser and observe the operations available under StockQuoteService.

If it's not the services.xml which added those operations, who else could it be?

It's basically the 'Savan' module does that [Remember!!! services.xml engages savan module to the StockQuoteService].

In otherwords engaging savan module will seemlessly add three more operations to your service.

Let's get into more deeper.

Extract the savan-SNAPSHOT.mar file inside [AXIS2_HOME]\repository\modules [Remember!!! you were asked to read my previous post :).]

You'll find module.xml inside META-INF directory. Lets dig into the module.xml.
<module name="savan" class="org.apache.savan.module.SavanModule">

<operation name="SavanInOutOperation" mep="http://www.w3.org/2004/08/wsdl/in-out">
<messageReceiver class="org.apache.savan.messagereceiver.SavanInOutMessageReceiver"/>
<actionMapping>http://schemas.xmlsoap.org/ws/2004/08/eventing/Subscribe</actionMapping>
<actionMapping>http://schemas.xmlsoap.org/ws/2004/08/eventing/Renew</actionMapping>
<actionMapping>http://schemas.xmlsoap.org/ws/2004/08/eventing/GetStatus</actionMapping>
<actionMapping>http://schemas.xmlsoap.org/ws/2004/08/eventing/Unsubscribe</actionMapping>
</operation>

<operation name="atom" mep="http://www.w3.org/2004/08/wsdl/in-out">
<messageReceiver class="org.apache.savan.atom.AtomMessageReceiver"/>
</operation>

<operation name="publish" mep="http://www.w3.org/2004/08/wsdl/in-out">
<messageReceiver class="org.apache.savan.messagereceiver.PublishingMessageReceiver"/>
<actionMapping>http://ws.apache.org/ws/2007/05/eventing-extended/Publish</actionMapping>
</operation>

</module>
Hold on a second. Lets cover bit of ground on Axis2.

One of the fundamental goals of SOAP processing frameworks is to deliver an incoming message to the targeted application.

The process of finding correct target application is known as 'dispatching'.

Let's have a look at the following section extracted from [AXIS2_HOME]\conf\axis2.xml.
<phase name="Dispatch" class="org.apache.axis2.engine.DispatchPhase">
<handler name="RequestURIBasedDispatcher"
class="org.apache.axis2.dispatchers.RequestURIBasedDispatcher"/>
<handler name="SOAPActionBasedDispatcher"
class="org.apache.axis2.dispatchers.SOAPActionBasedDispatcher"/>
<handler name="RequestURIOperationDispatcher"
class="org.apache.axis2.dispatchers.RequestURIOperationDispatcher"/>
<handler name="SOAPMessageBodyBasedDispatcher"
class="org.apache.axis2.dispatchers.SOAPMessageBodyBasedDispatcher"/>
<handler name="HTTPLocationBasedDispatcher"
class="org.apache.axis2.dispatchers.HTTPLocationBasedDispatcher"/>
<handler name="GenericProviderDispatcher"
class="org.apache.axis2.jaxws.dispatchers.GenericProviderDispatcher"/>
<handler name="MustUnderstandValidationDispatcher"
class="org.apache.axis2.jaxws.dispatchers.MustUnderstandValidationDispatcher"/>
</phase>
You can see a set of handlers being configured to execute under the 'Dispatch' phase.

All the dispatchers first try to find the service with the information it has. They do this if the dispatchers invoked before it had not found a service.

If the service is already found, the findService method of the dispatcher will just pass through. Then it tries to find an operation within the service, if a service is found by then.

Again, the dispatcher will do this only if other dispatchers invoked prior to it had not found an operation. Likewise, all the dispatchers put a collaborative effort in doing this. This will enable one dispatcher to find a service and another dipatcher to later find the operation.

If you'd like to read more on how Axis2 finds the service with the corresponding operation, read this.

Lets configure the TCP monitor to track subscription message. This explains how you can configure TCP monitor.

Once configured and run the Client, you'll see the following SOAP request, for the subscription.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsa:To>http://localhost:8080/axis2/services/StockQuoteService</wsa:To>
<wsa:MessageID>urn:uuid:F873BC9C2A4F33B6961225131910519</wsa:MessageID>
<wsa:Action>http://schemas.xmlsoap.org/ws/2004/08/eventing/Subscribe</wsa:Action>
</soapenv:Header>
<soapenv:Body>
<wse:Subscribe xmlns:wse="http://schemas.xmlsoap.org/ws/2004/08/eventing">
<wse:Delivery>
<wse:NotifyTo>
<wsa:Address xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
http://localhost:8080/axis2/services/StockQuoteConsumer
</wsa:Address>
</wse:NotifyTo>
</wse:Delivery>
</wse:Subscribe>
</soapenv:Body>
</soapenv:Envelope>
Once you look at the SOAP message and the extract from the axis2.xml which displays the set of available handlers for dispatching, you will not find a matching handler.

In this case, dispatching has to happen through WS-Addressing information.

So, once we engaged the 'addressing' module to the service, AddressingBasedDispatcher will be available for it during the "Addressing" phase.

With this, Axis2 will get to know, the message is destined to http://localhost:8080/axis2/services/StockQuoteService.

As I mentioned previously in this post, engaging savan module it self with the StockQuoteService has added three more operations to the service. Those three operations are defined in the savan module.xml - shown above.

You'll see that http://schemas.xmlsoap.org/ws/2004/08/eventing/Subscribe is mapped to the operation "SavanInOutOperation" [in module.xml] - in that case org.apache.savan.messagereceiver.SavanInOutMessageReceiver will be invoked.

By going through the above, you will figure out that all Subscribe/Renew/GetStatus and Unsubscribe operations are handled by the org.apache.savan.messagereceiver.SavanInOutMessageReceiver. In other words, that is exactly what savan module does.

Once a request to Subscribe being received at the 'savan' module, it will create a SubscriberStore for the 'publishing' [event source] service and will add the required information regarding the 'receving'[event sink] service to it.

If you look at the following code from [axis2-savan-event-source]\org.apache.ws.axis2\StockQuoteService, you will notice that Line:1 will get the SubcriberStore for the corresponding service, in this case, for the StockQuoteService, and if it's not null, then will publish events.
store = CommonUtil.getSubscriberStore(serviceContext.getAxisService());

if (store != null)  {
data = getNextPublicationData();
publicationClient = new PublicationClient(serviceContext.getConfigurationContext());
publicationClient.sendPublication(data, serviceContext.getAxisService(),null);
}

The man who went beyond UNICODE - no more

The nation in tears.

Music all around.

The most animated musician I have ever seen, dead and silent.

This is my humble tribute to the greatest musician, Sri Lanka ever produced, Dr.Premasiri Khemadasa - may you attain Nibbana.

WS-Eventing with SAVAN

WS-Eventing defines a protocol for one Web service (called a "subscriber") to register interest (called a "subscription") with another Web service (called an "event source") in receiving messages about events (called "notifications" or "event messages").

The subscriber may manage the subscription by interacting with a Web service (called the "subscription manager") designated by the event source.

Savan is the WS-Eventing implementation for Apache Axis2.

This post guides you through WS-Eventing with an example in Savan/Axis2.

-First download Axis2 1.4.1 and extract it to a local folder [AXIS2_HOME].

-Start Axis2 simple server with [AXIS2_HOME]\bin\axis2server.bat and make sure http://localhost:8080/axis2/services/ lists all avaialble services.

The sample application includes three components.

1. Event source[axis2-savan-event-source] - a stock quote service publishes stock prices iteratively

2. Event sink[axis2-savan-event-sink] - a stock quote consumer subsribes to the stock quote service to receive events

3. [axis2-savan-client] - initiates subscription for the stock quote consumer

You can download Eclipse projects for above three components from here and import those into your Eclipse workspace, say [SAVAN].

Copy all the jar files from [AXIS2_HOME]\lib to [SAVAN]\lib.

Copy [SAVAN]\lib\savan-SNAPSHOT.mar to [AXIS2_HOME]\repository\modules.

Copy [SAVAN]\lib\savan-core-SNAPSHOT.jar to [AXIS2_HOME]\lib.

Share the folder [SAVAN]\lib and map it to the network drive "W".

All set now, refresh your workspace and it should build with no compile errors.

Lets start with, Event source[axis2-savan-event-source].
// org.apache.ws.axis2/StockQuoteService
public OMElement getNextPublicationData() {

OMFactory factory = null;
OMNamespace namespace = null;
OMElement stockElement = null;
OMElement data = null;

// <ns1:publish xmlns:ns1="http://stocktrader.consumer">
//       <ns1:Stock xmlns:ns1="http://stocktrader.consumer">12345
// </ns1:publish>

factory = OMAbstractFactory.getOMFactory();
namespace = factory.createOMNamespace(NAMESPACE, "ns1");
stockElement = factory.createOMElement(STOCK, namespace);

int value = r.nextInt();
stockElement.setText(Integer.toString(value));

data = factory.createOMElement("publish", namespace);
data.addChild(stockElement);

return data;
}

The above code will generate the data to publish - where the subscribers can recieve. At the same time pay your attention to line:20.

Here the subscribed services should have a method called 'publish' [that is, they should match the name used here].
store = CommonUtil.getSubscriberStore(serviceContext.getAxisService());

if (store != null)  {
data = getNextPublicationData();
publicationClient = new PublicationClient(serviceContext.getConfigurationContext());
publicationClient.sendPublication(data, serviceContext.getAxisService(),null);
}
Line:1 will get the SubcriberStore for the corresponding service, in this case, for the StockQuoteService. Savan, module will create the SubcriberStore for the given service upon the first subscription request.

Following, shows the services.xml for StockQuoteService, where you need to engage "addressing" and "savan" modules.
<!-- src/META-INF/services.xml -->
<service name="StockQuoteService" scope="application">

<module ref="savan" />
<module ref="addressing" />

<parameter name="ServiceClass" locked="false">
org.apache.ws.axis2.StockQuoteService
</parameter>

</service>
Now lets deploy the StockQuoteService.

Right click the project axis2-savan-event-source, select 'Export' --> Select 'General/Archive File'. --> Select settings as in the image below.

Lets, move to the Event sink[axis2-savan-event-sink] or the StockQuoteConsumer.

This service has a single method, which simply prints the notifications received from the StockQuoteService.
public void publish(OMElement param) throws Exception {
System.out.println(param);
}
services.xml for the StockQuoteConsumer service will look like, following.
<service name="StockQuoteConsumer">

<parameter name="ServiceClass" locked="false">org.apache.ws.axis2.StockQuoteConsumerImpl</parameter>

<operation name="publish" mep="http://www.w3.org/2004/08/wsdl/in-only">
<messageReceiver class="org.apache.axis2.receivers.RawXMLINOnlyMessageReceiver" />
</operation>

</service>
Note down here that we do not engage 'savan' module with the StockQuoteConsumer.

Now deploy the StockQuoteConsumer service in the same way as we did in StockQuoteService.

Let's focus on the Client code.
final static String SUBSCRIBER_ID = "wso2-svan-subscriber";
final static String EVENT_SINK_EPR = "http://localhost:8080/axis2/services/StockQuoteConsumer";
final static String EVENT_SOURCE_EPR = "http://localhost:8080/axis2/services/StockQuoteService";

ServiceClient client = null;
Options options = null;
ConfigurationContext confContext = null;
EventingClientBean bean = null;
EventingClient eventingClient = null;


confContext = ConfigurationContextFactory.createConfigurationContextFromFileSystem("repo","repo/conf/client.axis2.xml");
client = new ServiceClient(confContext, null);
options = new Options();
options.setTo(new EndpointReference(EVENT_SOURCE_EPR));
client.setOptions(options);
client.engageModule("addressing");  

bean = new EventingClientBean();

// indicates where to send notifications
bean.setDeliveryEPR(new EndpointReference(EVENT_SINK_EPR));

// where to send a SubscriptionEnd message 
// bean.setEndToEPR(new EndpointReference(""));

// indicates the event sink would prefer to have the subscription expire
// bean.setExpirationTime(new Date(""));
// bean.setExpirationDuration(new Duration("10"));

// bean.setFilter(filter)'
// bean.setFilterDialect(filterDialect);

eventingClient = new EventingClient(client);
eventingClient.subscribe(bean, SUBSCRIBER_ID);
All set, start the Axis2 simple server first and then simply run the Client.

You can see the out put on Axis2 simple server console.

Mainstream SOA: Next-generation application development for the rest of us

Register today for the FREE webinar on the subject.

Presenters: Daniel Brum, Director of Technical Sales, WSO2 and Mike Moniz, Product Manager, Active Endpoints, Inc:.

Free Skype Call Recording with Call Graph

Available to download from here.

Automatically record Skype calls in a mp3 or wav file format.

The recording can be stopped or restarted at any point during the call by double clicking on the Call Graph Taskbar Icon.

Manage your calls and view timeline of your records.

Tag your records with names, subject, or any other keywords.

Call Graph automatically tags the calls with the display name of the contact.

These tags can be changed/removed/added from the search dialog.

Search with tags to locate needed call records.

All call graphs are tagged by default with the display name of the contact.

This makes it very easy to locate records from a particular contact.

Record Skype to Skype, SkypeIn, SkypeOut calls.

And Skype Conference Calls and Skype Casts

RESTful PHP Web Services

Representational State Transfer (REST) is a form of software architecture; systems that follow it are often called RESTful. It is the architectural style that drives the World Wide Web (the motivation for REST was to capture elements that made the Web successful), and RESTful web services use simple protocols already familiar to web developers. RESTful web services are found in lots of places with big name Web APIs such as Flickr, and Yahoo search following a REST-based approach.

With any architectural style or approach, struggling with its basic concepts is just one problem – implementation in your favorite language is another, and that's where this book comes in. If you're a PHP developer, this book will show you how to create and consume RESTful web services in PHP, and make your services work well in the context of the Web.

You will learn about the basic concepts of REST, and then look at PHP tools, libraries and techniques for working with RESTful web services. You will see how to use other RESTful services from your PHP applications, and also how to engineer your PHP applications to make them RESTful.

This book is about implementing RESTful web services in PHP, and so the book is packed with example code and careful explanations.

The author, Samisa Abeysinghe is the Director, Engineering at WSO2.

Samisa pioneered the Apache Axis2/C effort and architected the core of the Apache Axis2/C Web services engine.

Extending WSO2 Registry with Handlers

In this article, Chathura Ekanayake discusses on extending the WSO2 Registry capabilities using the handler framework. He gives details on concepts and architecture of the handler framework and illustrates its use with a sample.

Knopflerfish 2.1.1 RELEASED

Knopflerfish 2.1.1 is now released and is available here for download.

This is a maintenance release of KF and includes following features and fixes:

- Improved and update desktop bundle with
- new desktop views for events and bundle preferences
- new bundle icon for bundles having Declarative Services
- Improvements with System property handling,
- Improvements with fragments handling.
- KF build system enhancements.

Javascript debugging made easy with IE 8 - beta 2

Feel like debugging C# in Visual Studio...

IE 8 beta 2 can be downloaded from here.

WSO2 Identity Solution – Implementation of a CardSpace Authentication Framework

WSO2 Identity Solution is an implementation of Microsoft CardSpace specification.

It can issue InfoCards based OpenID tokens, SAML security tokens and pure OpenIDs.

Dimuthu Leelarathne in this white paper describes how CardSpace Specification was implemented by the WSO2 security team.