SCA

Reference

Overview

sgmljs.net SCA provides an advanced native API for implementing service components according to the OASIS SCA and SDO specifications. SCA and SDO are vendor-neutral specifications for implementing Service-Oriented Architectures and Microservices.

sgmljs.net SCA is designed as a practical and portable SCA and SDO implementation on Linux, Mac OS, and other POSIX/SUS systems

  • for use as (micro-) service back-end of modern browser-based applications using JSON/REST payloads
  • for direct use as the back-end of HTML forms-based browser interactivity
  • for providing content to sgmljs.net SGML template-driven web applications and other template engines capable to access remote HTTP services
  • to provide and consume enterprise services (using SOAP and other WS-* protocols) and for integration of web and enterprise applications
  • for use as network communication library and container target by the coJS JavaScript compiler.

Note: this document describes a native API using C language concepts and terms, suited for development in language environments capable to interface with native platform ABIs, such as C, C++, Rust, or Go. Please refer to the coJS manual for developing sgmljs.net SCA services using the JavaScript language.

In SCA

  • a service is a a piece of business functionality accessed locally or remotely described using the the Web Service Definition Language (WSDL).

  • functionality is provided in components implementing services

  • components can invoke other components.

SCA components provide services via service bindings. sgmljs.net SCA can provision services using one of the following binding types:

  • POX ("plain old XML")
  • POJSON ("plain old JSON")
  • SOAP 1.1 HTTP binding (optionally with WS-Addressing)
  • SOAP 1.2 HTTP binding (optionally with WS-Addressing)
  • XML/REST
  • JSON/REST (via JSON/XML mapping)
  • local (ie. invoked as a shared library function in the same process context as the invoking component).

SCA provides a uniform API and standardized binding rules for supported remote access protocols, so that a service implementation only needs to target the SCA API, rather than having to implement protocol specific code for each desired protocol.

A component can also be bound to more than a single protocol at the same time; in particular, a service implementation can be a made accessible locally (when the called service is deployed on the same host as the calling service or other client), and can be simultaneously accessible via JSON/REST from web browsers and/or provided to back-end systems (non-web browsers) via SOAP.

SCA component model

The SCA component meta-model defines a composite as a deployable set of components and service artifacts, and describes how a component is wired to other components of the composite (or to external web service), ie. how a service can access other service by a named service reference rather than by protocol properties such as IP endpoints etc.

