5. Composition

The last two chapters focused on the SCA programming model; in this chapter, we take a closer look at how applications are assembled using composites. Here we introduce another key concept, composition. In short, composition is the capability to build larger components and services from a series of smaller ones. The power of composition is that it provides a mechanism for more easily maintaining and evolving applications over time by making them more modular. With composition, sets of services encompassing various functional areas of an application can be more easily reused, upgraded, replaced, and changed. After working through this chapter, you will have a solid foundation in how composites are used to achieve a modular application design.

Composition

Most modern programming languages and models support some form of encapsulation. That is, they have constructs for breaking down parts and isolating them from one another. Modern programming languages and models also have mechanisms for reuse. Object-oriented languages are often designed around interfaces and classes, which serve both functions. SCA has services and components.

Up to this point, we have discussed how services and components provide reuse and encapsulation in several ways. First, services provide a way for multiple clients to address and invoke a unit of code contained in a component. Services also provide encapsulation as they hide implementation details from clients. Component implementations may be reused multiple times, potentially with different property values and wiring.

For many applications, this level of reuse and encapsulation is sufficient. However, as an application becomes more complex and the number of components grows, the need may arise to encapsulate sets of components that expose a few services. A credit appraisal process may be composed of multiple components but needs to expose only one service to its clients. Here, the fact that the credit appraisal process is handled by multiple components is an implementation detail; in the future, these “internal” components and their wiring may change.

In addition, as system complexity grows, the need may arise to reuse not just single components, but sets of components. Perhaps a group of components together perform an operation such as validating and persisting an employee record to a database. It would be beneficial to reuse this set of components as a single unit across a number of disparate applications, hiding the details of the components from clients. It would also be useful if there were facilities for making slight configuration changes to the components as a whole, rather than modifying the individual components.

To handle these cases—encapsulation and reuse of multiple, related components—SCA supports composition, or the capability to assemble larger components from smaller ones. SCA does this in a very simple but powerful way. Consider the visual representation of encapsulation shown in Figure 5.1.

Figure 5.1 Encapsulating three components

image

The composite contains four components, three of which interact to provide a service to the fourth. A component that performs credit scoring may use data validation and auditing components. These details should be hidden from clients using the credit-scoring service. A solution to this problem would be to allow components to be composed from other components like building blocks. We can modify the previous diagram to include this “composite” component, as illustrated in Figure 5.2.

Figure 5.2 A composite component

image

The composite component encapsulates the three components and their wires by exposing a single service to clients. SCA takes this a step further and makes the composite itself a type of component. In other words, composites are a component implementation type just like Java, BPEL, or C++. Our earlier diagram can now be represented as a series of nested components (see Figure 5.3).

Figure 5.3 Nested composite components

image

Because composites are just a particular type of component, they can also be reused like other components. As we explain in the next sections, composites can have services, references, and properties that are configured in their parent composite. We now look at how to use a composite as a component implementation.

The Composite Implementation Type

Suppose the previous credit-scoring function performed by the loan application involved a multistep process consisting of data validation, score calculation, and producing an audit record for legal compliance. This may best be architected using four components: one that functions as a central coordinator (the CreditComponent) and delegates to the other services; one that performs data validation (the ValidationComponent); one that serves as a scoring engine (the ScoringComponent); and one that writes audit messages to a log (the AuditingComponent). CreditServiceComposite, shown in Listing 5.1, assembles these four components.

Listing 5.1 The Credit Service Composite

image

We could have chosen to include these four components in the original LoanApplication composite. However, as the application grows, that strategy will likely result in a brittle and difficult-to-maintain system. In the future, all or part of the credit-scoring components may need to be changed. In addition, configuring all components in one composite is likely to result in a very unstructured application that is difficult to decipher (not to mention developers stepping on one another as they modify parts of the single composite).

Instead, good design suggests that we encapsulate the credit-scoring function in a composite, which is then used as a component by the LoanApplication composite. Figure 5.4 depicts this visually.

Figure 5.4 Encapsulating the credit-scoring process

image

The SCDL in Listing 5.2 configures LoanComponent and CreditComponent.

