There are two important drivers in the business world: change, and heterogeneity. Whatever your business solution is today, you know you'll have to change it, add new features, update pieces for better service, or adapt to the whims of your suppliers. And these drivers are creating unrelenting pressure to get the business solution to market quickly. Gone are the days when a business could design a large project from end to end and control all the subsystems.
SCA is a new technology that addresses change and heterogeneity. By abstracting much of the underlying implementation technology, SCA lets a system be more flexible and readily adapt to change while incorporating subsystems implemented in different technologies. SCA moves many of the details of access technology, implementation, and protocols to the middleware layer — away from the business logic.
Some technical architects and developers have taken the first step to implement a sampling of SCA or to update an existing service. As the technical consumers mature, there are often still many questions, such as:
- How exactly do SCA components talk to each other?
- When a client program talks to my SCA application, how does the SCA runtime invoke the methods on my implementation?
- When my SCA application encounters a problem, can someone explain the various classes I see on the runtime call stack?
In this article, learn the answers to these questions.
This article uses the Apache Tuscany SCA runtime environment as an example because:
- Apache Tuscany is an open source implementation of SCA and is freely available for download. You can install Tuscany and the Eclipse development platform to follow along.
- Tuscany is vendor- and platform-neutral. It can run as stand-alone, in conjunction with servers from several vendors (Tomcat, JBoss, Geronimo, IBM® WebSphere®, WebLogic), and on several platforms (Microsoft® Windows®, Linux®, and Mac OS).
- Tuscany uses many of the protocol bindings and implementations discussed in this article. It's an excellent platform to illustrate how the complexities of the underlying implementations are hidden from the SCA developer, letting you concentrate on adapting to change and incorporating various heterogeneous subsystems.
In case you're not familiar with basic SCA terms, this section provides an overview of terms shared by the many SCA implementations and endorsed by the latest Open SOA specifications.
SCA applications are modeled by assemblies. An SCA assembly contains a set of artifacts and the connections that link them together. The assembly is stored in a composite file. The composite file is often described as an XML file that contains the various SCA pieces and the connections between them. The composite file is loaded and made ready to run with an SCA runtime, such as Tuscany. Figure 1 shows an example assembly.
Figure 1. Typical SCA assembly
A component, which is a basic SCA artifact, is the building block of a business application. It provides basic business functions, such as a stock-quote service or a calculator service. Components can have properties that control how the business service acts, and they provide the configuration of the component. An SCA component can be implemented in a number of technologies. The SCA specification defines a basic set of implementation types (Java™ technology, BPEL, J2EE, and Spring) and allows recursive composition of other SCA composites. Tuscany provides an additional set, including scripting languages (JScript, Groovy, PGP, Python, Ruby) and OSGi. The implementation types are for incorporating heterogeneous subsystems and reusing existing code.
The function of an SCA component is offered to other components as a service; an SCA component can make use of services through a reference. The services and references are wired together, made visible, and published to the outside world by promotion. Each service or reference has an interface that describes the business interface as a set of methods. Each method has a name, a number of parameters, and a return value. SCA defines these interfaces with a Java language interface or by a Web Services Description Language (WSDL) file. Each service or reference is accessed with an access binding. The binding defines the protocol over which the service or reference may be accessed. Currently, the SCA specification mentions a basic set of popular binding technologies, such as HTTP, JMS, Web services, and SCA (which often is used when two components are running in the same Java virtual machine and binding is not otherwise specified).
Tuscany provides an additional set of useful bindings that help support Web 2.0-style applications, Atom, RSS, JSON/RPC and others. As shown in Figure 2, the Tuscany runtime is responsible for taking the protocol-specific messages from various technologies and converting them to a form the business-component implementation can use. The business-component implementation processes the data and passes it back to the Tuscany SCA runtime. Once again, the purpose is to incorporate and reuse existing access technologies while letting the business component developers concentrate on business functions.
Figure 2. SCA runtime stack
Finally, as each method in the business interface is invoked, the data provided to the method as parameters and returned from the call is abstracted using a data binding. Common data types include Java objects, XML documents, and Service Data Objects (SDOs). Tuscany can automatically translate between various data types to facilitate data flow to and from a provider and client. Though data binding is not the focus of this article, it's important to know of the multiple uses of the term.
This section highlighted the various abstracts that SCA provides to business application developers. The interface is currently specified in the Java language or WSDL. The access binding is implemented in a number of protocols (HTTP, JMS, Web service, Atom, JSON/RPC). The component implementation is available in several technologies (Java technology, BPEL, SCA, Spring, J2EE, Scripting languages, OSGi). The rest of this article explains how these technologies interact so you can make sense of the underlying path, from service call to an invocation of a business method in an implementation.
The example shows the evolution of a simple business application. You can download the source code for the examples in the scenario. (The application is brief and over-simplified for example purposes.)
The single requirement for this business service is to add two numbers together.
The calculator service is published and available for clients to invoke. The
calculator is wired to an add service that has one function: add two numbers
together and return the sum (for example, double add(double o1, double o2)).
Assume the interface is specified with the Java language, and the service is also
implemented with the Java language.
Figure 3 shows this SCA assembly.
Figure 3. SCA calculator component that adds
One calculator component and its implementation is specified,
and this component references the add service component and its implementation.
The corresponding SCA composite file for this business application
is shown in Listing 1. Download the source code for this component and others.
Listing 1. Calculator composite file
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
xmlns:sample="http://sample"
name="Calculator">
<component name="CalculatorServiceComponent">
<implementation.java class="calculator.CalculatorServiceImpl"/>
<reference name="addService" target="AddServiceComponent"/>
</component>
<component name="AddServiceComponent">
<implementation.java class="calculator.AddServiceImpl"/>
</component>
</composite>
|
Assume that customer requirements expand, and a new service for subtracting numbers is needed. However, there is a Web service available that specifies the interface as a WSDL document and is implemented as a Java program. The Web service is accessed with a Web-services access binding. This new requirement can easily be added to the SCA composite file by adding a single reference and a component that accesses the subtract service.
Listing 2. Calculator composite file with new service
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
xmlns:sample="http://sample"
name="Calculator">
<component name="CalculatorServiceComponent">
<implementation.java class="calculator.CalculatorServiceImpl"/>
<reference name="addService" target="AddServiceComponent"/>
<reference name="subtractService" target="SubtractServiceComponent"/>
</component>
<component name="AddServiceComponent">
<implementation.java class="calculator.AddServiceImpl"/>
</component>
<component name="SubtractServiceComponent">
<implementation.java class="calculator.SubtractServiceImpl"/>
<service name="SubtractService">
<interface.wsdl interface="http://calculator#wsdl.interface(SubtractService)" />
<binding.ws uri="http://localhost:8080/SubtractServiceComponent"/>
</service>
</component>
</composite>
|
To complete the evolution of the business example, let's add requirements for multiply and divide services. These services are available as JScript and Groovy implementations. Tuscany allows you to easily add these to the composite file. The business-application representation now looks like Figure 4.
Figure 4. SCA calculator with four services
In the final SCA composite file for the application, notice that the addition of JScript and Groovy components is a Tuscany-specific extension to the SCA specification. As such, a new namespace attribute pulls in the Tuscany-specific syntax for these components.
Listing 3. Calculator composite file with four services
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
xmlns:sample="http://sample"
xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0"
name="Calculator">
<component name="CalculatorServiceComponent">
<implementation.java class="calculator.CalculatorServiceImpl"/>
<reference name="addService" target="AddServiceComponent"/>
<reference name="subtractService" target="SubtractServiceComponent"/>
<reference name="multiplyService" target="MultiplyServiceComponent" />
<reference name="divideService" target="DivideServiceComponent" />
</component>
<component name="AddServiceComponent">
<implementation.java class="calculator.AddServiceImpl"/>
</component>
<component name="SubtractServiceComponent">
<implementation.java class="calculator.SubtractServiceImpl"/>
<service name="SubtractService">
<interface.wsdl interface="http://calculator#wsdl.interface(SubtractService)"/>
<binding.ws uri="http://localhost:8080/SubtractServiceComponent"/>
</service>
</component>
<component name="MultiplyServiceComponent">
<tuscany:implementation.script script="calculator/MultiplyServiceImpl.js"/>
</component>
<component name="DivideServiceComponent">
<tuscany:implementation.script script="calculator/DivideServiceImpl.groovy"/>
</component>
</composite>
|
The scenario lets you make two rapid changes and add three components to the original business application. The new components are implemented and accessed by different technologies from the original components. SCA can respond to changing and heterogeneous business requirements.
The Tuscany runtime simplifies access to these disparate technologies, and the SCA composite file is relatively free of technology-specific items. However, we haven't explored how these technologies are invoked underneath. Let's dive deeper to look under the SCA exterior.
Overview of Tuscany invocation architecture
SCA takes many of the details of access technology, implementation, and protocols, and moves them into the middleware layer away from the business logic. That's good for the business application developer, but what about the software developer? This section looks underneath the Tuscany framework to show the path of a typical invocation of a business-component implementation.
To run an SCA business application, the first step an SCA runtime (such as Tuscany) takes is to load and configure the SCA composite file. The various composite file artifacts are inspected, and factory methods help instantiate the various objects in memory. The next step is to instantiate the runtime wires that connect the components. In this phase, runtime wires are created for component references and component services over the bindings mentioned in the composite file.
A runtime wire is a collection of invocation chains; there is one invocation chain per method in the business interface. A handler is created, which acts as a message switchboard operator and routes each method call to the appropriate invocation chain. Each invocation chain consists of a set of invokers and interceptors. Invokers provide the invocation logic to binding protocols and implementation technologies. Interceptors are a special kind of invokers that provide additional function, such as data transformation, security, and transaction control. For a component reference, a runtime wire is created to represent the outbound invocation over the selected binding. For a component service, a runtime wire is created to represent the inbound invocation to the implementation type. Callback chains can also be added to the runtime wires to provide a reverse callback to a component.
Follow the path of an invocation in the calculator application as a message travels from
the calculator component to the add component.
- An invocation is dispatched to an
InvocationHandler. In the example, it's a Java technology-based handler. - The
InvocationHandlerlooks up the correctInvocationChain. The example looks up the add method chain. - Various invokers and interceptors create a message, set the payload, set the
TargetInvoker, and pass the message down the chain. - The
TargetInvokerlaunches the message over the underlying protocol. There's an SCA component passing some double values by reference to another SCA component, so no data transformations or protocol translations have to take place. - On the receiving end, a listener takes the message from the underlying protocol and routes it to one of the receiving component's invocation chains. Once again, an SCA component is implemented in Java technology. The chain corresponding to the add method is found.
- The invocation chain finds the
addserviceaddmethod and invokes the method call. The component implementation adds the numbers and returns the sum. - A reverse path is taken back to the calling component.
The path is shown below.
Figure 5. SCA invocation from source to target
Tuscany Java to Java invocation
When you put the example SCA application into a debugger and place a breakpoint on the
AddService add method,
you see a call stack trace similar to Listing 4.
The calculator service implementation caller is at the top.
The add method calls a Java proxy representation of the service.
A JDKInvocationHandler routes the message to the proper invocation chain.
A special PassByValueIntercepter finds the SCABindingInvoker to pass the message to.
The SCABindingInvoker finds a mirror-image PassByValueInterceptor on the service side.
The message is transformed to a Java call, which calls the add service component implementation.
Listing 4. Java invocation stack
CalculatorServiceImpl.add(double, double) line: 54 $Proxy7.add(double, double) line: not available JDKInvocationHandler.invoke(Object, Method, Object[]) line: 155 JDKInvocationHandler.invoke(InvocationChain, Object[], RuntimeWire, EndpointReference) line: 287 PassByValueInterceptor.invoke(Message) line: 112 SCABindingInvoker.invoke(Message) line: 61 PassByValueInterceptor.invoke(Message) line: 112 JavaImplementationInvoker.invoke(Message) line: 132 Method.invoke(Object, Object...) line: not available DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: not available NativeMethodAccessorImpl.invoke(Object, Object[]) line: not available NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available AddServiceImpl.add(double, double) line: 30 |
Phew! That seems like a long chain to make a single add call from the calculator service
to the add service.
It is rather long, but this type of abstraction from the business-world
domain to the underlying technology domain is present in every business application.
If you implement this type of feature yourself, you're forced to take on the burden
of implementing and maintaining this layer.
Apache Tuscany's SCA runtime has this implementation and does the work for you. It has the simple Java-to-Java invocation as shown above, and a large set of service and reference bindings with many component implementation types. The technology implementation is separated from the business logic, greatly simplifying the application.
Tuscany Java to WSDL invocation
This example from the SCA application has the more-complicated call from the calculator service to a subtract service method. Recall that both services are implemented in Java technology, but in this case, the subtract service is described by a WSDL interface and the invocation is run over a Web service access binding. SCA lets you reference and access many disparate technologies.
In this case, the same general invocation path applies, but there will be more
interceptors in the path. The Tuscany runtime now has to
translate the Java technology-based invocation to the Web services messages
of the underlying protocol.
For instance, the DataTransformationInterceptor is invoked
to transform the Java representation of double values
into the native Web services XML representation.
The multiple stages of the source component call to the
target component is shown in Figure 6, with each stage colored as in Figure 5 to
represent its role in the call.
Figure 6. SCA path with intermediate classes
Once again, if you put this calculator SCA application and the Tuscany runtime into a Java debugger, and you place a break point on the service subtract method, you'll see something like Listing 5. (This stack shows just the receiving part of the call. Web services typically sit on top of an HTTP protocol layer, and the HTTP layer receives a message call as a request and transfers the request to the underlying Web-services layer.)
At the top of the stack,
the underlying technology Web-services engine receives the call.
Since Apache Tuscany uses the Axis2 Web services engine,
you see several Axis2 classes on the stack.
The Tuscany RuntimeWire invoker then receives the native message
and finds the correct invocation chain to call.
The invocation starts by calling the DataTransformationInterceptor,
which converts the Web-services representation back into a Java double.
The JavaImplementationInvoker finds and invokes
the Java subtract method on the subtract service.
Listing 5. Web services invocation stack
AxisEngine.receive(MessageContext) line: 176 Axis2ServiceInOutSyncMessageReceiver(AbstractMessageReceiver).receive(MessageContext) line: 100 Axis2ServiceInOutSyncMessageReceiver(AbstractInOutSyncMessageReceiver). invokeBusinessLogic(MessageContext) line: 42 Axis2ServiceInOutSyncMessageReceiver.invokeBusinessLogic(MessageContext, MessageContext) line: 70 Axis2ServiceProvider.invokeTarget(Operation, Object[], MessageContext) line: 736 RuntimeWireImpl.invoke(Operation, Message) line: 158 RuntimeWireInvoker.invoke(Operation, Message) line: 98 RuntimeWireInvoker.invoke(RuntimeWire, Operation, Message) line: 104 RuntimeWireInvoker.invoke(InvocationChain, Message, RuntimeWire) line: 129 DataTransformationInterceptor.invoke(Message) line: 78 JavaImplementationInvoker.invoke(Message) line: 132 Method.invoke(Object, Object...) line: not available DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: not available NativeMethodAccessorImpl.invoke(Object, Object[]) line: not available NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available SubtractServiceImpl.subtract(double, double) line: 27 |
Although the example SCA application was simple in concept, it was rather complex in its implementation. The calculator application referred to four disparate services. Each service was either implemented or accessed in a different technology (Java technology, Web services, HTTP, JScript, and Groovy). With some architectures, the realities of integrating such disparate heterogeneous technologies might have been inhibitive. There might have been mixing of technology and business layers. Some developers would have wasted time converting from one technology domain into the one they knew the best.
SCA is different. It allows you to harness existing technologies and incorporate them into one application. The technologies are imported as-is with little translation and recoding. And the technology implementation is kept separate from the business logic. Any one of the SCA components can be swapped in or out, or hosted on a new binding or implementation, with little impact to the overall application.
The advantages of SCA come at a small price. Luckily, an SCA runtime such as Tuscany picks up the tab for routing messages, understanding various interfaces, interfacing with access and data bindings, and calling many types of implementations. In effect, many of the technology issues are removed from the application and placed in the Apache Tuscany middleware layer. Sometimes, when investigating issues on an SCA application, the resulting invocation path can seem a little complex. This article helped demystify some of the complexity using an example implementation of SCA.
| Description | Name | Size | Download method |
|---|---|---|---|
| Calculator showing various invocations | os-apache-tuscany-sca-sample-calculator.zip | 13KB | HTTP |
Information about download methods
Learn
-
Read about
Apache Tuscany, a comprehensive infrastructure for SOA development and management based on Service Component Architecture (SCA) standard.
-
Open SOA Service
Component Architecture Specifications includes final specifications and also draft specifications representing the latest versions.
-
Browse the
technology bookstore
for books on these and other technical topics.
-
To listen to interesting interviews and discussions for software developers, check out developerWorks podcasts.
-
Stay current with developerWorks' Technical events and webcasts.
-
Follow developerWorks on Twitter.
-
Check out upcoming conferences, trade shows, webcasts, and other Events around the world that are of interest to IBM open source developers.
-
Visit the developerWorks Open source zone for extensive how-to information, tools, and project updates to help you develop with open source technologies and use them with IBM's products.
-
Watch and learn about IBM and open source technologies and product functions with the no-cost developerWorks On demand demos.
Get products and technologies
-
Download
Apache
Tuscany open source SCA runtime and documentation.
- Download the Eclipse development platform.
-
Innovate your next open source development project with IBM trial software, available for download or on DVD.
-
Download IBM product evaluation versions, and get your hands on application development tools and middleware products from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.
Discuss
-
Participate in developerWorks blogs and get involved in the developerWorks community.
Dan Becker is a software developer with IBM Corporation. He creates features for open source projects, such as Apache Tuscany and Apache Geronimo. Previously, he was a team lead on the WebSphere Process Server and WebSphere Business Integration Adapters. He also developed the multimedia implementations for Java Sound on many operating systems, including Windows, Linux, AIX, OS/2, and OS/390.





