8. Bindings

Applications rarely exist in isolation. External clients inside or beyond an organization’s firewall may require access to services offered by an application. Likewise, an application may need to access services hosted by other applications.

Within an SCA domain, wires are used to integrate services that may be co-located or hosted on different machines. However, it is often the case that a service may need access to another service that is not hosted in the same domain or is not an SCA service at all. In SCA, bindings provide the means to communicate outside the domain. Bindings are used to expose services to external clients via a network protocol such as web services. In addition, bindings connect references to external services hosted outside the domain using a network protocol.

In previous chapters, we introduced the basics of using bindings to expose SCA services as web service endpoints. In this chapter, we cover the web service binding in more detail and connecting services to enterprise message buses. By the end of this chapter, you will have a thorough understanding of how to use bindings to integrate SCA services with applications and services hosted outside a domain, whether they are web services or message-based.

Interoperable Communications Outside the Domain: The Web Service Binding

In SCA, bindings establish communications outside the domain. Bindings are used to expose a service as an endpoint over a remote transport. Bindings also are used to connect references to an external service via a remote transport.

When SCA was created, it was envisaged that there would be many different types of bindings corresponding to the range of remote protocols used by distributed applications today. When performance is a concern, a binary-based binding such as RMI/IIOP could be used. In cases where interoperability is required—for example, when a service needs to be available to clients written in other languages, such as one of the .NET languages—the web service binding is the logical choice. In this section, we look at the details of working with the web service binding.

Making a service available as a web service endpoint or accessing a web service using SCA is fairly simple. The composite presented in Listing 8.1 promotes a service and reference using the web service binding.

Listing 8.1 Using the Web Service Binding

image

In this example, the LoanService is made available as a web service endpoint at the following address: http://bigbank.com/services/LoanService. The LoanComponent#rateService reference is bound to the web service endpoint located at http://somecompany.com/rateService.

It’s valuable to briefly describe the steps performed by the runtime to make this happen. First, when activating the LoanService endpoint, the runtime needs to generate a WSDL document for the service (remember from Chapter 2, “Assembling and Deploying a Composite,” WSDL is the language used by web services for describing services and their operations). Because the service is implemented using Java, the WSDL will be generated from a Java interface. After the WSDL is generated, the runtime needs to provision the endpoint at the address specified in the @uri attribute of the <binding.ws> element. At this point, the service will be ready to accept and process incoming requests.

On the reference side, the runtime needs to create a remote communications channel from the component to the remote endpoint. In the case of Java, this channel will be similar to one created for a wire (see the “What’s Behind a Wire” sidebar in Chapter 7, “Wires”). If the component is implemented in Java, a proxy will be created that dispatches an invocation on the reference over web services. In order to dispatch an invocation correctly, the proxy needs to map from the invoked Java method to a web service operation. After it has mapped the invocation, it needs to encode the request as a SOAP message and dispatch it over the network to the address specified by the @uri attribute on the <binding.ws> element.

Having dealt with the basics of the web service binding (they are fairly trivial), we turn to some of the more common configuration options that may be needed by applications.

Using WSDL as the Interface Definition Language

In top-down development, service contracts are defined before implementations are written. This is often done to facilitate interoperability across different technology platforms. By defining services, operations, and their messages using a language-neutral format such as WSDL, top-down development can avoid using features specific to a particular platform.

WSDL is also essential when connecting systems managed by independent organizations. Because it is difficult for an organization to control or mandate the technology clients use to connect to a service, a language-independent mechanism for describing services such as WSDL is the best way to facilitate integration.

Given these scenarios, it may be necessary to use a predefined WSDL as opposed to having the runtime generate one when using the web service binding. To understand how this is done, we need to briefly review some key WSDL concepts.

In WSLD 1.1, a port is some unit of code that is reachable at a given network address over a particular protocol. This unit of code is often referred to as an endpoint. For example, an endpoint may be located at http://somecompany.com/rateService or at www.somecompany.com/rateService using the HTTP protocol. A port contains a set of operations that process messages in a given format. The RateService endpoint has a #getRates operation that takes several data, including the date to return rates for. When the endpoint is invoked, it receives a message containing this data via HTTP encoded in a specified format—for example, SOAP 1.1.