Listing 5.2 The Credit Score Composite SCDL

image

The key part of the preceding SCDL is the use of the <implementation.composite> element. This instructs the SCA runtime to use a composite as the component implementation, just as if we had specified <implementation.java> or <implementation.bpel>. However, instead of referencing the class name, we refer to the fully qualified name of the composite using the “name” attribute. The fully qualified name, or QName, consists of the target namespace and name of the composite. This is equivalent to specifying the package and class name for Java implementation types.

Composite Qualified Names

It is worth highlighting one of the subtleties associated with using composite qualified names for <implementation.composite>. Namely, the QName does not need to correspond to a particular file location or composite filename. The QName is only a logical name. The CreditComposite could be defined in a file named CreditComposite.composite located in the META-INF directory of a jar contribution. (Recalling from Chapter 2, “Assembling and Deploying a Composite,” composites are packaged into contribution archives for deployment.) Or the composite could be located in some other directory or defined in a file named credit.composite.

Regardless of the filename or location, the SCA runtime is responsible for mapping the QName specified in <implementation.composite> to the actual composite SCDL. This makes assembly less susceptible to breaking during refactoring. The filename or location could change, and the assembly would continue to work. All that is required is that the QName must uniquely identify one composite within the contribution.

In addition, as we mentioned in Chapter 2 and will discuss in more detail in Chapter 9, “The Domain,” composites may be reused from other contributions. By referring to composites using their QName, the client or importing contribution need not be aware of the internal structure of the contribution providing or exporting the composite.

Service Promotion

The next step in encapsulating the credit-scoring process is to expose the CreditService from the CreditComposite. Exposing—or as SCA terms it, promoting—a service in a composite serves two purposes. It allows other references from outside the composite to be wired to it. It also provides a mechanism for the service to be configured by the composite using it as an implementation. We discuss each of these in turn.

Services are promoted using the <service> element in the composite, as demonstrated in the SCDL fragment in Listing 5.3.

Listing 5.3 Service Promotion

image

The <service> element configures a composite service by setting its name and identifying a service to promote via the promote attribute. In the example, the CreditService provided by the CreditComponent is promoted. Because the CreditComponent implements only one service, we could have omitted explicitly identifying the CreditService and written promote="CreditComponent".

Wiring to the CreditService provided by the composite is done like wiring to any other service (see Figure 5.5).

Figure 5.5 Wiring to a promoted service

image

In SCDL, wiring is done as shown in Listing 5.4.

Listing 5.4 The SCDL for Wiring a Promoted Reference

image

The wire defined in the previous SCDL connects the creditService reference of LoanComponent just like any other component, thereby hiding internal implementation details.

The Performance Implications of Composition

In the primary example for this chapter, we have been demonstrating how to encapsulate the credit-scoring function of the BigBank loan application as a composite. By creating a separate credit-scoring composite and using it as a component, we are better able to hide the implementation details of the credit-scoring service. Composition—the process of creating components from composites that in turn assemble smaller components—leads to more robust application architectures and makes applications easier to maintain.

You may be wondering about the runtime performance implications of composition. Specifically, does wiring to a composite service, which promotes a service on a contained component, introduce an extra invocation hop when servicing a request? For example, when the LoanComponent invokes the CreditService, does the call flow first to the promoted service on the composite and then to the service on the contained component (as depicted in Figure 5.6)?

Figure 5.6 Do promoted services require two hops?

image

The short answer is that, in a good runtime implementation, there should be absolutely no negative performance impact. This is because the runtime can optimize away the composite service and connect the two components directly. For example, Fabric3 will flow a call directly to the target service, as shown in Figure 5.7.

Figure 5.7 Optimizing the promoted service hop away

image

Because composite services are optimized away by the SCA runtime, composition can be used without fear of negatively impacting runtime performance with extra invocation hops.

Service Bindings

Composite services have all the characteristics of a component service, including the capability to be bound to a particular remote communications transport. In Chapter 2, we described how to expose the LoanService as a web service via the SCA web services binding (see Listing 5.5).

