2010/07/07
7 Jul, 2010

Web Services API - WSO2 Governance Registry

  • Tharindu Mathew
  • Technical Lead - WSO2

Introduction

This article gives a thorough analysis of the WS API so that the reader can understand the architecture, applicable scenarios, advantages and limitations of the same. Also, it includes recommendations and guides on how to use this component in the most effective and efficient manner.

It is assumed that the user has a basic knowledge of web services and Registry operations. In the context of this article, registry refers to WSO2 Governance Registry and WS API refers to the Registry Web Services API.

Applies To

WSO2 Governance Registry 3.5 or later
JDK 1.5 or later

The Registry WS API

With the release of the 3.5 version of the Registry, it features a WS API that allows users to conduct registry operations through simple SOAP requests. The opening up of this channel makes the Registry useful in a number of possible ways. Also, it introduces some best practices that should be adhered to, when using the WS API. First, I will outline some of the main uses of the WS API below:

Uses of the WS API

The WS API allows access to the core APIs through SOAP requests. This factor alone introduces a number of advantages to a user:

  1. True remote access - When the back end of the Registry is in a separate location, the WS API is a great way of performing operations on the Registry. Since the WS API communicates using port 80 over HTTP, users can avoid problems arising due to firewalls.

Registry BE seperated

  1. Quality of Service (QoS) - Users require QoS aspects, such as security, reliability, etc., when accessing the Registry. The WS API allows users to engage Axis 2 modules for WS-Security, WS-Addressing, etc. according to their requirements.
  2. Any language, any platform - Since interoperability is an inherent nature of web services, the WS API allows a client to be written in any language on any platform to access the Registry.
  3. Programmatic interface – The registry currently allows programmatic access to its operations through the Registry Core API and Atom API. The WS API will add itself as an additional programmatic interface to the registry.

A Sample demonstration

Before diving into the architecture of the WS API, I'd like to look at demonstrating on how to work with the same. I'd be using the client library which is provided with the Registry distribution, that allows users to access the WS API just as they would be accessing the core Registry API itself. A more detailed sample is included in the WS API developer guide of the Registry documents.

Please extract and run a binary distribution of the Registry, available at https://wso2.com/products/governance-registry/, prior to trying out this sample. This can be done by running the wso2server.(bat or sh) script from the command line. The script is present in the $GREG_HOME/bin directory.

Setting up the WS API Registry Client

The following code shows how to set up the WS Client and authenticate it against an instance of the Governance Registry. NOTE: It is assumed that default configurations of the Registry have not been changed.

First, we have to set the system properties to enable the https connection.