The SDO API is a companion API for SCA to uniformly access data passed in and out of service components with (optional) rich and strict typing. The SDO API is based on XML Schema concepts, but abstracts over it so that common data handling scenarios can be implemented easily, such as

  • access to structured data (ie. data which is organized in terms of record- and field-like structures, and where the order of "records" and "fields" relative to each other doesn't matter)
  • access to semistructured data (with XML/DOM- or JSON-array-like access to the sequence in which data objects are presented)
  • dynamically typed data (where data types can be defined at runtime or based on XML Schema).

SDO API

SDO is a library interface for access to structured data objects passed to and from SCA services. SDO can also be used as a stand-alone library, and to hold data passed to and from databases to applications.

SDO data objects are serializable containers for application data with optional run-time type checking based on XML Schema.

SDO provides both a getter/setter API for access to data objects properties by name, as well as a sequence API for access to data object properties by index.

Using SDO with SCA

When a SCA service implementation is invoked, the input request payload is presented as SDO data object to the service implementation, and the service's response, if any, is expected as SDO data object result.

An XML (SOAP or POX) request SDO data object, when supplied to a service implementation, is validated according to the service's XML Schema.

A JSON request SDO data object, on the other hand, isn't pre-validated and hasn't service-specific types assigned when passed to the service implementation. A service implementation, however, can still use SDO to handle typed access to JSON dataobjects by creating types dynamically for the JSON dataobject.

Service development

In this and the subsequent chapters, the SCA and SDO APIs are demonstrated using a "worldclock" example service. The worldclock service is designed to return the time (ie. the hour) in a particular city, given the time in another city. The service expects a reference time, a reference city name (where the reference time is the local time), and the city name to calculate the local time for as parameters.

The focus is on how to develop SDO and SCA services, so the actual calculation of a time difference and lookup of timezone data isn't shown; rather, the service implementation is expected to provide a calculate_time_diff C function externally.

POX/POJSON service

A POX service is a web service that either

  • as a HTTP GET request, takes input parameters encoded in the HTTP request URI, or
  • as a HTTP POST request, takes a XML input

and responds with an XML response.

A POJSON service is accessed like a POX service, but takes and responds with JSON instead of XML.

A POX or POJSON service deployed in sgmljs.net SCA can simultaneously accept/deliver XML and JSON, based on the value of the HTTP Content-Type (for HTTP POST) and Accept header (for HTTP GET).

POX or POJSON services are the most basic web service bindings supported by sgmljs.net SCA, and are designed directly after standard web browser (form GET/POST) facilities.

Unlike a REST service, which puts additional semantics on HTTP methods (and might also support HTTP PUT and DELETE), a POX/POJSON service merely distinguishes between HTTP POST and HTTP GET requests in so far as the former transfer parameters via their body payload, while the latter transfer parameters via their request URI.

A basic worldclock service as a POX service can be implemented in C as follows:

#include <stdio.h>

#include "SDO.h"
#include "SCA.h"

extern int calculate_time_diff(int hour, char *city, char *otherCity);

/**
 * Implementation of worldclock service. 
 */
DATAOBJECT getLocalTimeForCity(DATAOBJECT request) {

	SDOFACTORY df = getDataFactory();

	// get request parameters
	char *requestCity = getCStringByName(request, "city");
	int requestTime = getIntByName(request, "local-time");
	char *otherCity = getCStringByName(request, "city-to-request-time-for");

	// call external function to calculate time at "otherCity"
	int time_diff =
		calculate_time_diff(requestTime, requestCity, otherCity);

	// construct response object
	SDOXML xmlhlp = getXMLHelper(df);
	SDOXMLDOC doc = XMLDocAlloc(xmlhlp, 0, 0, "response");
	DATAOBJECT response = getXMLRootDataObject(doc);

	// populate response
	setCStringByName(response, "city", otherCity);
	setIntByName(response, "hour", time_diff);

	return response;
}

This service implementation can return either XML or JSON (even though it's using XMLHelper); the serialization format will be determined at run time based on HTTP Accept headers (when allowed by the service description; see below).

This implementation doesn't make use of custom XML Schema types to describe request and response data formats; instead, requests and responses are treated as generic anyType data and the implementation populates the response data object using set...ByName() SDO functions to create named properties (city and hour) dynamically.

A WSDL file describing this service as a POX GET service (declaring request and response types as anyType elements along with WSDL messages and message parts) contains definitions such as the following (see POX example for the full example source files):

<wsdl:definitions targetNamespace="http://www.example.com/worldclock.wsdl"
	xmlns="http://www.example.com/worldclock.wsdl"
	xmlns:t="http://www.example.com/worldclock.xsd"
	xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
	xmlns:xs="http://www.w3.org/2001/XMLSchema"
	xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
	xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
	xmlns:sca-c="http://docs.oasis-open.org/ns/opencsa/sca-c-cpp/c/200901">

	<wsdl:types>
		<xs:schema targetNamespace="http://www.example.com/worldclock.xsd"
	           elementFormDefault="qualified">
			<xs:element name="worldclockRequest" type="xs:anyType"/>
			<xs:element name="worldclockResponse" type="xs:anyType"/>
		</xs:schema>
	</wsdl:types>

	<wsdl:message name="worldclockRequest">
		<wsdl:part name="request" element="t:worldclockRequest"/>
	</wsdl:message>

	<wsdl:message name="worldclockResponse">
		<wsdl:part name="response" element="t:worldclockResponse"/>
	</wsdl:message>

	<wsdl:message name="worldclockFaultResponse">
		<wsdl:part name="message" element="xs:string"/>
	</wsdl:message>

	<wsdl:portType name="worldclock-ops">
		<sca-c:bindings>
			<sca-c:enableWrapperStyle>false</sca-c:enableWrapperStyle>
		</sca-c:bindings>
		<wsdl:operation name="getLocalTimeForCity">
			<wsdl:input message="worldclock-request"/>
			<wsdl:output message="worldclock-response"/>
		</wsdl:operation>
	</wsdl:portType>

	<wsdl:binding name="http-binding" type="worldclock-ops">
	<http:binding verb="GET"/>
		<wsdl:operation name="getLocalTimeForCity">
			<http:operation location="getLocalTimeForCity"/>
			<wsdl:input>
				<http:urlEncoded/> <!-- note this is ignored on POST -->
			</wsdl:input>
			<wsdl:output>
				<mime:content type="text/xml"/>
				<mime:content type="application/json"/>
			</wsdl:output>
		</wsdl:operation>
	</wsdl:binding>

	<wsdl:service name="worldclock">
		<wsdl:port name="worldclock-ops" binding="http-binding">
		<!-- ... see SCA examples page for complete definitions ... -->
		</wsdl:port>
	</wsdl:service>

</wsdl:definitions>
http:urlEncoded
is used to indicate that the service should be callable using a HTTP GET request, with service parameters encoded in the HTTP request URL
mime:content

the listed MIME media types are used to indicate that the service should return either an XML or JSON response; the actual response format will be determined by the Accept HTTP header of the request

sca-c:enableWrapperStyle

indicates to the SCA runtime that the service implementation function uses SDO data binding (receives and returns a SDO DATAOBJECT, as required for all services deployed with sgmljs.net SCA)

To deploy the service implementation as an SCA component, the implementation must be compiled into a shared library libworldclock.so, and an SCA composite file similar to the following must be created:

<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
	targetNamespace="http://www.pmsca.com" name="WorldclockComposite">

	<!-- expose worldclock via wsdl/SOAP -->
	<service name="worldclock" promote="worldclock-impl">
		<interface.wsdl
			interface="http://www.pmsca.com/worldclock.wsdl#wsdl.interface(worldclock-ops)"/>
		<binding.ws
			wsdlElement="http://www.pmsca.com/worldclock.wsdl#wsdl.port(worldclock/worldclock-ops)"/>
	</service>

	<!-- register worldclock implementation lib -->
	<component name="worldclock-impl">
		<service name="worldclock"/>
		<implementation.c module="worldclock" library="true"/>
	</component>
</composite>
service

defines a service exposed to clients as web service (service/binding.ws)

service/@promote

routes incoming request for the exposed service to the specified (promoted) component

component

defines a component implementing the worldclock service

component/implementation.c/module

defines the base name of the shared library implementing the service; the effective shared library file name to load is derived as libworldclock.so on POSIX/SUS-like systems, and is interpreted relative to the location of the composite file (eg. relative to xml:base); optionally, a path attribute may be specified to override this; note the SCA stand-alone program implementation model isn't supported by sgmljs.net SCA, so library must always have the value true

To create a deployable contribution archive, the service implementation library, the service description, and the composite file are placed into a ZIP archive file.

Moreover a contribution manifest file describing the content of the contribution archive must be created (and placed into the archive at META-INF/sca-contribution.xml) with the following content:

<?oasis-xml-catalog catalog="catalog.xml"?>
<contribution xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
              xmlns:worldclock="http://www.pmsca.com/worldclock">

	<!-- make component available for deployment/to other components -->
	<deployable composite="worldclock:WorldclockComposite.composite"/>

	<!-- export namespace of composite namespace -->
	<export namespace="http://www.pmsca.com/worldclock"/>

	<!-- export namespaces of wsdl -->
	<export namespace="http://www.pmsca.com/worldclock.wsdl"/>
</contribution>

Note that for sgmljs.net SCA, the contribution manifest must reference an XML catalog file to use for resolving exported namespaces; see the full example and chapter on deployment for an explanation of the role and structure of XML catalogs used by PMSCA).

Summing up, the contribution ZIP file must be named worldclock.zip and contain the following paths and files

META-INF/sca-contribution.xml
META-INF/catalog.xml
...
libworldclock.so
worldclock.composite
worldclock.wsdl

To install the contribution and start a service responding to worldclock request, the sca-install and sca-deploy-domain command line utilities are used:

sca-install worldclock.zip
sca-deploy-domain

To invoke the service from the command line, the curl command line utility can be used as follows:

curl -H 'Accept: text/xml' \
	http://localhost/worldclock/getLocalTimeForCity?city=Berlin&local-time=12&city-to-request-time-for=San+Francisco

(assuming the SCA runtime is listening on the default HTTP port).

The service is expected to respond with:

<response><city>San Francisco</city><hour>21</hour></response>

If a JSON rather than XML response is desired, the following command is executed instead:

curl -H 'Accept: application/json' \
	http://localhost/worldclock/getLocalTimeForCity?city=Berlin&local-time=12&city-to-request-time-for=San+Francisco

to yield a response such as the following:

{"response":{"city":"San Francisco","hour":"21"}}

See POX example for full source and artifacts.

REST services

While the shown action-oriented web service exposes a <service>/<operation> pattern as request URI, for REST services it is often desirable to expose a "resource"-like URI such as http://<host>/<resource> without an operation part, and have the SCA runtime select the operation to invoke based on the HTTP method (ie. GET, POST, PUT, or DELETE).

To achieve this with sgmljs.net SCA, the value of the location attribute on the http:operation element for the respective WSDL binding can be left empty.

Note sgmljs.net SCA will treat this internally as if the dummy URI component had been specified. For this reason, dummy shouldn't be used as either URI component or REST parameter name.

To have requests routed to different implementation functions based solely on a request's HTTP verb/method (ie. GET, POST, etc.) it is necessary to describe this mapping in multiple WSDL HTTP bindings, all of which have the same service (http:address) and empty operation @location values as shown in the following snippet for GET and POST (see SCA examples for full example code and supplementary artifacts):

<!-- port type for HTTP GET -->
<wsdl:portType name="worldclock-ops">
	<sca-c:bindings>
		<sca-c:enableWrapperStyle>false</sca-c:enableWrapperStyle>
	</sca-c:bindings>
	<wsdl:operation name="getLocalTimeForCity">
		<wsdl:input message="worldclock-request"/>
		<wsdl:output message="worldclock-response"/>
	</wsdl:operation>
</wsdl:portType>

<!-- binding for HTTP GET -->
<wsdl:binding name="http-binding" type="worldclock-ops">
	<http:binding verb="GET"/>
	<wsdl:operation name="getLocalTimeForCity">
		<http:operation location=""/>
		<wsdl:input>
			<http:urlEncoded/>
		</wsdl:input>
		<wsdl:output>
			<mime:content type="text/xml"/>
			<mime:content type="application/json"/>
		</wsdl:output>
	</wsdl:operation>
</wsdl:binding>

<!-- port type for HTTP POST -->
<wsdl:portType name="worldclock-post-op">
	<sca-c:bindings>
		<sca-c:enableWrapperStyle>false</sca-c:enableWrapperStyle>
	</sca-c:bindings>
	<wsdl:operation name="getLocalTimeForCity">
		<wsdl:input message="worldclock-request"/>
		<wsdl:output message="worldclock-response"/>
	</wsdl:operation>
</wsdl:portType>

<!-- binding for HTTP POST -->
<wsdl:binding name="http-post-binding" type="worldclock-post-op">
	<http:binding verb="POST"/>
	<wsdl:operation name="getLocalTimeForCity">
		<http:operation location=""/>
		<wsdl:input>
			<http:urlEncoded/>
		</wsdl:input>
		<wsdl:output>
			<mime:content type="text/xml"/>
			<mime:content type="application/json"/>
		</wsdl:output>
	</wsdl:operation>
</wsdl:binding>

<!-- service definition referencing both GET and POST bindings -->
<wsdl:service name="worldclock">
	<wsdl:port name="worldclock-ops" binding="http-binding">
		<http:address location="http://localhost:9090/services/worldclock"/>
	</wsdl:port>
	<wsdl:port name="worldclock-post-op" binding="http-post-binding">
		<http:address location="http://localhost:9090/services/worldclock"/>
	</wsdl:port>
</wsdl:service>

See REST example for full source and artifacts.

SOAP services

For SOAP services, sgmljs.net SCA constructs service endpoint URLs from service names in deployed composites; in the SOAP example the service name is worldclock, the operation is getLocalTimeForCity, and the SCA runtime uses services/worldclock/getLocalTimeForCity as endpoint URL by default.

Endpoint references specified in the WSDL file as values to a soap:address/@location attribute are checked against these rules, but aren't enforced. The soap:operation/@soapAction WSDL attribute isn't used by sgmljs.net SCA.

In addition, the SOAPAction HTTP header, if it isn't empty, can be used to determine an operation name. The SOAPAction header is parsed as an URL such that the last two path steps are interpreted as service and operation name, respectively. When using SOAPAction in this way, the operation URL path step of the request/endpoint URI can be omitted, ie. only needs to contain the service name as last path step. Note that the use of SOAPAction for service and operation routing is considered legacy practice for SOAP; for sgmljs.net SCA, it is recommended to use WS-Addressing instead.

For SOAP 1.1, the SOAPAction HTTP header must be present, but can be specified as the empty string constant '' (two consecutive single quotation marks). For SOAP 1.2, the SOAPAction header isn't required.

For a basic example providing a SOAP service see SOAP example. The example also demonstrates SCA error handling by reporting fault responses.

The example demonstrates a request/response (WSDL in/out) operation; for an operation that doesn't have a service response, the wsdl:output element is omitted in the WSDL.

Service endpoints

Summing up, to determine the service and operation name to route requests to, sgmljs.net SCA attempts to establish a canonical service URI consisting of the URL path step services, followed by a service name as the next URL path step, and optionally, followed by an operation name as URL path step.

The service URI is extracted from the following request data items:

  • the HTTP request URI; when using a HTTP request URI for routing, the services/ prefix isn't required

  • for SOAP with WS-Addressing, the wsa:To and wsa:Action SOAP envelope headers, if present; if a SOAP request contains WS-Addressing headers, these take precedence over other routing information; when using WS-Addressing, the request URI doesn't need to contain a service and/or operation name; it is sufficient to consist just of eg. http://<hostname>/services/

  • the SOAPAction HTTP header isn't used by sgmljs.net SCA for routing; note, however, that a SOAPAction HTTP header must be present for a request to be treated as SOAP 1.1 request

While using the canonical service URI is common for SOAP requests, the common way to expose a REST or POX service endpoint for access by clients over HTTP is by an URI just containing the service name as first path step (followed by the operation name as second path step for POX).

Using WS-Addressing

However, the endpoint address for SOAP services using WS-Addressing is just http://<host>/services and the wsa:To and wsa:Action elements specified in the SOAP header are inspected to determine the service and operation to invoke. URLs used in the wsa:To element must have the canonical service URI, ie. end in services/<service-name>. If using SOAP with WS-Addressing, the SOAPAction header, if present and not empty, is requred to be identical to the value of the wsa:Action element by the WS protocol specifications, but this isn't enforced.

In a SOAP/WSA binding representation of WS-Addressing properties in WSDL it's not possible to specify a WS-Addressing destination (wsa:To) other than the value specified for soap:address/@location for the respective port (the specification text specifically states that custom endpoint reference metadata subelements cannot redefine soap:address/@location).

See the WS-Addressing example for more details.

SDO programming

The shown example code accesses request and response data items via SDO get...ByName()/set...ByName()functions. In the SOAP example, on the other hand, properties are accessed via a SDOTYPE type object (which must be first looked up in a SDOFACTORY data factory object). The types resolvable in the context of the data factory of a service are those that are declared as XML Schema types in the service's WSDL.

Open content

If a looked up type is xsd:anyType or admits element wildcards, (as in the REST example) the get..ByName() and set...ByName() functions can add/replace or read elements by name that aren't declared by the schema.

Multi-valued properties

If a type for a dataobject has a sequence content model, and an element particle of the sequence has maxOccurs="unbounded", then it's treated as multi-valued property and isMany() returns true on the property. A multi-valued property can be manipulated via the setList()/getList() list API.

Validation

For SOAP and POX requests, full XML Schema validation and type assessment is performed, based on the schema(s) declared in the service's WSDL.

Note that this does not enforce that the assessed type (if a type could be assessed at all) is the one expected by the service; it only ensures that the input could be parsed as any element declared in the service WSDL's XML schema allowed as a document element.

At runtime, SDO data access functions provide a limited form of type validation as follows:

  • if a property corresponds to a declared attribute, then the attribute is used to store a value for it in an XML serialization
  • an element property is handled such that it is either inserted before ore appended after existing properties contained in a dataobject, depending on whether the element is supposed to come before or after in the schema type's content model; however, this is only performed when the content model of a type is a plain sequence (ie. not if the content model has choice or another compositor other than the sequence compositor)

  • multi-valued properties are maintained as consecutive elements

SDO JSON mapping

The rules for representing JSON data as a dataobject are based on and compatible with the "mapped" convention established by Java libraries and frameworks for JSON; however, as sgmljs.net SCA doesn't map XML to JSON or vice versa, XML namespaces aren't represented in JSON data.

For JSON objects (hash maps), keys/members are mapped to property names, and values to primitive or compound values. Note that this can result in property names that aren't serializable as XML (e.g. when a key contains a space character).

For JSON arrays, each array value is wrapped into a property occurence of the containing JSON object's key; for example, the JSON object

{ "obj" : { "prop" : [ "value 1", "value 2", "value 3" ] } }

is mapped to an SDO dataobject serialized into XML as follows

<obj>
	<prop>value 1</prpo>
	<prop>value 2</prop>
</obj>

Since JSON arrays are mapped into a sequence, there must be a containing dataobject (a sequence as such isn't a dataobject); therefore, JSON data such as the following (where it isn't part of a larger JSON data string like above) cannot be represented in sgmljs.net SDO and will be rejected:

{ "prop" : [ "value 1", "value 2", "value 3" ] }

sgmljs.net SDO is designed such that service response data objects are automatically serialized to JSON if the request contains application/json as value of the HTTP Accept: header, without having the service implementation to handle JSON explictly or otherwise special.

For parsing and serializing JSON data programmatically, sgmljs.net SCA also provides the JSONHelper extension API.

For further information, see the SCA/SDO API documentation.

Service assembly

Deployment and wiring of services is accomplished by publishing one or more contribution archives (ZIP archives) to a sgmljs.net SCA domain. The archive contains compiled object files as implementation artifacts and also SCA artifacts (XML files) describing how implementation artifacts should be called and configured by the runtime. In particular, services that call other services are configured with references to the services to call (which could be running on the same machine as the calling service, or could be provided remotely at another machine).

Note: SCA service assembly makes extensive use of XML techniques for composition and resolution of contribution artifacts; the description of the assembly process below might be easier to follow when also studying the shell and XSLT script sources used to implement sgmljs.net SCA service assembly and deployment for reference

Service references

A SCA service implementation can invoke other services deployed in the same SCA domain (or as an external web service). To inject (eg. make available for lookup by name via the SCAGetReference routine) a service reference into a component, the .composite file needs to contain reference child elements for the component; at runtime, the service reference is resolved (wired) to the component providing the desired service as explained in the next chapter.

For example, a "multiworldclock" service capable to return local times for more than a single city could be implemented by performing multiple calls to the worldclock implementation demonstrated above. A .composite file wiring the base worldclock service implementation to the multiworldclock service will contain definitions similar to these:

<!-- expose base worldclock locally -->
<service name="worldclock" promote="worldclock-impl">
	<interface.wsdl interface="http://www.pmsca.com/worldclock.wsdl#wsdl.interface(worldclock-ops)"/>
	<binding.sca/>
</service>

<!-- expose multiworldclock via SOAP -->
<service name="multiworldclock" promote="multiworldclock-impl">
	<interface.wsdl interface="http://www.pmsca.com/multiworldclock.wsdl#wsdl.interface(multiworldclock-ops)"/>
	<binding.ws wsdlElement="http://www.pmsca.com/multiworldclock.wsdl1#wsdl.port(multiworldclock-ops)"/>
</service>

<!-- worldclock impl -->
<component name="worldclock-impl">
	<service name="worldclock"/>
	<implementation.c module="worldclock" library="true"/>
</component>

<!-- multiworldclock impl (aggregates worldclock service) -->
<component name="multiworldclock-impl">
	<service name="multiworldclock"/>
	<implementation.c module="multiworldclock" library="true"/>
	<reference name="worldclock" target="worldclock-impl/worldclock">
		<binding.sca/>
	</reference>
</component>

The binding.sca element indicates, to the runtime, that the service is available for other services in the domain, but isn't bound to a web service endpoint. Technically, this service is invoked via a subroutine call, without serializing and/or deserializing of message payloads, and without using network or other interprocess communication.

For comprehensive example implementation code where a worldclock service implementation invokes a base service placed into a single service contribution, see the service aggregation example.

This example also demonstrates the need to resolve a WSDL file for the service being called in order to determine soap:address/@location and WS-A action details.

The address of the remote service to call is discovered by resolving the reference to the worldclock service. The relevant portion of the composite file is as follows:

<reference name="worldclock">
	<binding.ws port="http://www.example.com/worldclock.wsdl#wsdl.port(worldclock-service/worldclock-ops)"/>
</reference>

To map http://www.example.com/worldclock.wsdl to a locally accessible file, the WSDL URI is resolved using an XML catalog established by SCA domain management tools (see next chapter).

The content of that file is then examined to provide addressing details (eg. SOAPAction and/or WSA Action), as well as an endpoint URI (in soap:address/@location).

Contribution manifest

A contribution must contain a contribution manifest named META-INF/sca-contribution.xml within the archive. The contribution manifest can contain

  • export elements for making available files (WS-* and/or SCA artifacts) provided by the contribution to other contributions; the files are made available via export namespaces

  • import elements for importing namespaces; importing a namespace is performed by modifying resolution rules of importing contributions to locate WS-*/SCA artifacts

  • deployable elements for putting a .composite file into a deployed state when processing the contribution

.componentType vs .composite files

A .componentType file is meant to be packaged along with a service implementation. It's used only as a "side file" when the implementation technology/environment for the service doesn't have native mechanisms for discovering service metadata from deployable artifacts. According to http://stackoverflow.com/questions/23611080/whats-the-use-of-the-component-type-file-in-sca it's not even supported for Java contributions in the SCA 1.1 specification, and the SCA runtime is supposed to extract equivalent information from eg. JAXB metadata.

A .composite file, on the other hand, contains or represents a deployed SCA domain. It has the same structure as a .componentType file. A SCA runtime will take runtime metadata info from the (virtual) .composite file, and fall back to implementation-declared metadata from a .componentType file if present.

Note that in sgmljs.net SCA, .componentType files aren't supported; instead, only .composite files are recognized. Where a reference to a componentType is required for validation of composite files, the empty string should be placed into the composite file.

sca:include element in a composite file

A SCA .composite (or .componentType) file can contain sca:include XML elements. The general semantics for sca:include is that the sca:include element gets replaced lexically by the referenced content:

  • the referenced content must ultimately resolve to an XML file having a sca:composite or sca:componentType element as document element

  • the sca:include element is replaced by the child content of the document element of the referenced .composite or .componentType file

  • .composite or .componentType files to include are referenced by qualified name rather than file location. The namespace of the qualified name must resolve to a namespace known to the SCA domain (ie. being exported by a contribution), and the localname of the qualified name must match the @name attribute of the contribution.

Exporting and importing file and namespaces

The role of import elements and import catalogs is to provide a contribution-local view to domain-globally provided resources: since resources are imported based solely on namespaces (which are made globally visible in matching exports), all configured contributions of a domain ultimately reference the same files given a partiular namespace URI; import configurations, however, might differ between contributions

  • in the location/schemaLocation URI under which an imported resource is made available to resolution processes within the importing contribution

  • in whether a namespace is imported at all; if a particular namespace isn't imported, then location/schemaLocation are resolved relative to the contribution

Operations on a SCA domain

The Install a contribution operation stages artifacts and make the involved namespaces available for reference from other contributions.

Deploy a constribution and adding a composite to the set of domain-level operations puts a previously installed composite's service(s) into the set of services offered by the SCA domain to outside clients, and wires components required by the deployed components

The SCA assembly specification makes mention of the operation of adding a composite to the domain-level composte and describes its semantics in terms of the sca:include operation. In sgmljs.net SCA, a composite is added to the domain-level composite (ie. deployed as a running service) by placing a <deployable> element naming the composite to deploy in a contribution manifest file.

Deployment and wiring details

Assembly of a SCA domain is implemented transparently via XML catalog construction and manipulation techniques as follows

  • exported namespaces from contributions get collected into a contribution export catalog; a domain-global catalog is maintained which delegates to the respective contribution export catalog on the respective exported namespace as URI suffix
  • namespace imports are mapped into contribution import catalogs; rules in the import catalog map location URIs (relative file paths) to files in the respective export contribution, as obtained by resolving the import namespace URI against the domain export catalog
  • the domain composite is created as a composite file containing inclusions pointing to deployed contribution composites; included composites are processed in the contribution's a catalog context

Installation

For each export element in the contribution manifest

  • a contribution export catalog is created, containing rules to map exported URIs to contribution-provided resources; the contribution export catalog is constructed by filtering only those rules from the contribution manifest's catalog resolving exported namespaces

    • the target of an exported URI is (attempted to be) resolved, using the contribution manifest's catalog, as determined by the ?oasis-xml-catalog? processing instruction

    • if an exported URI is mapped via a delegateURI rule in the contribution manifest's catalog, it is treated as a composite namespace; entries of this form are used to resolve import QNames for composite files at import processing time later on by constructing a lookup URI to resolve from appending the local name to the exported namespace

    • otherwise, it is expected to be mapped in an uri rule in the contribution manifest's catalog, and must resolve to a file contained in the contribution; entries of this form as used to resolve XSD and WSDL files imported by other contributions

  • the contribution export catalog is added to the domain catalog (using a nextCatalog rule)

Import processing

At configuration time, after exports for all installed contributions have been processed, the domain catalog is used to create a contribution import catalog for every installed contribution from the contribution manifest's import rules by resolving the namespace URI to import using the domain catalog.

location QNames in include elements in the domain composite file get expanded into inclusions of the file resolved by the namespace URI of the QName, with the local name appended as final path step in the domain catalog; these will be resolved by delegateURI rules in an exporting contribution's export catalog (and then ultimately by the delegated-to catalog) as described above

Domain deployment

After processing imports, deployed composites (those in deployable elements from installed contributions) and their services are deployed by iterating over the domain composite containing the included composites and by performing the following operations:

  • change sca:include into xi:include elements, rewriting the included composite's namespace and name into an URI

  • invoke XInclude expansion using the domain catalog; the domain catalog will map composed namespaces from the step before into .composite files in installed contributions, using delegate/nextCatalog rules placed into the domain catalog at contribution install (export processing) time

  • run schema validiation starting from WSDLs referenced from included composites XInclude processing will have adjust xml:base on included domain composite fragments, the relative paths used by wsd/xsd imports in which get resolved by delegation to a contribution's local catalog on the contribution namespaces as prefix
  • perform validation on the expanded domain composite file
  • wire service references if necessary (see below)
  • deploy services by checking, and copying required WSDL files to the service directory

Wiring

In this step, performed as part of domain deployment, service references in components get configured to use other components providing the required service as expressed by the service's WSDL.

Wiring produces a result composite file from an input composite that has wired and normalized "target" attributes for all service references of all components (or produce an error message indicating why it isn't possible to satisfy a particular service reference) by extending the input composite file as follows:

  1. only those components are considered which have false as the effective value of the wiredByImpl attribute (which is the default); of those, only component references are considered which don't have a binding child element specified

    • that is, only component reference either having no target attribute specified, or which have a target attribute specified and have either true as value of the nonOverridable attribute specified, or which are wired by a composite-level wire element

  2. service references which are targeted by a composite-level promote attribute (irrespective of whether already qualified with a target attribute) are overridden by the promoted source reference, unless the component reference has nonOverridable true (per default this value is false)

    • note this is about promote attribute placed on a composite-level reference element (which pushes a reference down to a component) rather than a service element (which pulls a service from a component up to the composite)

  3. on service references which are targeted by a wire element, and if the wire element has true as value of the replace attribute (which it hasn't by default), the target element is regenerated to reflect the wire source (irrespective of whether already qualified with a target attribute, ignoring the value of nonOverridable)

  4. otherwise, for service references that have a target attribute specified, the target attribute is checked, normalized, and reproduced

  5. for service references that are neither qualified by a target attribute or binding subelement, nor targeted by a promote or wire element, if the autowire attribute is true on the associated reference, component, or composite, a blank target attribute is produced (reference elements having a blank target attribute are eg. picked up for autowiring in the next step)

  6. (autowire) for any component reference that hasn't a non-empty target attribute nor an embedded binding element at this point, an attempt is made to find a provided service by a match on the interface attribute of the interface.ws element on the reference and on the interface.wsdl element on a component service

Runtime catalog resolution

At runtime, imported namespaces can be used in a contribution

  • (in XML Schema files) in schemaLocation attributes on import or include elements; the applicable schemaLocation values are resolved against the contribution import catalog,

  • (in WSDL files) in location attributes on import elements; these are resolved identically to schemaLocation attribute values