Listing 5.5 Binding a Service as a Web Service Endpoint

image

Binding the LoanService using <binding.ws> instructs the runtime to make the service available as a web service endpoint for external clients.

If BigBank also wanted to expose the CreditService as a web service endpoint, the corresponding SCDL for the composite component would look the same (see Listing 5.6).

Listing 5.6 Binding a Composite Service as a Web Service Endpoint

image

Recalling that the CreditComposite promoted the CreditService from the CreditComponent, look at Listing 5.7.

Listing 5.7 The Promoted Service

image

The SCDL in Listing 5.8 instructs the SCA runtime to bind the CreditService provided by the CreditComponent as a web services endpoint.

SCA also allows bindings to be specified on a promoted service inside a composite. Instead of specifying <binding.ws> on the composite component, the prior example could be recast as that shown in Listing 5.8.

Listing 5.8 Specifying a Binding on a Promoted Service Inside a Composite

image

The component that uses the composite could be recast, as shown in Listing 5.9.

Listing 5.9 The Binding Information Is Not Set When Using the Composite from Listing 5.8

image

The SCDL in Listing 5.8 also instructs the SCA runtime to make the CreditService available as a web service endpoint. However, it is subtly different than the previous example. Specifying the binding on a composite service will apply to all uses of the composite. In contrast, specifying the binding in the component configuration will only apply to the specific component. For example, if the CreditComposite were reused several times, multiple CreditService endpoints would be activated.

Reference Promotion

Components implemented by composites can also have references that are wired to services. Similar to a composite service, a composite reference is created by promoting the reference of a contained component. The earlier version of the credit score component contained an auditing component. It is likely that this auditing capability will be needed by other components and is therefore a good candidate to be refactored into a generalized service used by the various loan application composites. Refactoring the auditing component can be done by moving it to the parent LoanApplication composite, as shown in Figure 5.8.

Figure 5.8 A wired composite reference

image

Figure 5.8 also demonstrates how reference promotion is used to wire from a component contained in the credit score component to the auditing service. In SCDL, reference promotion is done using the <reference> element (see Listing 5.10).

Listing 5.10 Reference Promotion

image

The <reference> entry creates a composite reference that promotes the auditService reference on the CreditComponent. When the CreditComposite is used as a component implementation, this reference must be wired to a service as done in the SCDL in Listing 5.11.

Listing 5.11 Wiring a Promoted Reference

image

In a slightly more complex scenario, a promoted reference may be wired to a promoted service. This is shown in Figure 5.9, which changes the AuditComponent to be implemented by a composite containing two components.

Figure 5.9 Wiring from a promoted reference to a promoted service

image

Take the audit composite SCDL shown in Listing 5.12.

Listing 5.12 The AuditComposite

image

The wiring to the audit service would remain the same as in Listing 5.11. The only difference would be the substitution of <implementation.composite> for <implementation.java> (see Listing 5.13).

Listing 5.13 The Revised LoanApplication Composite

image

More on Runtime Performance Optimizations

We have already mentioned that wiring to a promoted service should not result in a negative impact on performance. This is because runtimes can optimize composite services away and connect references directly to services provided by components contained in the composite.

The same optimization can be performed when wiring a promoted reference to a promoted service. The current example where we wire from the promoted auditService reference to the promoted AuditService service can be reduced to a single connection by an SCA runtime. Fabric3, for instance, will create the connection shown in Figure 5.10.

Figure 5.10 Optimizing the wire from a promoted reference to a promoted service

image

As we see in the diagram, an efficient SCA runtime replaces the series of wires defined in SCDL with a single wire that flows a call directly to the service provider.

Reference Bindings

In Chapter 1, “Introducing SCA,” we discussed how references can be bound to a particular communication protocol. This is typically done when a component requires a service that is external to the SCA domain. (Perhaps it is a web service not written using SCA.) For example, a component may be dependent on an external web service that provides interest rates, as shown in Listing 5.14.

Listing 5.14 Binding a Reference

image

The <binding.ws> element configures the reference to connect to the web service endpoint located at http://www.bigbank.com/rateService. Invocations from the component will be dispatched via web services to the endpoint by the SCA runtime.

