Section 9.8. Queued Versus Connected Calls


9.8. Queued Versus Connected Calls

Although it is technically possible (with simple changes such as configuring operations as one way, or adding another contract with the one way operations) to use the same service code both connected and queued, in reality it is unlikely that you will actually use the same service both ways. The reasons are similar to the arguments made in the context of asynchronous calls discussed in Chapter 8. Synchronous calls and asynchronous calls addressing the same business scenario often have to use different workflows, and these differences will necessitate changes to the service code to adapt it for each case. The use of queued calls adds yet another barrier for using the same service code (both connected and disconnected): changes to the transactional semantics of the service.

Consider, for example, the application in Figure 9-10, which depicts an online store application that uses connected calls only.

Figure 9-10. A connected application relies on a single transaction


The Store service uses three well-factored helper services to process the order: Order, Shipment, and Billing. In the connected scenario, the Store service calls the Order service to place the order. Only if the Order service succeeds in processing the order (that is, if the item is available in the inventory) does the Store service call the Shipment service, and only if the Shipment service succeeds does the Store service access the Billing service to bill the customer. The connected case involves exactly one transaction created by the client. All operations commit or abort as one atomic operation. Now, suppose the Billing service exposes also a queued endpoint for the use of the Store service, as shown in Figure 9-11.

Figure 9-11. A disconnected application relies on multiple transactions


The queued call to the Billing service will be played to the service in a separate transaction from that of the rest of the store, and could also commit or abort separately from the transaction that groups Order and Shipment. This could in turn jeopardize the system consistency, so you must include some logic in the Billing service to detect the failure of the other service and to initiate some compensating logic in case it fails to do its work. As a result, the Billing service will no longer be the same service used in the connected case.

9.8.1. Requiring Queuing

Since not every service can be connected and queued, and since some services may be designed for a particular option and only that option, WCF lets you constrain the communication pattern with such services. The DeliveryRequirements attribute presented in Chapter 1 lets you also insist on a queued or connected delivery of messages to the service:

 public enum QueuedDeliveryRequirementsMode {    Allowed,    Required,    NotAllowed } [AttributeUsage(AttributeTargets.Interface|AttributeTargets.Class,                 AllowMultiple = true)] public sealed class DeliveryRequirementsAttribute : Attribute,... {    public QueuedDeliveryRequirementsMode QueuedDeliveryRequirements    {get;set;}    public bool RequireOrderedDelivery    {get;set;}    public Type TargetContract    {get;set;} } 

The attribute can be used to constrain a contract (and all its supporting endpoints) or a particular service type. The default value of the QueuedDeliveryRequirements property is QueuedDeliveryRequirementsMode.Allowed, so these definitions are equivalent:

 [ServiceContract] interface IMyContract {...} [ServiceContract] [DeliveryRequirements] interface IMyContract {...} [ServiceContract] [DeliveryRequirements(QueuedDeliveryRequirements =                       QueuedDeliveryRequirementsMode.Allowed)] interface IMyContract {...} 

QueuedDeliveryRequirementsMode.Allowed grants permission for using the contract or the service with either connected or queued calls. QueuedDeliveryRequirementsMode.NotAllowed explicitly disallows the use of the MSMQ binding, and all calls on the endpoint must therefore be connected calls. Use this value when the contract or the service is explicitly designed to be used in a connected fashion only. The QueuedDeliveryRequirementsMode.Required is the oppositeit mandates the use of the MSMQ binding on the endpoint, and it should be used when the contract or the service is designed from the group up to be queued.

Note that even though the DeliveryRequirements attribute offers the RequireOrderedDelivery property (Chapter 1), if QueuedDeliveryRequirementsMode.Required is used, then RequireOrderedDelivery must be false, because queued calls inherently are unordered and messages may be played back in any order.

When the DeliveryRequirements attribute is applied on an interface, it affects all services that expose endpoints with that contract:

 [ServiceContract] [DeliveryRequirements(QueuedDeliveryRequirements =                       QueuedDeliveryRequirementsMode.Required)] interface IMyQueuedContract {...} 

The client as well can apply the DeliveryRequirements attribute on its copy of the service contract.

When the DeliveryRequirements attribute is applied on the service class, it affects all endpoints of that service:

 [DeliveryRequirements(QueuedDeliveryRequirements =                       QueuedDeliveryRequirementsMode.Required)] class MyQueuedService : IMyQueuedContract,IMyOtherContract {...} 

When applied on the service class while using the TargetContract property, the attribute affects all endpoints of the service that expose the specified contract:

 [DeliveryRequirements(TargetContract = typeof(IMyQueuedContract),                       QueuedDeliveryRequirements =                       QueuedDeliveryRequirementsMode.Required)] class MyService : IMyQueuedContract,IMyOtherContract {...} 




Programming WCF Services
Programming WCF Services
ISBN: 0596526997
EAN: 2147483647
Year: 2004
Pages: 148
Authors: Juval Lowy

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net