Applying the web services invocation framework

Calling services independent of protocols

The Web Service Invocation Framework provides a means to call any web service irrespective of the transport protocol or where it is located. This allows WSIF to be used to call non-SOAP based services in the same manner, simplifying application development. Learn about the recent changes to WSIF as it is submitted to the Apache Software Group.

Paul Fremantle, Senior Software Engineer, IBM Application and Integration Middleware

Paul Fremantle is an architect in IBM's Hursley Laboratory, working on web services components in IBM WebSphere Application Server, as well as open source projects such as WSDL4J and WSIF. Paul is the co-lead of the Java standard JSR110: Java APIs for WSDL. Paul previously worked as a WebSphere specialist in the software group and as an architect in IBM Global Services. Before joining IBM, Paul worked as a consultant in the pharmaceutical industry.
His publications include articles on porting EJBs from WebLogic to WebSphere, and a Redbook, "The XML Files: Using XML and XSL in WebSphere." Paul has presented at ApacheCon, XML Europe, Software Architecture, and other industry conferences. He has an M.A. in Mathematics and Philosophy and an M.Sc in Computation from Oxford University.
You can contact Paul at pzf@uk.ibm.com.



01 June 2002

Introduction

The Web Service Invocation Framework (WSIF) is a simple Java API for invoking web services, no matter how or where the services are provided. It frees the developer from the constraints of having to develop services for particular transport protocols or service environments. Thus, it has an API that provides binding-independent access to any web service. It allows stubless or completely dynamic invocation of web service, based upon examination of the meta-data about the service at runtime. It also allows updated implementations of a binding to be plugged into WSIF at runtime. It can also allow a new binding to be plugged in at runtime, if you use WSIF's provider concept. It allows the calling service to choose a binding deferred until runtime. Finally, it is closely based upon WSDL, and so it can invoke any service that can be described in WSDL.

WSIF was initially released on alphaWorks in October 2001 (see Resources). The alphaWorks release has had more than 4000 downloads since posting. There are already two excellent articles on WSIF by one of the creators describe the motivation and use of WSIF and you are encouraged to read those (See web service invocation sans SOAP, Part 1 and 2 in Resources).

This article corresponds with the donation of WSIF to the Apache Software Foundation. The WSIF source code has been donated to the Apache XML project under the auspices of the Axis work. It is available on the Apache CVS tree under the name xml-axis-wsif. The code can be browsed at: http://ws.apache.org/axis/cvs.html.

In this article I'll take a look at the motivations, usage, and architecture of WSIF. The changes to WSIF since the alphaWorks release are outlined, and there is a look at experimental and future ideas. But before all that, I'll quickly recap WSDL.


Some background on WSDL

The Web Services Description Language (see Resources) is inherently extensible -- from the beginning, the designers built in a separation between the interface and implementation of services in WSDL.

In WSDL a service is defined in three distinct parts:

  1. The PortType. This defines the abstract interface offered by the service. A PortType defines a set of Operations. Each operation can be In-Out (request-response), In-Only, Out-Only and Out-In (Solicit-Response). Each operation defines the input and/or output Messages. A message is defined as a set of Parts and each part has a schema-defined type.
  2. The Binding. A binding defines how to map between the abstract PortType and a real service format and protocol. For example, the SOAP binding defines the encoding style, the SOAPAction header, the namespace of the body (the targetURI), and so forth.
  3. The Port. This defines the actual location (endpoint) of the available service -- for example, the HTTP URL on which a SOAP service is available.

In WSDL today, each Port has one and only one binding, and each binding has a single PortType. Conversely (and more importantly), each Service (PortType) can have multiple Ports, each which represents an alternative location and binding for accessing that service.

We set out to mirror WSDL when we designed WSIF -- because we wanted an API based on WSDL rather than directly on SOAP. WSIF is effectively a framework for plugging in support for transports and formats. These are called providers in WSIF, and the most obvious provider supports SOAP.

Adding extensibility elements to WSDL allows the creation of descriptions of other service implementations than SOAP. Typically, web services are implemented using existing application components -- such as Java classes, Enterprise JavaBeans, or COM objects. These components are also sometimes wrappers for applications on legacy systems, such as mainframe transaction systems. By extending WSDL to describe the existing component models, we can capture the dependence relationship between the exposed SOAP-available service and the underlying component, and the fact that the two available implementations are actually the same business service. In fact, adding extensibility elements for existing components does something more -- it adds the description capability of the services oriented architecture to the existing component model.