Because composite references are like any other component reference, they may also be bound. And, as with composite services, the binding may be configured either in the composite SCDL or as part of the composite component configuration. We look at both examples in turn.

Listing 5.15 demonstrates binding the rateService reference using promotion—it is almost identical to the previous example.

Listing 5.15 Binding a Promoted Reference

image

Alternatively, if we wanted to configure the binding as part of the composite component configuration, we would first remove the binding from the promoted the reference, as shown in Listing 5.16.

Listing 5.16 The Promoted Reference

image

Then we’d configure the composite component reference, as shown in Listing 5.17.

Listing 5.17 Binding a Composite Reference as Part of the Composite Component Configuration

image

It is important to bear in mind that binding a promoted reference (as represented by Listing 5.15) and binding the reference as part of the composite component configuration (Listing 5.16 and Listing 5.17) are not the same. The SCDL in Listing 5.15 will bind the reference for every use of the composite as a component implementation. In contrast, the SCDL in Listing 5.16 leaves the binding open. In other words, the binding may be changed each time the composite is used as a component.

Perspective: Use Bindings Only at the Domain Level

SCA provides several ways to configure bindings. At times, it may not always be apparent which alternative is best. In most cases, a simple rule can be applied: Even though bindings may be specified on references of encapsulated components—don’t do it. Specify bindings only on references of the components in the top-level composite (that is, the composite being deployed into the SCA domain) and avoid doing so on components of nested composites.

It is okay to specify bindings on the composite-level references of nested composites, but they should be considered to be just hints, because they can be overridden.

Specifying component reference bindings only at the top-level composite brings several advantages. First, it allows bindings to be changed as late as deployment. Second, it places all endpoints provided by the SCA domain and dependencies on services outside the SCA domain at the same level, so they are easier to visualize and manage.

Figure 5.11 demonstrates using promotion to bind two services and two references in top-level composites.

Figure 5.11 Binding two services and references in the top-level composite

image

A complaint that could be raised against this approach is that promotion is more verbose than simply inlining the binding configuration directly in the component definition. In this case, it is important to remember that binding a service or reference without promoting it is essentially “hardcoding” an endpoint. As with code, hardcoding can save time initially but be costly when a change is needed after an application has gone into production.

Consider the preceding example. If the services or references were directly bound in the two inner components and they were not promoted, there would be no way to change them without changing the two composite SCDLs. This would involve a modification to the application and redeployment.

In contrast, if the bindings are set in the top-level composites, they can be modified without altering the inner composite SCDLs. In fact, some SCA runtimes may allow these modifications to be done without requiring a redeployment.

Composite Properties

Given that composite components may have services and references, it should come as no surprise that they may also have properties. The composite in Listing 5.18 declares two integer type properties.

Listing 5.18 Composite Property Declarations

image

The example provides default values of 200 and 700, respectively.

The properties can be set when the composite is used as a component implementation, as shown in Listing 5.19.

Listing 5.19 Composite Property Configuration

image

The preceding example sets the min and max properties to 100 and 800, respectively, overriding the default values.

Note that in Listing 5.18, we declared the property type to be integer as defined by XML Schema (the use of the “xs” prefix). SCA defines the range of valid property types to include those defined by XML Schema—for example, string, integer—and user-defined complex types (more on that later).

More on XML Schema

A lot has been written on XML Schema. To learn more, you can consult the specifications at http://www.w3.org/XML/Schema. As the specifications are quite dense, we recommend XML Schema by Eric van der Vlist (O’Reilly, 2002), which provides a thorough overview of the technology.

Composite properties are optional by default—that is, they do not need to be configured when the composite is used as a component implementation. If a property is not configured and a default value is provided, the property will be set to that value. If the CreditComponent in Listing 5.19 had not specified min and max property values, the SCA runtime would have substituted the default values of 200 and 700.

A property configuration can be made mandatory by setting the mustSupply attribute on the property declaration in the composite to true (by default, it is set to false). This is shown in Listing 5.20.

Listing 5.20 Optional Composite Property Declarations

