Introduction
Service Component Architecture (SCA) is a collaborative effort by the leading vendors in the enterprise software space to define an architecture for building applications and systems using a Service-Oriented Architecture (SOA).
SCA encourages an organization of business application code based on components that implement business logic and offer their capabilities through service-oriented interfaces called services and which consume functions offered by other components through service-oriented interfaces, called references. SCA divides up the steps in building a service-oriented application into two major parts:
- The implementation of components which provide services and consume other services
- The assembly of sets of components to build business applications by connecting references to services.
SCA emphasizes the decoupling of service implementation and of service assembly from the details of infrastructure capabilities and from the details of the access methods used to invoke services. SCA components operate at a business level and use a minimum of middleware APIs.
SCA supports service implementations written using any one of many programming languages such as Java™, PHP, C++, COBOL. SCA also supports a range of programming styles, including asynchronous and message-oriented styles, in addition to the synchronous call-and-return style.
SCA supports bindings to a wide range of access mechanisms used to invoke services. These include Web services, messaging systems and CORBA IIOP. Bindings are handled declaratively and are independent of the implementation code.
Infrastructure capabilities, such as Security, Transactions and the use of Reliable Messaging are handled declaratively and are separated from the implementation code. The SCA Policy Framework describes the way in which these infrastructure capabilities are handled, through the use of intents and policySets which are designed to simplify the mechanism by which the capabilities are applied to business systems.
In SCA, services and references can have policies applied to them that affect the form of the interaction that takes place at runtime. These are called interaction policies. Service components can also have other policies applied to them which affect how the components themselves behave within their runtime container. These are called implementation policies. Both interaction policies and implementation policies use intents and policySets (discussed below) in essentially similar ways.
Intents
In SCA, intents are used to describe abstract policy requirements. Intents provide a means for the developer and the assembler to state requirements in a high-level abstract form, independent of the detailed configuration of the runtime and independent of the technology used to implement the requirements. Intents can be attached to any SCA construct. SCA constructs are specified as XML elements and intents are attached as attributes on those elements. Intents can also be attached to interface declarations and intents can also be attached to program code by means of annotations in some programming languages such as Java.
At deployment time, intents are translated into concrete policies. Although policies can also be attached directly to SCA constructs, SCA recommends a late binding model where the bindings and the concrete policies for a particular assembly are decided at deployment time. Late binding promotes re-use of components. It allows the use of components in new application contexts which may require the use of different bindings and different concrete policies. Forcing early decisions on which bindings and policies to use is likely to limit re-use and limit the ability to use a component in a new context.
For example, a service which requires its messages to be authenticated can be marked with an intent "authentication". This marks the service as requiring message authentication capability without being prescriptive about how it is achieved. At deployment time, when the binding is chosen for the service (say SOAP over HTTP), the deployer can apply suitable policies to the service which provide aspects of WS-Security (say) and which supply a group of one or more authentication technologies.
Developers who want a little more control over the policies that are applied can use qualified intents. Assume that the intent "confidentiality" comes in two flavors: transport and message. Or it may be qualified by technology: X509 or Kerberos. A developer who uses an unqualified intent is saying, in effect, "use any flavor you wish" while a developer who uses a qualified intent is specifying, in more detail the desired facility. The pseudo-schema for defining an intent is:
<intent name="xs:QName" constrains="list of xs:QNames" ? requires="list of xs:QNames" ? > <description> <!-- description of the intent --> </description> </intent>
SCA provides a set of basic intents, but the set of intents available to developers and assemblers can be extended arbitrarily by policy administrators. The definition of each intent specifies the SCA element it applies to by including the element in the @constrains attribute of the intent.
The example below shows how an intent can be attached to a service. In the example, the service requires "confidentiality". This applies to any binding selected for the service. Since no further requirements are placed on the intent, the deployer is free to choose whatever policy he sees fit to implement confidentiality.
<service name="myService" requires="confidentiality"/>
PolicySets
PolicySets are XML elements that encapsulate concrete policies. PolicySets can be attached directly to SCA constructs: typically they are used to determine the policies that satisfy specified intents at deployment time.
In the simplest case, a policySet declares the binding that it applies to and the intent for which it provides policies. The policySet contains a policy, which may be expressed as a WS-Policy or in some other policy language (depending on the target binding):
<policySet name="acme:CorporateSecurityPolicy" provides="acme:security" appliesTo="sca:binding.ws" xmlns="http://www.osoa.org/xmlns/sca/1.0" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"> <wsp:Policy> <!-- policy expression and policy subject for --> <!-- "corporate security policy" --> ... </wsp:Policy> </policySet>
In more complex cases, a policySet can satisfy more than one intent and can also satisfy intents that are qualified. Such policySets contain within them one intentMap for each intent that they satisfy. The intentMap contains policies for the various flavors of the intent, with one flavor being marked as "default".
The example below shows a policySet that satisfies a single intent but provides two alternative policies for that intent and identifies one of the alternatives as default.
<policySet name="acme:SecureMessagingPolicies" provides="confidentiality" appliesTo="binding.ws" xmlns="http://www.osoa.org/xmlns/sca/1.0" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"> <intentMap provides="confidentiality" default="transport"> <qualifier name="transport"> <wsp:PolicyAttachment> <!-- policy expression and policy subject for "transport" alternative --> ... </wsp:PolicyAttachment> <wsp:PolicyAttachment> ... </wsp:PolicyAttachment> </qualifier> <qualifier name="message"> <wsp:PolicyAttachment> <!-- policy expression and policy subject for "message" alternative" --> ... </wsp:PolicyAttachment> </qualifier> </intentMap> </policySet>
PolicySets can also be attached directly to SCA elements. For example:
<service name="myService" policySets="acme:SecureMessagingPolicies"/>
In this case, the default, confidentiality.transport, policy would be selected (assuming there are no @requires attributes specified on the ancestor elements.) PolicySets and intents can be attached together to SCA elements. For example:
<service name="myService" policySets = "acme:SecureMessagingPolicies" requires = "confidentiality.message"/>
When policySets and intents are used together in this manner, the intents are used to override the defaults in the policy set. So, in this case, the confidentiality.message policy would be selected from the policy set.
Bindings
In SCA, binding types implement particular communication mechanisms for connecting components together. Some binding types may realize intents inherently by virtue of the kind of protocol they use (e.g. an SSL binding would natively support confidentiality). For these kinds of binding types, it may be the case that using that binding type, without any additional configuration, will provide a concrete realization of a required intent. In addition, binding instances which are created by configuring a bindingType may be able to provide some intents by virtue of its configuration.
The pseudo-schema for defining binding types in SCA is:
<bindingType type="xs:QName" alwaysProvides="list of intent QNames"? mayProvide = "list of intent QNames"?/>
where the value of the alwaysProvides attribute is the list of intents inherently provided by the binding and the value of the mayProvide attribute is a list of intents the binding type can be configured to provide.
Implementation Policies
Intents and policySets can also be attached to implementations.
Just as bindings can natively satisfy intents for interaction policies, implementations can natively satisfy some intents while other intents can be satified by configuring the implementation in a particular way. Thus, the framework for interaction policies and for implementation policies is the essentially the same.
Here is an example of a component that has a policySet attached to it that allows users with role "customer" to access the component.
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" name="AccountService"> <component name="AccountServiceComponent">* <implementation.java class="services.account.AccountServiceImpl" policySets="acme:allow_customers"/> </component> </composite>
To specify authorization policies we define a policyAssertion called <allow> that can be embedded directly within a policySet. The following is what the policySet definition would look like:
<policySet name="acme:allow_customers"> <allow roles="customers"> </policySet>
Determination of Policies at Deployment Time
As we have discussed, intents and policySets can be associated with an SCA element at any level. Further, some intents can be satisfied based on the binding or the implementation. At deployment time, this information is used to determine the concrete policies that are associated with SCA components. What follows is a somewhat simplified explanation of the steps by which the actual policies are computed.
First, compute the set of required intents that applies to the SCA element. To do this, start with the list of intents specified in the element's @requires attribute. Then, add intents found in the @requires attribute of each ancestor element. Remove any intents that do not include the target element's type in their @constrains attribute. If the set of intents includes both a qualified version of an intent and an unqualified version of the same intent, remove the unqualified version from the set.
Next, remove all directly supported intents from the required intent set. Directly supported intents are intents that are provided by the binding either inherently or by virtue of configuring the binding type. Or they are intents satisfied in the same way by the implementation type.
The remaining intents must be specified by policies from available policySets. To accomplish this, start with the list of policySets specified in the element's @policySets attribute. If any of these explicitly listed policySets does not apply to the target element (binding or implementation) then the composite is invalid. Include the values of @policySets attributes from ancestor elements. Remove any policySet where the policySet's @appliesTo attribute does not match the target element. It is not an error for an element to inherit a policySet from an ancestor element which doesn't apply. Remove all required intents that are provided by the specified policySets (i.e. all intents from each policySets' respective @provides attribute.)
The remaining required intents, if any, must be provided by finding additional matching policySets within the SCA Domain. Choose the smallest collection of these policySets that satisfy all remaining required intents.
A policySet satisfies a required intent if any of the following are true:
- The required intent matches a @provides intent in a policySet exactly.
- The provides intent is a parent (e.g. prefix) of the required intent (in this case the policySet must have an intentMap entry for the requested qualifier)
- The provides intent is more qualified than the required intent
All intents should now be satisfied.
If no collection of policySets covers all required intents, the configuration is not valid.
If there is not one unique smallest collection of policySets that satisfy all required intents, then the composite definition document is not valid. The composite definition must be changed so that either it has enough explicit policySets declared that the ambiguity is removed or additional intents are added to remove the ambiguity.
Summary
SCA simplifies the application of infrastructure services such as Security and Transactions. It does this by applying them declaratively, outside the business code of service components, through the use of intents and policySets attached to elements within SCA composites.
The intents are abstract requirements that are used to select appropriate bindings and required policySets. PolicySets contain concrete policies which can be applied to bindings and implementations.
References
[1] Service Component Architecture specifications
http://www.osoa.org/display/Main/Service+Component+Architecture+Specifications![]()
[2] Web Services Policy (WS-Policy)
http://www.w3.org/TR/2006/WD-ws-policy![]()
[3] Web Services Policy Attachment (WS-PolicyAttachment)
http://www.w3.org/TR/2006/WD-ws-policy-attachment![]()
[4] XML Schema Part 2: Datatypes Second Edition
XML Schema Part 2: Datatypes Second Edition, Oct. 28 2004.