Motivation for WSIF

The motivation for WSIF is that we wanted to see the "Services Oriented Architecture" become wider than just SOAP. There are a number of different protocols, transports, and distributed computing technologies that offer more than SOAP does today -- especially in terms of management, transactions, security, and other Quality of Service (QoS) features. While SOAP is catching up quickly, the main issue is actually one of investment. Many companies already have an investment in technologies such as CORBA that they wish to use and keep. On the other hand, web services with SOAP have a unique advantage -- an infrastructure for description and discovery. Anyone can download a WSDL document they have found either in a UDDI directory or in an inspection document, and use a commonly available tool to generate code that uses that service, whether it is on a local network or across the Internet. The common availability of this description language is also fuelling the growth of other tools -- for example the development of languages for composing and choreographing services together (for example, XLANG and WSFL).

We really wanted to make the extensibility and structure of WSDL real. WSDL allows us to describe existing systems using extensibility elements. For example, we have written WSDL extensions to describe transactions in CICS and IMS using connectors, calls to remote stateless session Enterprise JavaBeans, as well as SOAP and non-SOAP messages over JMS-based messaging systems. However, while describing things is useful, it isn't as useful as executing them.

WSDL today is not just a description layer -- it has a real implementation in tools that can use WSDL descriptions to generate stubs that can access the services. So if we add descriptions of non-SOAP systems, we are in danger of losing that benefit. WSIF addresses that. Effectively it is a pluggable framework, which allows providers to be plugged in. A provider is a piece of code that supports a WSDL extension and allows invocation of the service through that particular implementation. This means that the client code is independent of the implementation, and only dependent on the PortType of the service. WSIF also allows late binding, where a new provider and description are made available at runtime, and the existing client can then utilize the new implementation. Finally, WSIF allows the client to delegate the choice of port to the infrastructure and runtime, which can allow the implementation to be chosen on the basis of quality of service characteristics or business policy.

The structure of WSDL allows there to be multiple implementations for a web Service, and multiple Ports that share the same PortType. In other words, WSDL allows the same interface to have bindings to SOAP and IIOP. We wanted our API to allow the same client code to access any available binding -- if the code was written to the PortType then it would be a deployment or configuration setting (or a code choice) which port and binding was used.

We established the following requirements for WSIF. It must:

  1. Support any valid WSDL extensions.
  2. Support dynamic invocation of WSDL-described services.
  3. Support an API based on WSDL PortTypes.
  4. Allow late binding to different formats and transports.
  5. Support both compiled and dynamic approaches.
  6. Support minimum code deployment scenarios (n providers, no per-service code).
  7. Support different in-memory representations of service request data.

WSIF usage

There are two ways of using WSIF: a stub-based model and a dynamic invocation interface (DII).

Stub model

The stub-based model allows users to use the normal programming model to call business methods on web services. There is a standardised Java mapping from WSDL defined interfaces into Java defined interfaces -- in the JAX-RPC standard. There was some effort to integrate the WSIF model with JAX-RPC through the JCP/JSR process, but it was felt that WSIF was too experimental to include at that point. What we have done is created a loose-integration. JAX-RPC defines the Service Definition Interface -- the business interface of the stubs. WSIF also defines an interface to use the same SDI as JAX-RPC. So, although WSIF and JAX-RPC do not share interfaces, they do share tooling (for example, Axis WSDL2Java). An example of the stub model is shown in Listing 1.

1	WSIFService sq = ServiceFactory.newInstance().
	getService("http://my.com/svcs/stockquote.wsdl");
2	MyService mySvcStub = sq.getStub("soap", MyService.class);
3	mySvcStub.myMethod();

Dynamic invocation interface

The DII is modelled very closely on WSDL. In WSDL, an operation has an input message and optionally an output or fault messages.In WSIF, we navigate a similar hierarchy. There is a close correspondence. In fact, our first iteration was a one-for-one correspondence, but we refactored to be more logical and (slightly) simpler. The correspondence is shown in Table 1: Correspondence of WSDL and WSIF entities.

Table 1: Correspondence of WSDL and WSIF entities
WSDLWSIF
(WSIL/UDDI)WSIFServiceFactory or JNDI
ServiceWSIFService
PortWSIFPort
Binding(No corresponding entity)
OperationWSIFOperation
MessageWSIFMessage
Part(No corresponding entity)

To use the DII you need to:

  1. Select a port.
  2. Create an operation.
  3. Create and populate the in-message.
  4. Execute the operation.
  5. Read the response data from the out-message.