image

When @mustSupply is set to true, a property must be configured when the composite is used as a component implementation.

Configuring Composite Properties

Composite properties would not be very useful unless they could be accessed by contained components. The SCDL in Listing 5.21 demonstrates how to do this.

Listing 5.21 Referencing a Composite Property

image

The @source attribute of the <property> element instructs the SCA runtime to set the value of the property to the given composite property value. The source attribute value is an XPath expression. We discuss XPath in more detail later in the chapter, but if you are not familiar with it, XPath is essentially a technology for addressing parts of an XML document. Because SCDL is XML, SCA uses XPath to refer to XML values. In the example, the $ character is an XPath operator that instructs the SCA runtime to select the min and max properties.

Why did the SCA authors choose XPath as the expression language for referencing composite properties as opposed to something simpler, such as just referring to the property name? As we show in the next sidebar, basic XPath is relatively easy to write. Also, there are times when only part of a composite property or subelement needs to be selected, such as when the property is a complex type containing several data parts. (We cover complex types in a later section.) XPath is a widely accepted standard for doing this, and inventing a technology would likely lead to more complexity as people would need to master a new approach.

Fortunately, most applications are likely to make much more use of simple property types, such as string and integer, than complex ones. In the cases where simple types are used, the only XPath you need to remember is the $ character preceding the composite property name being referenced.

Multivalued Properties

Property values may contain multiple values, such as a collection of strings or integers. Multivalued properties are declared by setting the @many attribute to true (the default is false), as shown in Listing 5.22.

Listing 5.22 Declaring a Multivalued Property

image

The property declaration in Listing 5.22 provides multiple default values. When the composite is used as a component, values can be set for property by creating multiple <property> entries (see Listing 5.23).

Listing 5.23 Configuring a Composite Property Using a Complex Type

image

At runtime, any component that accesses the validStates composite property will be given a collection containing the strings CA and MA. If no value were set for the property, the default values as defined in Listing 5.23 would be provided: namely CA, MA, and NY.

Using Complex Property Types

Sometimes configuration consists of information that is best represented using a data structure as opposed to a simple type. Consider the case where the BigBank loan application contains a number of components that validate data at various stages in the approval process. The credit data validator ensures that all required information is present and in the correct format. The validation rules are name-value pairs, where the name corresponds to a data element name and the value is a regular expression defining the formatting rules for the field.

Instead of hardcoding the formatting rules in the component implementation, BigBank has decided to use a composite property. BigBank could have used a database to store this configuration but opted not to do so for two reasons. First, validation information is static and does not change. Requiring an additional database table will make the application more difficult to configure than is necessary. Second, more practically, storing the configuration information in a database table would require changes to the corporate database, which is often subject to a lengthy review processes.

Listing 5.24 is the property declaration for the validation rules using a complex type, validationRules.

Listing 5.24 Declaring a Property Using a Complex Type

image

As shown in this example, where the @type attribute is set to bb:validationRules, complex property types are defined in SCA using XML Schema.

XML Schema can be somewhat complex and verbose, but it is the most widely accepted way to specify the set of rules to which an XML document must conform (also known as a “schema language”). Other alternative schema languages exist, such as DTDs, RELAX NG, and Schematron, but SCA chose XML Schema largely due to its ubiquity and existing software support. The XML Schema for validationRules is listed in Listing 5.25.

Listing 5.25 The validationRules XML Schema

image

When the loan application is deployed, the XML Schema file would typically be packaged as part of the contribution containing the CreditComposite.

The SCDL in Listing 5.26 sets the validationRules property on the CreditComponent.

Listing 5.26 Configuring a Composite Property Using a Complex Type

image

This approach of including the value of a complex property within a composite file is awkward, because the application developer is likely going to want to manage the contents of this configuration as part of a separate file. In this example, it would be most natural to have a validationRules.xml configuration file. That way, the configuration rules can be modified without modifying the composite that uses it.

It is possible to specify the value of any property by referring to the contents of a separate file. The file is specified using a relative URI—in this case, relative to the location of the composite file. So, if the validationRules.xml file is kept in the same directory as the composite, the new composite would look like Listing 5.27.