String GREG_HOME = /path/to/Governance_Registry
System.setProperty("javax.net.ssl.trustStore", "GREG_HOME/resources/security/client-truststore.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "wso2carbon");
System.setProperty("javax.net.ssl.trustStoreType","JKS");

A number of parameters are required to initialize the client. These are initialized in the following code:

String axis2Repo = GREG_HOME + "/repository/deployment/client";
String axis2Conf = GREG_HOME + "/repository/repository/conf/axis2_client.xml";
ConfigurationContext 
 configContext = ConfigurationContextFactory.
 createConfigurationContextFromFileSystem(axis2Repo, axis2Conf);

The final steps of the initialization is done in the following code segment:

String username = "admin";
String password = "admin";
String backEndServerURL = "https://localhost:9763/services/";
String serverURL = "https://localhost:9443/services/";

WSRegistryServiceClient registry = new WSRegistryServiceClient(serverURL, username, password, backEndServerURL, configContext);

Please run an "ant" command at GREG_HOME/bin and add all the jars created in GREG_HOME/repository/lib to the class path prior to running the examples in this guide.

Now, if you now run this example, an output similar to the following output will be generated at the server side console:

[TIMESTAMP] INFO - 'admin' logged in at [TIMESTAMP] from IP address https://localhost:9443/services/AuthenticationAdmin

This client instance can now be used just as using the Registry API. Some of the possible operations are illustrated below:

Adding a resource to the registry

Resource r1 = registry.newResource();
String path = "/dev_guide/r1";
String r1content = "R1 content";
r1.setContent(r1content);
registry.put(path, r1);
Adding a resource using the WS API

From the above sample, I hope it is clear that the client is designed in such a way that every Registry operation can be performed as you are using the core Registry API itself. If I re-iterate this point, it means that every operation that can be called in the form of, registry.put(“/some_path”, some_resource) instead of registry.WSput(“/some_path”, some_resource).

Initializing the client just need the following parameters to be passed in :

WSRegistryServiceClient(String serverURL, String username, String password,
String backendServerURL, ConfigurationContext configContext)

If I explain these parameters further, all that needs to be provided are the URLs of the Registry that has been started. In basic cases serverURL and backendServerURL are the same. The backendServerURL will always be used to access the registry. Therefore, a http port used here would increase performance. An example of the recommended usage is (using default settings),

String backendURL = "https://localhost:9763/services/";
String username = "admin";
String password = "admin";
String serverURL = "https://localhost:9443/services/";

The making of the configuration context is skipped here for brevity. It is shown in the sample code shown above.

The WS API Architecture

WSDL Location : Once the Registry is started up, the WSDL can be viewed by going to the following URL: https://YOUR_IP_ADDRESS:9443/services/WSRegistryService?wsdl

The WS API acts as a wrapper class to the core Registry API. For all registry operations, the WS API wraps the operation and makes it compatible to function with web services. The inter-operable nature of web services introduces some limitations, thus, making some data objects and methods inaccessible as a web service. The WS API solves this issue by introducing a WS compatible objects and operations that corresponds directly to objects and operations in the core Registry API.

The following table illustrates the mapping between objects:

WS API

Core API

WSResource

Resource

WSCollection

Collection

WSComment

Comment

WSProperty (An array)

Properties (Java util object)

WSMap

Map (Java util object)

These web service objects are used for wrapping and unwrapping data to send across the network when the WS API is used.

The case of sending across a resource's content (obtained through getContent()), i.e. binary data or text, is done by using MTOM (Message Transmission Optimization Mechanism). It can be thought as the binary data or text is base64 encoded in the XML document, and set across the wire. To learn more about MTOM, please refer:

http://ws.apache.org/axis2/1_0/mtom-guide.html

The Registry WS Client performs the direct inverse of the wrapping/unwrapping done by the WS API. For ex: If a Collection (i.e. A Registry collection, not Java collection) is requested,

  • Server side – wraps the Collection and it's content as a WSCollection with an attachment, and sends it over across the wire as a SOAP message.

  • Client side – unwraps the WSCollection and the attachment, and converts it into a Collection with content and presents it to the user.

The WS API has been implemented mainly thorough the class, WSRegistry. The class implements the main Registry interface. But some methods in the Registry interface are not compatible to be exposed as web services. Therefore, each of these incompatible methods are wrapped by a web service compatible methods. The following table illustrates each of the methods that went through the wrapping process:


WS API

Core API

WSnewResource

newResource

WSnewCollection

newCollection

WSget

get – 2 parameters

WSgetMetaData

getMetaData

WSgetWithPageSize

get – 3 parameters


WSgetChildCollection

getChildCollection

WSput

put

WSimportResource

importResource

WSgetResourcePathsWithTag

getResourcePathsWithTag

WSaddComment

addComment

WSgetComments

getComments

WSexecuteQuery

executeQuery

 

WSsearchContent

searchContent

These methods will generally wrap Objects in WS compatible objects and send them over the wire.

A Sample Flow

Let me explain the flow of a method call and its response with the help of the following illustrations. I will consider a scenario where a registry.get() is called to obtain a registry Collection.

Let us first consider the flow of the method call. The numbers depict the order of the flow.

get() Method Call

(1) - The user program executes a get() method call
(2) - The WS API Client converts this call into a web service compatible WSget() method call and sends it over the wire
(3) - The WS API converts this method back to a get() method call and that calls the Core API

Now let us look at the response for the get() method call.

Response to get() method call

(1) - The Core API returns the relevant Collection object
(2) - The WS API converts this into a web service compatible WSCollection object and send it over the wire
(3) - The WS API Client converts the received WS Collection back into a Collection object and returns it to the user program

WS API Security

The WS API exposes almost all of the methods of the core API so that it can be accessed through a web services client. This kind of method exposure would implicitly raise questions on security. Users would concern themselves on what security mechanisms are used to secure this WS API channel. Bearing these concerns in mind, the WS API supports 2 security mechanisms:

  1. Basic Authentication over HTTPS
  2. WS-Security

Let's look at these 2 mechanisms in detail:

  1. Basic Authentication over HTTPS

Authentication through this mechanism is compulsory if you are to use the WS API. The client needs to be authenticated using valid credentials. These credentials are authenticated against the registry user base, so the user's registry credentials are valid for this purpose as well. The registry exposes a web service that allows authentication known as the Authentication Admin that allows a user to login to the registry using the exposed method 'login'. This web service is only accessible through HTTPS. The cookie obtained through the Authentication Admin is then used to access the WS API.

Here is how it's done in the Registry WS API service client:

 String serviceEPR = serverURL + "AuthenticationAdmin";
AuthenticationAdminStub stub = new AuthenticationAdminStub(ctx, serviceEPR);
ServiceClient client = stub._getServiceClient();
Options options = client.getOptions();
options.setManageSession(true);
try {
       boolean result = stub.login(username, password, serviceEPR);
    if (result){
            cookie = (String) stub._getServiceClient().getServiceContext().
                                getProperty(HTTPConstants.COOKIE_STRING);
       }
       return result;
} catch (Exception e) {
       String msg = "Error occurred while logging in";
       throw new AuthenticationException(msg, e);
}

Using this mechanism alone is recommended only when performance cannot be compromised. In other cases, the recommendation is to use WS-Security as well.

  1. WS-Security

WS-Security can be engaged to the Registry WS API by simply by dropping in the relevant policy file to the conf directory inside directory. Let the Registry installation location be $GREG_HOME. The policy file must be named “ws-api-sec.xml” and should be places in the $GREG_HOME/repository/conf directory. This will then be picked up and applied to the WS API. A sample policy file is available at [1]. The rampart module should be dropped into $GREG_HOME/repository/deployment/server/axis2modules.

NOTE: The server has to be restarted after this file is placed in the said location.

On successful engagement of security the following log statement will be displayed on the console:

[TIMESTAMP] INFO - Loading security policy for the Registry WS-API Component from $GREG_HOME/repository/conf/ws-api-sec-policy.xml

The class known as WSDeploymentInterceptor is responsible for engaging WS-Security for the WS-API. This class implements the Axis Observer interface. The methods of this interface is then used to engage security if the presence of a policy file is detected. In the presence of a “ws-api-sec.xml”, the policy within a file is attached to the service and Apache Rampart is engaged for the service for the said policy.

Conclusion

The WS API, when strengthened with a sound security mechanism, it is possible to operate the Registry through any environment making it truly inter-operable. The architecture and security of this component makes it suitable for most user scenarios. Later releases will concentrate more on performance and additional features. But it is stressed that further additions and enhancements will be made to the WS API to increase it's efficiency and performance while continuing to support the interoperability.

References

Registry API - https://wso2.org/project/registry/3.5.0/docs/apidocs/kernel/org/wso2/carbon/registry/core/Registry.html

Apache Axis2 - http://ws.apache.org/axis2

MTOM with Axis2 - http://ws.apache.org/axis2/1_0/mtom-guide.html

 

About Author

  • Tharindu Mathew
  • Technical Lead
  • Home