PublishSubscribe Using Callback Contracts


Publish/Subscribe Using Callback Contracts

A simple way of building a publish/subscribe system with the Windows Communication Foundation is to use callback contracts. This service contract, IPublisher,

[ServiceContract(Session=true,CallbackContract=typeof(ISubscriber))] public interface IPublisher {     [OperationContract]     KnownDataPoint[] GetKnownDataPoints();     [OperationContract]     void Subscribe(KnownDataPoint[] dataPoints, out bool subscriptionAccepted); }


identifies a callback contract, ISubscriber, that clients of the service are required to implement:

[ServiceContract] public interface ISubscriber {     [OperationContract(IsOneWay=true)]     void Notify(Guid dataPointIdentifier, byte[] value); }


Because all clients of a service that implements IPublisher must implement ISubscriber, which exposes a one-way operation called Notify(), the service can rely on being able to use the client's Notify() operation to publish data to the client. The callback contract can include any number of operations, but they must all be one-way operations.

Note that the IPublisher service contract also has the value of the Session parameter of the ServiceContract attribute set to true. That signifies that the messages exchanged between a client and a service for the duration of a connection between them will be grouped together by the Windows Communication Foundation into a session, and that the Windows Communication Foundation will maintain some information about the state of each session. Having the Windows Communication Foundation do that is a prerequisite for using callback contracts.

Using callback contracts requires not only the obvious task of specifying a callback contract for a service contract, but also the task of selecting a binding for the service by which the service can initiate transmissions to the client. For a binding to allow for that possibility, it must incorporate the composite duplex binding element, CompositeDuplexBindingElement. Two standard bindings that incorporate that binding element are WSDualHttpBinding and NetTcpBinding.

To use the operations of the callback contract implemented by the client, the service requires a proxy for communicating with the client. The service obtains that proxy by using the GetCallbackChannel<T>() generic method of the Windows Communication Foundation's OperationContext class, introduced in Chapter 2, "The Fundamentals":

ISubscriber proxy = OperationContext.Current.GetCallbackChannel<ISubscriber>(); proxy.Notify(...);


To see how to use the ISubscriber callback contracts in a publish/subscribe solution, follow these steps:

1.

Copy the code associated with this chapter that you downloaded from www.samspublishing.com to the folder C:\WCFHandsOn. The code is all in a folder called PublishSubscribe. After you have unzipped the code, there should be a folder that looks like the one shown in Figure 10.1.

Figure 10.1. PublishSubscribe folder.


2.

Open the solution C:\WCFHandsOn\PublishSubscribe\Callbacks\CallbackContract.sln.

The solution consists of six projects:

  • The RandomDataPoint project is for building a class library with a class called RandomDataPoint that represents the source of the information that subscribers want to receive.

  • The RandomDataPoint class derives from the DataPoint class provided by the class library built from the DataPoint project.

  • The PublisherService project is for building a class library incorporating the IPublisher service contract, which has ISubscriber as a callback contract. The class library also includes the PublisherService class, a service type that implements the IPublisher service contract.

  • The PublisherServiceHost project provides a console application to serve as the host for the PublisherService service type.

  • SubscriberOne and SubscriberTwo are both console applications with clients of PublisherService service that implement the ISubscriber callback contract.

3.

Examine the IPublisher service contract in the IPublisher.cs module of the PublisherService project in the CallbackContract solution:

[ServiceContract(Session=true,CallbackContract=typeof(ISubscriber))] public interface IPublisher {     [OperationContract]     KnownDataPoint[] GetKnownDataPoints();     [OperationContract]     void Subscribe(KnownDataPoint[] dataPoints,                      out bool subscriptionAccepted); }


The IPublisher interface is a Windows Communication Foundation service contract that designates ISubscriber as its callback contract. The service contract provides the GetKnownDataPoints() operation for retrieving the identifiers of the data items about which a service that implements the contract can publish information. The Subscribe() operation is provided for clients to subscribe to information about one or more of those data items.

