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 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
SCA components provide services via service bindings. sgmljs.net SCA can provision services using one of the following binding types:
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.
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
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.
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.
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.
A POX service is a web service that either
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
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.
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.
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.
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).
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.
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.
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.
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.
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:
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)
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.
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
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
).
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.
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
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.
Assembly of a SCA domain is implemented transparently via XML catalog construction and manipulation techniques as follows
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)
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
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
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:
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
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)
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
)
otherwise, for service references that have a target
attribute
specified, the target
attribute is checked, normalized, and
reproduced
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)
(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
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