Listing 5.27 Configuring a Composite Property Using a File

image

The validationRules.xml document contents can then be a little simpler, because it can use the bigbank.com namespace as the default namespace (see Listing 5.28). It also is easier for tools to validate it against its schema.

Listing 5.28 File Contents Used for the Composite Property

image

Having walked through the configuration of complex property types, is the complexity and time required to define an XML Schema worth it? Most applications can likely make do with simple types. However, considering that an XML Schema only needs to be written once, the benefits it affords (most notably validation of property values) are well worth it.

Binding XML Schema Types

In our property examples, we did not discuss how property values are set on component instances. This will vary by implementation type and runtime. For example, a BPEL component gets an infoset representation of the XML value used for the property.

In contrast, a Java implementation must have XML used for property types translated into Java types (that is, primitives or types defined by the JDK, such as java.util.Integer or java.util.List) or user-defined classes. How the property type is mapped to Java types will vary by runtime. Some SCA runtimes may support a data-binding technology such as JAXB, which defines standard mappings from XML to Java. In a JAXB-enabled runtime, the validation rules example would bind to a java.util.Map.

At the time of this writing, Fabric3 supports binding XML Schema built-in types to their Java type equivalent as defined by the JAXB specification. However, Fabric3 does not currently support binding complex or user-defined data types.

Given these differences, it is wise to check the particular runtime documentation before using complex property types.

Referencing Complex Property Values

Previously, we mentioned that it is possible for a component property to reference part of a composite property via an XPath expression. Suppose a component needs access to only one validation rule, such as the correct format for Social Security numbers. This can be referenced using the “source” attribute with the XPath shown in Listing 5.29.

Listing 5.29 Using XPath to Access Parts of a Complex Property

image

The XPath expression, $validationRules//rule[@name='ssn'], instructs the SCA runtime to select the rule whose name is ssn (remember that the actual rule values are set when the composite is used as a component; refer to Listing 5.25). As you can see, even nontrivial XPath expressions are easy to read. At the same time, they are a powerful tool, as evidenced by our example of selecting a specific validation rule.

More on XPath

In addition to properties, SCA uses XPath to configure policy. We briefly touched upon policies in the first chapter and will provide in-depth coverage in Chapter 6, “Policy.”

For the majority of application use cases, simple XPath expressions are likely to suffice. However, for more advanced scenarios, a deeper understanding will be required. As XPath is beyond the scope of this book, we recommend the following sources for more information:

XPath and XPointer by John E. Simpson (O’Reilly, 2002)

• The XPath Specification at http://www.w3.org/TR/xpath

Overrides

In some situations, it is necessary to override a service, reference, or property configuration at a higher level of composition. In this section, we look at several of the more common override scenarios.

Services and References

One of the most common cases where a service or reference configuration needs to be overridden involves changing a binding. Overriding a binding is done by promoting the service or reference. Suppose the RateComposite bound the rateService using the web services binding in the following manner:

image

Now suppose that after the rate composite has been packaged, installed, and activated in a domain, BigBank offers a new loan type to small businesses, which requires a different rating service from its consumer division. Fortunately, the rate composite can be reused by having the rateService reference use a different service. To do this, the reference binding can be overridden when the composite is used as a component implementation. The SCDL in Listing 5.30 shows how to do this.

Listing 5.30 Overriding a Reference Binding

image

In the preceding SCDL, reconfiguring the binding in the component definition overrides the binding information in the composite implementation. In addition to overriding binding settings, reference and service bindings can be changed entirely at outer levels of a composition. When overriding the rate service binding, JMS could have been substituted for web services. The basic rule for bindings is that the outer level always replaces inner levels of composition. (For other service and reference configuration, such as policies, the rules are different—we deal with these in later chapters.)

When Are Binding Overrides Useful?

The previous rate service example demonstrates another reason why it is best practice to avoid specifying bindings except in top-level composites that are deployed to a domain (see the earlier sidebar entitled “Perspective: Use Bindings Only at the Domain Level”). Binding overrides tend to make reading and understanding SCDL difficult.