4.

Look at the ISubscriber service contract in the ISubscriber.cs module of the PublisherService project:

[ServiceContract] public interface ISubscriber {     [OperationContract(IsOneWay=true)]     void Notify(Guid dataPointIdentifier, byte[] value); }


ISubscriber is a service contract, all the operations of which are one-way operations. Actually, there is just one operation, called Notify(), by which the service can push the current values of a data item to the client.

5.

Examine the PublisherService service type's implementation of the IPublisher contract's Subscribe() method, in the PublisherService.cs module of the PublisherService project:

void IPublisher.Subscribe(     KnownDataPoint[] dataPoints, out bool subscriptionAccepted) {     Console.WriteLine("Received subscription request.");     subscriptionAccepted = false;     string dataPointIdentifier = null;     if (dataPoints.Length == 1)     {         dataPointIdentifier = dataPoints[0].Identifier;         this.ValidateDataPoint(dataPointIdentifier, out subscriptionAccepted);     }     if (subscriptionAccepted)     {         if (!(this.randomDataPoint.Active))         {             this.randomDataPoint.Active = true;         }         lock (this.subscribersLock)         {             this.subscribers.Add(                 OperationContext.Current.GetCallbackChannel<ISubscriber>());         }     } }


After confirming that the subscription request is for information about a data item of which the service is aware, the method retrieves a proxy for communicating with the subscriber using the Windows Communication Foundation's OperationContext class. Then it adds that proxy to a list of subscriber proxies.

6.

Study the NextValueHandler() method of the PublisherService service type, which is also in the PublisherService.cs module of the PublisherService project:

private void NextValueHandler(IDataPoint sender, byte[] newValue) {     lock(this.subscribersLock)     {         for(int index = this.subscribers.Count - 1; index >= 0; index--)         {             try             {                  this.subscribers[index].Notify(sender.Identifier, newValue);             }             catch (Exception exception)             {                  Console.WriteLine(                      "Removing subscriber due to exception {0}.",                      exception.ToString());                  this.subscribers.RemoveAt(index);             }             if (this.subscribers.Count <= 0)             {                 this.randomDataPoint.Active = false;             }         }     } }


This method is the one by which the service type is notified of a change in the value of the data item about which it publishes information. The service type iterates through the list of subscriber proxies, using each proxy to publish a message concerning the fluctuation in the value of the data item to a subscriber.

7.

Look at the subscribers' implementation of the Notify() operation of the ISubscriber callback contract, which is in the Subscriber.cs module of the SubscriberOne project of the CallbackContract solution. It simply outputs the content of messages published by the client to the console:

void ISubscriber.Notify(Guid dataPointIdentifier, byte[] value) {     Console.WriteLine(         "Notified of value {0} of data point {1}.",             BitConverter.ToInt32(value,0),             dataPointIdentifier.ToString()); }


8.

Start debugging the solution. Console windows for the PublisherServiceHost and for the two subscribers should appear.

9.

When there is activity in the console of the PublisherServiceHost, enter a keystroke into the console windows of both subscribers' consoles.

After a few moments, the service should begin publishing messages about fluctuations in the value of a data item to both of the subscribers, as shown in Figure 10.2. It may take a moment after the first published message is received by the first subscriber before the first published message is received by the second subscriber.

Figure 10.2. Publish/Subscribe using callback contracts.


10.

Stop debugging the solution.

Callback contracts provide a very easy way of implementing publish/subscribe with the Windows Communication Foundation. As is true of push-style notification solutions generally (Graham, Hull and Murray 2005, 24), the technique presupposes the network being configured to allow the publisher to transmit messages to the client.




Presenting Microsoft Communication Foundation. Hands-on.
Microsoft Windows Communication Foundation: Hands-on
ISBN: 0672328771
EAN: 2147483647
Year: 2006
Pages: 132

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