Articles Forum Examples Download Open Source
Oct 15, 2007
Copyright 2007 by Pocomatic Software. All Rights Reserved.
Web Services applications are software systems consist of service users (clients) and service providers (servers). Clients use SOAP protocol to access services provided by remote servers. These services are business logic components implemented, for instance, in conventional programming languages (such as C++ and Java).
Service components are deployed to a runtime environment, referred to as WebServices container hereafter, which adopts them as service endpoints to a message dispatch engine atop a SOAP stack. Ideally, such a container infrastructure should reduce the complexities and cost of WebServices application development and maintenance.
Unfortunately, available WebServices containers are mostly proprietary and primitive, especially for C++ applications. Not only they rely on vendor specific component programming, configuration, and deployment models, but also they do not have a declarative assembly model. These problems largely prohibit the reusability of third party and legacy service components, rule out the transferability of developer/user skills and experiences, and discourage the interchangeability of development tools across containers from different vendors.
A group of vendors known as the Open SOA Collaboration have been soliciting their Web Services component architecture, the Open Service Component Architecture (SCA), as an industrial standard. Lately, the SCA effort has been moved into OASIS and renamed as Open Composite Service Architecture (CSA).
As a design-by-committee architecture, the SCA (especially the SCA C++ mapping) emphasizes its sophisticated appearance rather than the straightforwardness and the effectiveness. The SCA C++ mapping committee decided not to use the non-invasive inversion of control (IoC) on plain old C++ objects (POCO) for component wiring and property setting. Instead, a contrived thread local context lookup scenario was invented, a kludge that has been abandoned by the mainstream industry for years.
For instance, in a plain old C++ object implementation, a dependent service object reference can be injected to the user object through a setter method (accountDataService()) as follows:
|
// a setter method sets the dataService dependency void AccountServiceImpl::accountDataService( AccountDataService* service) { ... _dataService = service; }
AccountReport AccountServiceImpl::getAccountReport( const std::string& customerId) { // calling a method on the service reference. ... = _dataService->getCheckingAccount(customerId); ... }
|
By the SCA C++ mapping, however, an assembly container does not actually wire up components. Rather, it only configures the wiring on component shadow contexts. These SCA proprietary component contexts are served by the container runtime. Before calling a dependent service, the business logic implementation (such as the getAccountReport()) of a component supposes to resolve the reference of that service from its shadow context and then dangerously cast the returned void pointer to the assumed service interface type. This scenario is illustrated in the following code (see section 1.3 of the SCA C++ mapping specification as well as the BigBank example):
|
AccountReport AccountServiceImpl::getAccountReport( const std::string& customerId) { ComponentContext* context = ComponentContext::getCurrent();
// Look up the wiring from the thread local context. // The return value is an opaque pointer (void*). void* ptr = context->getService( <id-of-account-data-service>);
// Dangerously cast the opaque pointer to the // assumed class type without any type check. AccountDataService* _dataService = (AccountDataService*)ptr;
// Finally, the _dataService dependent reference // is ready for use. ... = _dataService->getCheckingAccount(customerId); ... } |
This design is not only dangerously type unsafe but also forces component implementations to be tightly coupled with the underlying SCA (OASIS-CSA) container. Consequently, SCA C++ components have to be designed and implemented specifically for a SCA container, debugged and tested within the SCA container, and built against the SCA container runtime library.
The SCA C++ mapping also imposes many contrived restrictions in its component and deployment models, such as rules on file names of composite descriptions and rules on component implementation classes (have to have their methods declared in abstract base classes). These contrived restrictions do give the SCA a sophisticated look and can also help SCA vendors to tightly lock-in adopted customers. However, they largely sacrifice the simplicity, usability, legacy compatibility, and flexibility of the framework itself and its application implementations.
A non-invasive IoC framework, such as PocoCapsule, inherently supports Web Services component assembly and configuring. In contrast to those proprietary, complex, and restrictive Web Services component solutions and SCA, this IoC based assembly and configuration alternative is open, straightforward, and flexible. It has the following characteristics:
Neutral to component programming models: Hence, it seamlessly supports component programming models imposed by any SOAP protocol stacks or WSDL to C++ mappings, such as what supported by Apache Axis C++, gSOAP C/C++, and HP Systinet WASP Server for C++.
Assembly/configuration model is orthogonal to Web Services: Therefore, development experience and tools for this model are fully transferable from and applicable to other problem domains.
Agnostic to container: Components are completely decoupled from the framework runtime environment. Components can be designed, implemented, built, debugged, tested, and even used without using or even without knowing the container.
Free from contrived restrictions: It does not mandate the names of composite description files, does not even mandate they are described in files. It does not impose any restriction on component C++ class, and implementation programming paradigms. For instance, an implementation can be made in interface-paradigm (inherited from pure abstract classes), generic-programming-paradigm (from template classes), or model driven paradigm (explicitly generated from CASE, UML, or MDA tools).
The IoC technique also provides a straightforward and declarative method to deploy service components to arbitrary WebServices runtime. For instance, with explicit imperative program, a Web Services service component could be deployed as a service endpoint in the following pseudo C++ code:
|
AccountServiceImpl my_service;
// a service component ... // deploy it to the WS runtime adapte env WSAdaptor::export_service( ..., &my_service, "AccountService", ...); |
From IoC perspective, such a service endpoint deployment is no more than injecting references of either service component beans or their factory/manager beans as dependencies to the Web Services runtime environment adapter bean(s). The above C++ code, therefore, can be expressed in the following declarative application description:
|
<bean id="my-service" class="AccountServiceImpl"/> <bean class="void" factory-method="WSAdaptor::export_service"> ... <method-arg ref="my-service"/> <method-arg type="string" value="AccountService"/> ... </bean> |
Further, to conceal low level complexities of this service deployment programming model from domain users, a domain specific modeling (DSM) schema can be defined that uses an <endpoint> element to express the factory injection based on the factory method WSAdaptor::export_service(). With this DSM schema, the application description becomes:
|
<bean id="my-service" class="AccountServiceImpl"/> <web-server> <endpoint
ref="my-service" name="AccountService"/> </web-server> |
As concluded in the previous section, an IoC framework, such as PocoCapsule, is inherently a web services component assembly, configuring, and deployment container. With minimum extension, a DSM schema is able to express web service endpoint deployment in very high level declarative application descriptions. Such a DSM model, defined in the http://www.pocomatic.com/ws-application.dtd, is supported by PocoCapsule/C++ out-of-the-box.
The BigBank example from SCA is used here to illustrate how to assemble, configure, and deploy a component based Web Services application in this IoC model. The full source code and document of this example can be found in the examples/web-services/bigbank-ws directory of a PocoCapsule/C++ IoC&DSM installation. This application is declared in the following description:
|
<ws-application> <bean id="AccountService" class="AccountServiceImpl"> <ioc method="accountDataService"> <method-arg ref="AccountDataService"/> </ioc>
<ioc method="stockQuoteService"> <method-arg ref="StockQuoteService"/> </ioc>
<ioc method="currency"> <method-arg type="string" value="EURO"/> </ioc> </bean>
<bean id="AccountDataService" class="AccountDataService"/>
<bean id="StockQuoteService" class="StockQuoteService"> <ioc method="webService"> <method-arg ref="StockQuoteWebService"/> </ioc> </bean>
<bean id="StockQuoteWebService" class="StockQuoteSoap"/>
<web-server> <endpoint name="AccountService" ref="AccountService"/> </web-server> </ws-application> |
By this description, this application consists of the following beans and organization structure:
Three plain old C++ objects: AccountService, StockQuoteService, and AccountDataService. They will be instantiated on demand using their C++ constructors.
A soap stub object StockQuoteWebService, will be instantiated on demand using the StockQuoteSoap class constructor.
These beans and the soap stub object are configured and wired together using IoC setters.
The AccountService bean is deployed as a service endpoint using the DSM <web-server> and <endpoint> elements.
The application structure described above is illustrated in the following diagram:

PocoCapsule IoC & DSM is not only an inherent and straightforward framework for building component-based Web Services applications, but also an open and effective platform for quickly authoring other user-defined or committee-designed assembly/deployment models, including the SCA assembly model.
A SCA assembly/deployment model authored as a domain specific model (DSM) is available out-of-the-box in the PocoCapsule installation. It demonstrates that the combination of a plain-old C++ object (POCO) based SCA component programming model and a non-invasive inversion of control (IoC) based SCA assembly model is much superior to its predecessors. Not only this POCO+IoC based SCA container (supporting SCA assembly model) is built within a few hours (after spending weeks to figure out the "simple" SCA specification itself) instead of nearly a year of heavy engineering effort, but also it largely avoids and eliminats complexities, flaws, and restrictions of the original design-by-committee SCA C++ mapping specification and its reference implementation, as summarized in the following table:
|
|
The designed-by-committee SCA C++ mapping and its reference implementation |
The SCA based on plain C++ components and authored as a DSM of an IoC framework |
|
Engineering cost |
Several thousands lines of code involving low level APIs. A team of senior developers, nearly a year of heavy engineering effort. |
Only a few hundreds lines of code without involving low level APIs. A few days or even hours of casual exercise. |
|
Component-container coupling. |
Components have to look up container served shadow contexts to resolve dependency references and property settings, and then set up these dependencies and properties by themselves. |
Components are container agnostic and only need to consist pure business logic. Dependency and property settings are explicitly injected and set via IoC invocations. |
|
Type safety |
Dangerously unsafe (getService() returns void*). Equivalent to C-style cast or the reinterpret_cast, the potential type mismatch is very hard to be diagnosed. |
Type safe, with both build time and runtime type check. Type mismatch will be detectable at build time as well as runtime. |
|
Support multi-hop local component calls, dependency calls in user thread, etc.. |
No. The ComponentContext:: getCurrent() only returns the component context on the thread-local-storage that is set by the container on dispatching the request to the initial component. |
Yes, the wiring model is completely orthogonal to the underlying thread model. |
|
Life cycle control |
No |
Yes |
|
Wiring and property setting through constructors/factories |
No |
Yes |
|
Names of SCDL composite description file names |
Has to use the ".composite" as the extension name. |
No restrictions |
|
Component implementation programming model |
All methods of a component implementation class have to be declared in an abstract base class (SCA C++ mapping spec. section 1.2.1). All public methods of this abstract base class have to be pure virtual (SCA C++ mapping spec. Appendix 3) |
No restrictions. The assembly model seamlessly works with Apache Axis C++, gSOAP C/C++, HP Systinet WASP Server for C++, as well as any plain-old C++ classes that are declared and implemented in any conventional style or paradigm (such as generic-programming). |
|
C++ preprocess macros, friend classes, templates, non-virtual methods, inline methods, static/global functions, function pointers, etc. in component interface define classes. |
Largely prohibited (SCA C++ mapping spec Appendix 3). Legacy components have to be refactored with wrapper implementations. |
Fully and seamlessly supported. |
|
The SCDL component descriptions. |
Heavily rely on component type files to ensure implementation classes are converted to desired interface classes |
No longer needed. |
|
Component wiring multiplicity attribute |
Mandatory for the assembly to work properly in case of multiplied wiring end (a subscribe(..) setter on an emitter component). |
No longer needed. Container is agnostic to multiplicity. |
|
Proprietary SCA C++ annotation |
Tying components to the container. Violated the plain old object premise. Implementations have to be specially implemented for SCA, or heavy manual refactoring. |
Not needed at all. |
The SCA
BigBank
example is used here to illustrate the POCO
component implementation and IoC wiring/deployment in SCDL schema of SCA. The
full source code and document of this example can be found in the examples/web-services/bigbank-ocsa
directory of a
PocoCapsule/C++ IoC&DSM installation. In SCDL schema of SCA, this
application is declared in the following composite description:
|
<composite name="bigbank.account"> <service name="AccountService"> <binding.ws port="http://www.bigbank.com/AccountService #wsdl.endpoint(AccountService)"/> <reference>AccountServiceComponent</reference> </service>
<component name="AccountServiceComponent"> <implementation.cpp class="AccountServiceImpl"/> <reference name="accountDataService">AccountDataServiceComponent</reference>
<reference name="stockQuoteService">StockQuoteServiceComponent</reference> <property type="xsd:string" name="currency">EURO</property> </component>
<component name="AccountDataServiceComponent"> <implementation.cpp class="AccountDataService"/> </component>
<component name="StockQuoteServiceComponent"> <implementation.cpp class="StockQuoteService"/> <reference name="webService">StockQuoteWebService</reference> </component>
<reference name="StockQuoteWebService"> <interface.wsdl interface="http://www.webserviceX.NET/ #wsdl.interface(StockQuoteSoap)"/> </reference> </composite> |
By this description, this SCA composite consists of the following components and organization structure:
The application structure described above is illustrated in the following diagram:

PocoCapsule/C++ IoC&DSM framework provides 25 examples out-of-the-box. Among them, the following five are for WebServices and SCA.
|
examples |
descriptions |
|
This is a basic client/server Web Services example deployed using PocoCapsule/WebServices deployment model. It comprises one service provided by a plain old server object extended from C++ SOAP skeleton. |
|
|
This example is originated from an OASIS-OpenCSA (formerly known as OpenSOA-SCA) user example highlighted in the official OASIS-OpenCSA documents and a prove-of-concept prototype implementation. Here, it is converted to use the PocoCapsule/WebServices service deployment and component assembly model, that is not only more intuitive, simpler and flexible but also powerful than OASIS-OpenCSA's model. |
|
|
This is a basic client/server Web Services example of using OASIS-OpenCSA assembly model. The assembly descriptor (service.composite) declares an OASIS-OpenCSA composition that comprises of one service provided by a plain old service object extended from a C++ SOAP skeleton. |
|
|
This is the well known OASIS-OpenCSA (formerly known as OpenSOA-SCA) user example highlighted in official OASIS-OpenCSA documents and the prove-of-concept prototype implementation. The assembly descriptor (bigbank.account.composite) declares an OASIS-OpenCSA composite that exports one web service, uses one external service, and contains three internal components. |
|
| This is also a OASIS-OpenCSA (formerly known as OpenSOA-SCA) user example originated from an OASIS-OpenCSA prove-of-concept prototype implementation. In this examples, components are wired up by using either OASIS-OpenCSA <wire> elements (if the calculator-by-wire.composite descriptor is used) or <reference> elements (if the calculator-by-ref.composite descriptor is used). |
Back to the PocoCapsule articles page
This page has been visited:
| free hit counter html code |