Ports are broken down into a number of separate elements. A portType defines the set of operations for an endpoint. It is roughly analogous to an interface in Java. A binding defines the message format (for example, SOAP 1.1) and protocol details for a portType (for example, HTTP). Finally, a port specifies an address where the endpoint can be contacted. WSDL separates out these elements so that they can be reused. Two ports may use the same portType but different bindings. Two different endpoints would be created that perhaps were available over different protocols but offered the same set of operations to clients.

WSDL 1.1 somewhat confusingly (at least from the perspective of SCA) also defines the concept of a “service,” which is different than an SCA service. In WSDL 1.1, a service is a collection of related ports.

In response to limitations and complaints about the complexity of WSDL 1.1, WSDL 2.0 introduced several important changes. Although we will not document the changes here, there are two that you need to be aware of. First, WSDL 2.0 has renamed portType to interface and port to endpoint. Second, a service is now restricted to one interface (as opposed to WSDL 1.1, which allowed multiple portTypes).

More on WSDL

In this book, we don’t explain the details of WSDL. At some point, it is worth becoming more familiar with the technology. The WSDL 1.1 (http://www.w3.org/TR/wsdl) and WSDL 2.0 (http://www.w3.org/TR/wsdl20-primer, http://www.w3.org/TR/wsdl20, http://www.w3.org/TR/wsdl20-adjuncts, and http://www.w3.org/TR/wsdl20-bindings) specifications are options, although they can be tedious reading.

Having reviewed some of the key WSDL concepts, we now examine how to use WSDL with the web service binding. As Listing 8.2 illustrates, an existing WSDL document can be specified for the service and reference interface contracts using the <interface.wsdl> element.

Listing 8.2 Using WSDL 1.1 to Define Service and Reference Contracts

image

Listing 8.2 uses WSDL 1.1 to specify interface contracts via the @wsdlElement attribute. When using WSDL 1.1, the format for the @wsdlElement attribute is as follows:

<WSDL-namespace-URI>#wsdl.port(<service-name>/<port-name>)

In Listing 8.2, the service and reference interfaces are configured to use the portTypes defined by the LoanApplicationPort and RatePort, respectively. When this is done, the runtime will do two things. First, it will introspect the WSDL identified by the <service> entry to find the portType and map the portType operations to the promoted SCA service, LoanService, which is promoted from LoanComponent. The runtime will also introspect the WSDL specified by the <reference> configuration to find the portType so that it can map invocations to the correct endpoint operation.

The web service binding configuration in Listing 8.2 did not include an @uri attribute as it had when <interface.java> was used. This is because WSDL ports (or endpoints in WSDL 2.0) include an address. When <interface.wsdl> is used, the SCA runtime uses the address provided in WSDL.

Note that both the <service> and <reference> declarations in Listing 8.2 do not specify the physical location from which to retrieve the WSDL. How does the runtime know where to get the WSDL? If the WSDL is bundled as part of the same contribution archive as the composite file, the runtime will have access to it. If the WSDL is located elsewhere (for example, in another contribution archive), the WSDL will need to be imported. We briefly discussed contribution imports in Chapter 2 and provide a more detailed account in Chapter 9, “The Domain.” Until then, we can assume the WSDL is packaged in the same contribution as the composite file.

Using WSDL 2.0 is slightly different from WSDL 1.1, and specifying interface contracts is one of those areas that involves those slight differences. Listing 8.3 modifies the previous example (refer to Listing 8.2) to show how this is done.

Listing 8.3 Using WSDL 2.0 to Define Service and Reference Contracts

image

The difference between the WSDL 1.1 and WSDL 2.0 examples is the use of wsdl.endpoint in place of wsdl.port. The format for the @wsdlElement attribute when using WSDL 2.0 is as follows:

image

Also note that we changed the name of LoanApplicationPort to LoanApplicationEndpoint and RatePort to RateEndpoint to reflect the new WSDL 2.0 terminology.

Perspective: Should WSDL Be Used When Specifying Service Contracts?

Although we have discussed <interface.wsdl> in conjunction with the web service binding, it can also be used in other contexts. Specifically, WSDL can be used as the interface definition language for any service or reference, whether it is explicitly bound or wired. WSDL can also be used to define the interface contracts on both sides of a wire, as the following illustrates:

image

Most applications probably don’t need the added complexity of explicitly specifying WSDL except in special circumstances. For example, when wiring references to services, the runtime will establish a remote communications channel without requiring WSDL to be specified.

One case where the added complexity of using WSDL directly may be beneficial is binding a service or reference. In these situations, the WSDL may be created prior to the service implementation to facilitate interoperability between service clients and providers written in different languages. Using explicitly defined WSDL avoids the possibility that WSDL generated by the SCA runtime when a service or reference is bound will contain subtle differences.

Specifying WSDL may also beneficial when applications are assembled from components written in multiple languages. For these types of applications, it may be easier to write WSDL upfront and generate interfaces for clients in their respective languages. Similar to the previous case, explicitly declaring WSDL avoids the possibility that runtime-generated WSDL will contain subtle differences from that used during development.

Non-Blocking Interactions Using Web Services

The web service binding examples so far have used synchronous operations. When a client invokes a synchronous operation, it waits until a response is received. As we explained in Chapter 3, “Service-Based Development Using Java,” in loosely coupled systems where network connections introduce latency, it is often better to use non-blocking operations. After a non-blocking operation is invoked, control is returned immediately to the client so that it can continue processing. Non-blocking operations do not return a response. Instead, if a response is needed, the service provider must make a callback.

Using non-blocking operations with the web service binding is straightforward. When creating the service interface, define its operations as one-way. In Java, recall that this is done using the @OneWay annotation for a service that records a loan approval event (see Listing 8.4).

Listing 8.4 Non-Blocking Operations and Web Services

image

Because the approved operation is marked as one-way, when a reference to the ApprovalService is bound using web services, the SCA runtime returns control immediately to the client component when the operation is invoked. The client will not block while the invocation is sent to the ApprovalService.

Callbacks and Conversations with Web Services

In theory, using callbacks and conversations with the web service binding is straightforward. For example, a service bound using web services and requiring a callback must simply annotate its Java interface with @Callback, specifying the callback interface. Similarly, a conversational service needs to mark only its Java interface with @Conversational. In both cases, when an invocation is made, the runtime needs to add additional information to the message it sends out over the network to the target service. In the case of callbacks, the runtime must send some form of endpoint address the target service can use to make a callback. Similarly, for conversations, an ID must be sent with the message so the target service can correlate multiple requests. Otherwise, the target service will not know which conversational a particular request is part of.

In practice, at least at the present time, things are not likely to work as simply as this. If both a client and service provider communicating via web services are hosted by the same SCA runtime implementation, problems are not likely to occur. Rather, issues are likely to arise when the client and service provider are hosted either by different SCA vendor runtimes or one is not built using SCA at all (for example, it is a .NET service). Because SCA does not specify the format for propagating callback and conversational information, vendors will likely implement such features using proprietary approaches, making interoperability more difficult. At some point, SCA may standardize how callback and conversational information is propagated. However, until that happens, it is best to avoid using these features unless a client and service provider are deployed to the same SCA vendor implementation.

Accessing Messaging Infrastructure: The JMS Binding

Message-oriented middleware (MOM) is often a key part of enterprise architectures. MOM products typically function as a messaging backbone that integrates disparate corporate systems. SCA standardizes connecting to messaging infrastructure via the Java Message Service (JMS) binding. The JMS binding allows references to flow invocations to a target service using JMS topics and queues. The binding also allows services to receive incoming requests from topics and queues. In this section, we look at the details of working with the JMS binding.

One-Way Messaging with JMS

JMS is an asynchronous messaging API—that is, messages may be sent to a destination after control has returned to the client. Due to its asynchronous nature, JMS is a natural transport to use with non-blocking service operations.

Suppose BigBank already has a legacy auditing system in place. This system is used by all corporate applications to record credit rating results, lending statistics, and other information mandated by law. Further, the system is accessed through JMS.

BigBank has plans to convert the system to SCA as part of the second phase of their loan application build-out. To minimize the amount of work for the first phase, BigBank has decided to have the SCA loan application components access the legacy auditing system via JMS. In the second phase, the legacy system will be replaced by an SCA-based implementation similar to the auditing composite we introduced in Chapter 6, “Policy.” Because existing, non-SCA systems will still require access to auditing via JMS, the replacement composite will expose the auditing service as a JMS endpoint.

Binding References to JMS

The first step in accessing the legacy auditing system from an SCA component is to define a service interface for auditing operations. Because the system was built using JMS, it has a message-based API, as opposed to a service-based API. An example of using the original message-based API is given in Listing 8.5.

Listing 8.5 Accessing the Auditing System Using JMS

image

In contrast, the service-based API is defined by the AuditService interface listed in Listing 8.6.

Listing 8.6 The Service-Based API for the Auditing System

image

Because the auditing operation will be performed asynchronously, we declare the record operation to be non-blocking by using the @OneWay annotation. Listing 8.7 illustrates how the service-based API is used instead of the message-based API shown previously in Listing 8.5.

Listing 8.7 Using the Service-Based API

image

In the preceding example, when the audit service reference is configured to use the JMS binding, the SCA runtime will flow service requests—calls to CreditScoreService.checkCredit(..)—as JMS messages. Let’s see how that is done.

As Listing 8.8 demonstrates, binding a reference using JMS is simple.

Listing 8.8 Using the JMS Binding

image

In the preceding example, the JMS binding configuration specifies the AuditQueue for flowing invocations to the AuditService, as depicted in Figure 8.1.

Figure 8.1 Enqueuing a reference invocation

image

When the audit service reference is invoked, the reference proxy converts the invocation to a JMS message and enqueue. At that point, the JMS provider delivers the message to its intended destination—in this case, a consumer attached to the AuditQueue.

Perspective: Why Not Use JMS Directly?

Would it be better to have a component implementation use the JMS API directly as opposed to binding a reference? This question could be raised about bindings in general: Wouldn’t it be easier to use transport APIs directly? An argument can be made that dealing with an API is easier than having to create and maintain XML configuration.

Although it is hard to make sweeping generalizations and claim that using bindings for external communications is always the better approach, it does provide a couple of key advantages.

First, bindings decouple component implementations from the transports used to invoke dependent services. If BigBank decided to rewrite its audit service to use something other than JMS, client code would not have to be modified.

The second advantage bindings bring is that they externalize communications configuration. Some may say placing configuration in XML makes applications more difficult to maintain. However, the advantage in doing so is that it allows remote communications to be reconfigured without modifying code. For example, an SCA runtime could change the JMS queue used by a bound reference without requiring a code change. If the configuration is buried away in code, runtimes can’t provide this type of dynamic behavior.

Binding Services with JMS

For the second phase of refactoring the auditing system, BigBank has decided to re-implement it as an SCA composite. Because existing non-SCA clients will still access auditing via JMS, the new composite must maintain backward compatibility with the old system by binding a service to the AuditQueue. This can be done using the configuration shown in Listing 8.9.

Listing 8.9 Using the JMS Binding

image

As the composite is deployed, the SCA runtime registers a listener on the AuditQueue. When an incoming message arrives on the queue, the listener dispatches the message to the service for processing, as depicted in Figure 8.2.

Figure 8.2 Dequeuing a message and dispatching it to a service

image

Existing clients can continue to send messages to the AuditQueue. The SCA runtime will be notified by the JMS provider when messages arrive and will forward them to the AuditService.

Operation Selection

The JMS messaging model differs from the SCA programming model in that it deals with messages and destinations (that is, queues and topics), as opposed to service operations and endpoints. This requires the JMS binding to perform two types of mapping. Incoming JMS messages must be mapped to service operations, and outgoing invocations must encode service operation information in the JMS message. In addition, input and output data for service invocations (that is, the operation parameters and return values) must be mapped to and from the JMS message. We refer to these processes of mapping operations and data as operation selection and message data binding, respectively. SCA defines default behavior and provides the ability for applications to specify custom behavior for operation selection and message data binding. We now look at how this is done. In the next section, we discuss message data binding in more detail.

The JMS binding was designed to map a single service to a destination (topic or queue). In other words, a JMS destination is always associated with one service. Although it is possible to bind a service multiple times to different destinations (using multiple <binding.jms> configurations), different services should be bound to individual destinations.

When dispatching to a target service for a destination, the SCA runtime must select the correct operation. To do this, SCA defines a set of rules for encoding operation information in a JMS message. These rules are straightforward. If the target service has only one operation, it is automatically selected. If the target service has more than one operation, the runtime looks for a user property on the JMS named "scaOperationName" and uses its value to map to the appropriate operation. If the user property is not found and the service has more than one operation, the runtime looks for an operation named "onMessage".

When non-SCA external clients invoke a service bound to JMS, they may have to encode the operation information manually (assuming the service contains more than one operation and no "onMessage" operation). Going back to the AuditService example, because the service has only one operation—record—no encoding needs to be done because the SCA runtime will automatically map incoming messages to it. However, if AuditService had multiple operations, clients would need to specify the operation in the JMS message. The example in Listing 8.10 modifies the code originally listed in Listing 8.5 to include the addition of the operation information as a message property.

Listing 8.10 Flowing Operation Information Manually Using the JMS API

image

When the message is dequeued on the receiving end, the SCA runtime will dispatch to the record operation by reading the value of the "scaOperationName" set on the JMS message.

Message Data Binding

In addition to encoding and decoding operations, the JMS binding must also map parameter data to and from messages. If the invoked service operation has one parameter, the data is serialized and sent as XML. How the data is serialized to XML is determined in one of two ways. If WSDL is used to specify the service interface (that is, <interface.wsdl>), the SCA runtime will use it to determine how to serialize the parameter data. For example, in Listing 8.11, the interface for the AuditService is configured using WSDL.

Listing 8.11 Using interface.wsdl with the JMS Binding

image

The WSDL for the AuditService will contain definitions for its operations and the messages they receive and return. A message definition in WSDL is specified using XML Schema.

When a message is enqueued, the SCA runtime will serialize parameters as part of the JMS message. SCA mandates parameters be sent using JMS text messages. The format for parameter serialization is, however, left unspecified. The Fabric3 SCA runtime uses JAXB for complex types, and it is likely that other vendor implementations will support the data-binding technology. In addition, Fabric3 also supports sending JMS object messages (when parameter types implement java.lang.Serializable), JMS stream messages, and JMS bytes messages for primitive types (for example, int or long).

Request-Response Messaging with JMS

Message-based communication is often one-way. However, there are times when a response is needed. In SCA, there are two ways to propagate responses, either as a return value to an operation or through a callback. In this section, we discuss request-response operations using the JMS binding. In the next section, we cover callbacks.

One of the loan application requirements is that new mortgage applications be appraised for their value on the secondary market. After a loan is made, BigBank often sells the right to collect interest and principal payments to a third party. The appraisal is handled by a legacy system accessible via BigBank’s JMS provider.

Like the auditing function, BigBank defines a service interface to the legacy appraisal system, which is listed in Listing 8.12.

Listing 8.12 The Secondary Market Appraisal Legacy System

image

The SecondaryAppraisalService uses request-response style messaging: After the service has been invoked, the client blocks waiting for a response.

How does this interface map to JMS, given that messages are sent in a one-way, asynchronous fashion? Request-response messaging is commonly implemented in JMS using separate request and reply queues (see Figure 8.3).

Figure 8.3 Request-response messaging with JMS

image

JMS has built-in support for request-response messaging with the replyTo message header. Using the JMS API directly, a client sets the replyTo header to the queue on which it receives responses. The message endpoint in turn uses the replyTo header for the queue to return a response. An example of setting the replyTo queue is given in Listing 8.13.

Listing 8.13 Setting the JMS replyTo Header

image

Similarly, the message endpoint accesses the replyTo queue by calling Message.getJMSReplyTo() on the received message.

One missing piece we have not yet discussed is how a client associates a response with the original request. Because JMS is asynchronous, a client may send multiple requests before it receives any responses. Consequently, it needs a way to correlate response messages with its original request. JMS provides built-in support for message correlation via the correlationId message header. The correlation ID is most commonly set to the message ID of the original request by the message endpoint. Listing 8.14 shows how an endpoint sets the correlation ID.

Listing 8.14 Setting the JMS Correlation ID Header

image

When the client receives the response, it can use the correlation ID to match the message to the original request.

Setting up request and response queues and managing correlation can be tedious. An SCA runtime will handle this so that request-response invocations can be made without having to perform these tasks in application code. Listing 8.15 shows how to invoke the SecondaryAppraisalService and receive a response over JMS—it’s no different than invoking any other reference.

Listing 8.15 Invoking the LoanAppraisalService

image

Notice that in the example, the client invokes the service and waits for a response. When the invocation is made, the SCA runtime is responsible for enqueuing the message and having the client block until a response is received. This requires the runtime to manage message correlation transparent to the component implementation. When using the JMS binding, components don’t need to deal with request and response queues or correlation IDs. Handling these transport specifics is the job of the SCA runtime.

Configuring a service or reference to use request-response style messaging with the JMS binding is only slightly more involved than one-way messaging. Listing 8.16 provides an example of how to bind a reference.

Listing 8.16 Configuring Request-Response Messaging with the JMS Binding

image

The preceding example configures the reference to send requests to the AppraisalQueue and receive responses from the AppraisalResponseQueue. Setting up the required message consumer and correlation infrastructure will be automatically done by the SCA runtime when the composite is deployed.

How Are Destinations Created?

The JMS binding supports a number of options for creating destinations (topics and queues). The default—which we have been using in the examples—is to have the SCA runtime create the destination if it does not exist. The options for creating destinations are specified using the @create attribute on the destination element:

image

Valid values are "ifnotexist" (the default), "always", and "never". If "always" is used and a destination already exists, the runtime will raise an error.

Performing Callbacks with JMS

In request-response messaging, clients block waiting for a response. In loosely coupled applications, this synchronous communication style may not be appropriate. For example, the secondary loan appraisal system may take some time to deliver a response. Or it may be down for maintenance during certain times of the day, in which case message delivery must be temporarily halted and done at a later time. Having component instances block in these situations will be inefficient and likely introduce bottlenecks.

As with wires, asynchronous two-way invocations over JMS are done using callbacks. Instead of blocking, clients make a service request and return immediately. After a period of time, they will be called back with a response. The SecondaryAppraisalService is modified in Listing 8.17 to use a callback.

Listing 8.17 Using Callbacks with the Secondary Appraisal Service

image

The callback interface is listed in Listing 8.18.

Listing 8.18 Using Callbacks with the Secondary Appraisal Service

image

When the SecondaryAppraisalService is invoked and a callback made, the SCA runtime performs the sequence of steps depicted in Figure 8.4.

Figure 8.4 The callback sequence over JMS

image

In the preceding sequence, the LoanComponent invokes the appraisal service and returns immediately, enabling it to perform additional processing prior to the arrival of the response. At some later point in time, the component will be called back on its SecondaryAppraisalCallback interface. The LoanComponent implementation is presented in Listing 8.19.

Listing 8.19 The LoanComponent Using a Callback

image

Configuring the appraisal service reference to use a callback is done in exactly the same way as setting up a request-response interaction. We relist the composite used in the previous section in Listing 8.20.

Listing 8.20 Configuring Callback Messaging with the JMS Binding

image

The same binding configuration can be used because the SCA runtime knows from the reference service contract that a callback is required (remember, SecondaryAppraisalService was annotated with @Callback in Listing 8.17). Again, as with request-response operations, the SCA runtime will set up the appropriate JMS infrastructure—queues and message consumers—to flow request and callback invocations.

When a request is initiated, the SCA runtime will include the callback queue as part of the JMS message header in the "scaCallbackQueue" property. Message receivers that use the JMS API directly can use this information to return a response. When a response is sent to the callback queue, the SCA runtime will dequeue it and invoke the corresponding callback operation.

Optional JMS Binding Configuration

In our coverage of the JMS binding, we don’t discuss all the possible configuration options. The JMS binding specification includes a variety of additional options, including setting alternative correlation schemes, message delivery modes, and message headers.

Most of these options will need to be used only for specific binding scenarios. For a listing and explanation, see the JMS Binding Specification, available from http://www.osoa.org.

Using Publish-Subscribe Messaging Patterns

So far, the JMS binding examples we have presented make use of queues. The JMS binding also supports publish-subscribe style messaging using topics. When binding a reference to a topic, from the component implementation perspective, things remain the same: The reference proxy is invoked like any other service.

There is, however, one important restriction when binding to a topic. Namely, service operations must be one-way—that is, they cannot be request-response operations. If a response is needed, a callback can be used.

To configure a topic, the binding makes use of the @type attribute on the destination element (see Listing 8.21).

Listing 8.21 Publish-Subscribe Messaging with the JMS Binding

image

In Listing 8.21, the binding configuration sets the audit service reference to publish to the AuditTopic. This results in the audit message being broadcast to topic subscribers instead of being delivered to a single receiver.

Conversational Interactions with JMS

If a JMS binding is used with a conversational interface, it is up to the provider of the JMS binding to make sure that a conversation ID is assigned to each conversation and passed in each message in the scaConversationID user property. The developer of the implementation does not create any code specific to JMS.

Proprietary Bindings

SCA runtimes are not restricted to the JMS and web service bindings. In fact, it was the intention of the SCA authors to enable runtimes to support a host of proprietary communications mechanisms. One of the advantages of SCA is that components can use these bindings without tying application code to proprietary APIs.

Using Bindings for Communicating Within a Domain

SCA allows bindings to be specified on services and references that are not promoted. In other words, SCA allows bindings to be specified on wires for services that will never be exposed outside the domain. This is a capability that we recommend that users not take advantage of. There really is no reason to specify a binding for services that are not exposed outside of the domain. If there are aspects of the implementation that imply that something about a binding is required, that requirement can be specified with an intent.

For example, if there is a strict requirement that the SOAP is used, it can be accomplished by requiring the “SOAP” intent. If there is a strict requirement that the binding be accessible through the JMS API, the “JMS” intent can be required. By using intents, it frees the runtime to pick any binding that can provide whatever guarantee is required by the intent, rather than being limited to using one specific intent.

Bindings Overrides

Having covered the web service and JMS bindings in detail, we now turn to the subject of binding overrides. Sometimes it is necessary to override a binding configuration in a higher-level composite. This may be for a variety of reasons. Perhaps the most common case where this comes up is when there is a need to deploy a composite in a testing and production domain. In the testing domain, bound references need to be configured to point to mock endpoints, whereas in the production domain, they need to point to the “live” services.

These two variations could be accommodated by not binding the references until deployment. This would require the deployer to specify the binding configuration when the composite is activated in the domain. Another, less error-prone option is to have the bindings for the production domain configured in the composite. This will avoid the need to specify bindings when the composite is deployed in production. When the composite is deployed to the test domain, the production configuration can be overridden.

Overriding a binding on a promoted reference is straightforward. To do so, add a new binding configuration to the component that uses the composite. Listing 8.22 shows how this is done.

Listing 8.22 Overriding a Binding on a Promoted Reference

image

The preceding example overrides binding configuration in the CreditScoreComposite and replaces it with the JMS binding set to use the TestAuditQueue. One additional thing to keep in mind is that binding overrides are complete—that is, they completely replace any binding settings made at lower levels in the composition.

The SCA Binding

In addition to the web services and JMS bindings, the SCA specifications talk about the “SCA binding.” This binding is not a transport protocol invented specifically for use with SCA applications. Rather, it refers to the remote communications protocol selected by the runtime to establish a wire. Because a runtime may select different protocols for different wires, the SCA binding may vary. In other words, a runtime may use more than one protocol for the SCA binding.

Calling the transport protocol assigned to a wire the “SCA binding” is confusing, and an argument can be made that the SCA authors should have named it something else. In fact, the SCA binding is different than other bindings. When a service or reference is bound, the binding fixes the communications channel. That is, the remote communications protocol cannot be changed by the runtime at some later point. The SCA binding, on the other hand, does not fix the remote protocol; it is just a placeholder for one selected by the runtime when it creates a wire.

Why did the SCA authors even bother to mention the SCA binding? The answer is that there is one case where it is needed. When a reference is explicitly bound, there must be a mechanism for overriding the binding in a higher-level composite and replacing it with a wire. This is done by using binding.sca on a promoted reference. For example, the following overrides a binding set on a reference in a composite and replaces it with a wire:

image

Because this is a corner case, it is likely that most applications will never need to make use of the SCA binding directly. However, it is important to be aware of the differences between it and other bindings.

Summary

This chapter has covered integrating SCA services with clients and services hosted outside a particular domain using bindings. In particular, we covered interoperable communications using web services and connecting services in a domain to a message bus via JMS.

Having now covered the core SCA concepts, including services, components, composites, policy, wires, and bindings, in the next chapter, we turn to an in-depth discussion of the role the domain plays in SCA.

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

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