A simple example is shown in Listing 2.

1	WSIFService sq = ServiceFactory.newInstance().
	getService("http://my.com/svcs/stockquote.wsdl");
2	WSIFPort defPort = sq.getPort();
3	WSIFOperation getQ = defPort.createOperation("getQuote");
4	WSIFMessage inMessage = getQ.createInputMessage();
5	inMessage.setStringPart("symbol", "IBM");
6	...
7	getQ.executeRequestResponse(inMessage, outMsg, fltMsg);
8	outMessage.getFloatPart("value");

One of the features of the alphaWorks release of WSIF was a command-line tool called the DynamicInvoker, which can invoke any web service that has simple types in the interface. One of the requests we frequently had was to allow dynamic invocation of services that used complex types for the parameters. WSIF was designed with this in mind, but for the first iteration we only supported the use of JavaBean components to represent complex types, so you could not invoke a service which required these without first generating an appropriate JavaBean component. To remedy this, we have developed a set of classes called JROM (originally this stood for Java Record Object Model -- but it's really just become a name -- pronounced Jay-Rom). JROM is an abstract tree structure that can represent most schema complex types in memory. Think of JROM as a lightweight DOM, where each leaf in the tree is a basic type (unlike DOM, where they are all strings).

By using JROM with WSIF, dynamic invocation is allowed even if there are no Java types that match the schema complex types in the classpath. This is a very powerful approach, especially in building dynamic web services systems such as gateways, flow engines, or test clients. Not all the providers support JROM as yet, but we have added support for JROM into the ApacheSOAP provider.

JROM is not part of the WSIF open-source release, but is being made available on alphaWorks, see www.alphaworks.ibm.com/tech/jrom.


WSIF architecture

The architecture of WSIF is based on a number of factories. The reason for using factories is that we wanted to hide whether the objects used were "static" or "dynamic." In the static case, the objects are generated to satisfy that particular port, message, or operation. This allows a very fast implementation to be built. In the dynamic case, the objects use the WSDL description at runtime to handle the particular port, operation or message handling. Currently WSIF mainly uses dynamic objects, as this is how we implemented them initially. We actually envisage several different levels of dynamism.

Fully dynamic architecture

This might be used, for example, in a flow control engine, where a flow description is provided as an XML document. The flow engine manipulates messages before sending them on to other operations to create a new aggregate service. The deployed code is one provider per binding type. Thus, there are b artifacts where b is the number of different WSDL binding extensions.

Semi-dynamic architecture

The messages that define the PortType are staticly compiled, but the bindings themselves are dynamic. This requires code-deployment based on the PortType, plus one provider per binding type. Thus, there are p + b artifacts, where p is the number of PortTypes, and b is the number of WSDL bindings. The compiled messages have to be redeployed when the interface changes.

Static architecture

Both the WSDL bindings and the ports are staticly compiled. In this case the default ports that were defined at tooling time are compiled. The code deployment is one entity per binding instance. Thus, the number of artifacts is p x b.


Changes since the alphaWorks release

There are a number of changes since the alphaWorks release. You are encouraged to look at the open source code tree yourself. The main changes are:

  • Simplification of the WSIFMessage and WSIFPart model. We removed the WSIFPart interface and merged it into WSIFMessage. In order to capture different styles of using WSIFMessage, we added a method getRepresentationStyle().
  • Renaming of the PortFactory object to Service.
  • Addition of a ServiceFactory interface.
  • Change from using the PortTypeCompiler to using the J2SE 1.3 dynamic proxy support.
  • Addition of new bindings and transports -- SOAP over JMS, EJB binding, Apache Axis-based SOAP provider.
  • Support for tracing and logging activity.
  • Support for dynamic registration of new providers using the J2SE JAR service provider spec (see Resources).

Experimental additions to WSIF

Currently there are a number of areas we are exploring with WSIF, among them are asynchronous request-response messages, and context-aware messages.

Asynchronous request-response

We currently have an asynchronous request-response model, where the response is handled in a different thread of execution from the originating request. To support this, basically, the requestor registers a callback object or handler, that is invoked when the response is received.

When the request message is sent, the handler object is passed to WSIFOperation. WSIF provides a correlation service to store the handlers against a given identifier. WSIFOperation calls the WSIF correlation service, that stores the service itself and the handler using the correlation id of the request. This all takes place within the current transaction. If the requesting user has specified a transactional queue, then the work is done within the current transaction.

The WSIFOperation and WSIFResponseHandler objects are serializable so that the state of the handler object can be persisted in case of system failure between the request and response. The correlation service is also pluggable so that other features such as atomic transactions and persistence can be provided for high-availability.

When the response comes at some later point, a listener thread picks it up and passes it to the stored WSIFOperation. The operation contains the logic to demarshall the response into a WSIFMessage, and then executes the handler method executeAsyncResponse() with outMessage as the parameter. The listener thread is running on a different transaction from the original request, and so the response is a separate transaction from the request.

For example, Listing 3 shows how a handler is implemented based on the WSIFResponseHandler class. A handler is designed to understand the response message and use the response values.

Listing 3. Implementing an ansynchronous handler in WSIF
1	public class QuoteHandler implements WSIFResponseHandler  {
2	       
3	protected String symbol = null; // local storage of the symbol we wanted quoted
4	public void setSymbol(String value) { symbol = value };   
5	public void executeAsyncResponse(WSIFMessage out, WSIFMessage fault) {
6	         // this simplified example assumes no failures and that the symbol has 
			been set correctly
7		float quoteValue = out.getPart ("quote");
8		updateQuoteDB(symbol, quoteValue);
9	}

The service invocation is shown in Listing 4.

Listing 4. Invoking a service asynchronously with WSIF
1	String symbol = "IBM";
2	QuoteHandler quoteHandler = new QuoteHandler();
3	quoteHandler.setSymbol(symbol); // the handler needs to know 
	the symbol when it gets executed later.
4	
5	WSIFMessage inMessage;
6	WSIFOperation quoteOperation;
7	...
8	inMessage.setXXXPart(...) // set up inMessage for invocation
9	quoteOperation.executeAsyncRequestResponse(inMessage, quoteHandler);

Content-aware message

We also wanted to support the idea of setting and using context. There has been some discussion in the WS-Description working group of the W3C on this topic, but no actual syntax or semantics yet.

For example, a SOAP/HTTP port may require an HTTP username and password. This information is specific to the invocation, but not usually a parameter of the service. In general, context is defined as a set of name-value pairs. However, as web services tend to define the types of data using XML Schema types, we choose to represent the name-value pairs of the context using the same representation that WSIFMessages use -- namely a set of named Parts, each of which equates to an instance of an XML Schema type. This has slightly more overhead than using a properties concept, but more in keeping with the rest of WSDL and WSIF.

The methods setContext() and getContext() on a WSIFPort and WSIFOperation allow the application programmer or stub to pass context information to the binding. The Port implementation may use this context -- for example to update a SOAP header. There is no definition of how a Port may utilize the context.


Ideas for the future

There are a number of areas in WSIF we would like to see work on to improve its functionality and usefulness. First, we would like to have refactoring capabilities to separate the transport from message formatting. We have defined a WSIFFormatter class to allow access to and conversion of the data into a native format.

Next, an abstract tree representation of the data in a a message would be useful. Currently, we mainly use compiled classes from the schema to carry the service parameters in WSIFMessage. However, in one implementation of WSIF, the Web Services Gateway (see Resources), we use an abstract tree notation called JROM that closely maps to an XML Schema.

We would also like to see more and better providers for the many types of transports and object systems that exist. Finally, an implementation of WSIF in C or C++ would certainly be helpful to developers creating services in those languages.


Summary

The Web Services Invocation Framework is an open source initiative to provide a service oriented framework that allows both SOAP and non-SOAP services to be described in WSDL and invoked in a common way. WSIF defines a pluggable interface (provider interface) to support new transports and protocols. By supporting both a proxy interface and dynamic invocation interface WSIF allows end users and system software developers use the multi-protocol support that WSIF offers. WSIF supports late binding, so that services can be retargeted to new protocol types without code changes. The open source WSIF codebase includes providers for Java, EJB, and SOAP (over HTTP and JMS). WSIF has been used in WebSphere Enterprise Edition 4.1 and Versata's Logic Server WebServices Add-On.

Acknowledgments

The main contributors to the WSIF release, in alphabetical order, are: Aleksander A. Slominski, Anthony Elder, Dieter Koenig, Gerhard Pfau, Jeremy Hughes, Mark Whitlock, Matthew J. Duftler, Michael Beisiegel, Nirmal Mukhi, Owen Burroughs, Paul Fremantle, Piotr Przybylski, and Sanjiva Weerawarana

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into SOA and web services on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=SOA and web services
ArticleID=11670
ArticleTitle=Applying the web services invocation framework
publish-date=06012002