However, binding overrides are useful for integration and predeployment testing. In the rate service example, BigBank may have a QA and staging environment for testing applications prior to placing them in production. This environment may have slightly different configurations, such as a specific rate service for testing located at a different endpoint address. Overrides provide a mechanism to accommodate environmental differences as an application is tested before it is moved into production.

The SCA Binding

Sometimes it is necessary to “unbind” a reference. Again, take the example we used previously where the reference to the rate service was bound to a web service endpoint:

image

Suppose the new rate service for commercial loans was not a web service but rather provided by another SCA component deployed in the domain. The reference binding needs to be overridden and the reference wired to the target service instead.

In order to accomplish this, SCA defines a binding called the “SCA binding,” or binding.sca. This binding can be used to override a binding set in a composite and instruct the SCA runtime to create a wire to a target service. Listing 5.31 details how the SCA binding is used.

Listing 5.31 The SCA Binding

image

The configuration overrides the web services binding set in the composite SCDL and replaces it with a wire to a target service provided by another component in the domain.

Properties

In SCA, properties are not, strictly speaking, overridden. Rather, a combination of using the default value and the @source attribute on the <property> element can be used to expose a property for configuration higher up in the composition hierarchy. Taking the earlier min and max properties:

image

To make the min and max properties optionally configurable when the loan application composite is used, declare the RateComponent properties to be set by two properties in the LoanApplication composite using the @source attribute (see Listing 5.32).

Listing 5.32 Configuring Properties

image

The SCDL in Listing 5.32 effectively allows the default property values defined in the CreditServiceComposite to be overridden outside the loan application composite.

Inclusion

Often, different developers may be responsible for component implementations that reside within a composite. This can create difficulties, as multiple people need to modify a composite file during development. One solution to this problem is to use composition to break the composite into multiple composites, which are then contained in a common parent composite.

Using composition in this manner can be somewhat tedious, particularly if components in different composites need to be wired together. Because composites provide encapsulation, components in different composites cannot be wired directly. Instead, the source reference and target service would each need to be promoted in their respective composites. Then, the promoted reference would need to be wired to the promoted service in the parent composite. With multiple wires, this can result in a lot of extra configuration that will be difficult to maintain.

In cases where encapsulation is not required but it is helpful to separate a composite into multiple files, SCA supports the ability to include a composite in another. Specifically, inclusion inlines a composite in another. For those familiar with C, inclusion is similar to #include: including a composite within another merges its contents. Inclusion is done using the <include> element and setting the @name attribute to the qualified name of the included composite. Unlike C’s #include, composite inclusion is not a textual include, because XML concepts like namespace prefix declarations don’t apply across an include (see Listing 5.33).

Listing 5.33 Two Included Composites

image

In the preceding, two composites are inlined into the ParentComposite. When inlining a composite, its contained components become children of the parent composite. This means that encapsulation is not enforced between two composites included in a common parent. Consequently, it is possible to wire between them without requiring promotion. For example, given CompositeB:

image

It is possible to wire to ComponentB directly from a component contained in CompositeA:

image

It is important to note that because inclusion inlines components directly in the parent, the same rules and conventions apply as if the components were all defined in a single composite. In particular, care should be taken to avoid component name clashes.

Inclusion Versus Composition

A common question people raise is when to use inclusion versus when to instead use composition. One way of answering this is to say that composition should be used as part of the architectural design, whereas inclusion should be done for expediency. In other words, when you want to make a set of components within a composite replaceable as a unit or hide their wiring details, use composition. When you need an easy way to allow more than one person to work on a composite without clashing, break out the contained components into multiple included composites.

Summary

This chapter illustrated how composition is used to achieve application modularity in SCA. Composition allows services to be built from composites that contain more fine-grained components. Composition fosters modularity in two ways. First, it provides encapsulation by allowing composites to be treated as single components that provide services to clients. Additionally, composition fosters reuse by allowing composites to be configured as component implementations multiple times, potentially using different property values or wiring. With composition in hand, you will be able to create applications that are easier to manage, maintain, and evolve.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset