Developer Resources:

Customer Quotes:

WebORB provides a powerful framework for delivering data from the server-side application to Flex clients. The framework allows data push for both in-process and out-of-process data. This article contains a overview of performing data push from a standalone (out-of-process) Windows application to a Flex client using Microsoft MessageQueue (MSMQ).

The diagram below demonstrates data flow in the example discussed in this article. 'Message Queue Publisher'  is a native Windows application with access to a MSMQ queue. It publishes a message (.NET complex type) into a queue. WebORB subscribes to the same queue on behalf of the connected Flex clients. As soon as a message is placed in the queue, WebORB delivers it to all Flex clients as an ActionScript object

Requirements

  • WebORB for .NET v.3.2 or later
  • Microsoft .NET Framework 2.0 or later
  • Flex Builder 2 or Flex SDK v 2.0.1 or later
  • Microsoft Message Queue (MSMQ)

Resources

Data Producer - Windows Publisher

Message publisher is a Windows Forms application. It creates a timer controlled by the Start and Stop buttons

When the timer is running, it publishes a message into a queue on each timer interval. Each message is a serializable object (instance of the Car class):

private void publishTimer_Tick( object sender, EventArgs e )
{
     // create a new object instance
     Car car = new Car();

     // populate instance properties
     car.Make = "TurboQ-" + messageCounter;
     car.Model = "MSMQ-2007-" + messageCounter;
     car.Mileage = messageCounter;
     messageCounter++;

     // display the number of published message in the label
     counterLabel.Text = messageCounter.ToString();

     //publish message into the queue
     myMessageQueue.Send( car );
}

The message queue is identified by the <code>myMessageQueue</code> object. It is configured as a control added to the application from the Visual Studio Toolbox:.

myMessageQueue object has the following properties:

Objects published into the queue are instances of the Car class:

namespace ORBExamples
{
    [Serializable()]
    public class Car
    {
        private string make;
        private string model;
        private long mileage;

        public string Make
        {
            get { return make; }
            set { make = value; }
        }

        public string Model
        {
            get { return model; }
            set { model = value; }
        }

        public long Mileage
        {
            get { return mileage; }
            set { mileage = value; }
        }
    }
}

Notice the class has the Serializable attribute. The attribute is required since the MSMQ queue is configured to use binary message formatter. Additionally, it is important to compile the Car class in a separate class library and reference the project from Windows Publisher. The reason for such configuration is the class must be shared between the Publisher and the WebORB processes. When WebORB picks up a message from the queue, the object in the message is automatically deserialized. As a result, object's class in the message must be present in the WebORB memory space. Full source code listing and project file for the queue publisher application are available in the Resources section of this article.

WebORB Configuration

WebORB functions as a gateway between MSMQ queues and Flex clients. Flex client can use the <code>mx.messaging.Consumer</code> or <code>weborb.messaging.WeborbConsumer</code> API to receive messages from a queue. When a message is published in a queue, WebORB receives it and routes to the client. WebORB exposes MSMQ queues as messaging destinations. A queue must be configured as a destination in messaging-config.xml located in the [WEBORB-INSTALL]/WEB-INF/flex directory. The queue used by the Windows Publisher application shown above is <code>.\private$\weborb-mqpush</code>. To configure the queue as a Flex messaging destination, the following XML must be added to messaging-config.xml:

<destination id="mqtoflex">
  <properties>
    <msmq>
      <path>.\private$\weborb-mqpush</path>
      <!-- zero means 'do not send past messages'.
           Set to -1 to receive previously sent messages -->
      <deliverPastMessages>0</deliverPastMessages>
      <BasePriority>0</BasePriority>
      <Category>00000000-0000-0000-0000-000000000000</Category>
      <Label>WebORB MessageQueue for Messages from Windows client</Label>
      <MaximumQueueSize>4294967295</MaximumQueueSize>
      <UseJournalQueue>false</UseJournalQueue>
      <MaximumJournalSize>4294967295</MaximumJournalSize>
    </msmq>
  </properties>
  <channels>
    <channel ref="weborb-rtmp"/>
  </channels>
</destination>

The configuration node above registers the <code>mqtoflex</code> messaging destination. The destination is mapped to the same MSMQ queue used by the Windows Publisher. The <code><msmq></code> node contains additional properties configuring the queue. You can see their description in messaging-config.xml included with the WebORB distribution.

Developing Flex Client

Flex client can use either the <code>mx.messaging.Consumer</code> or <code>weborb.messaging.WeborbConsumer</code> API to subscribe to a messaging destination.

When a message is available in a destination, WebORB delivers it to the subscribers. In this example, the destination is linked with MSMQ, as a result, the source of messages is a message queue. WebORB will deliver all message published in the queue to Flex.

Creating a Flex consumer requires very little code. You need to know the name of the messaging destination and must specify a function to be called when a message arrives. The function is added as a listener for the <code>MessageEvent.MESSAGE</code> event:

import weborb.messaging.WeborbConsumer;
import
mx.messaging.events.MessageEvent; [Bindable]
private
var
car:Car;
private
var
consumer:WeborbConsumer;

public
function doConnect():void
{
  consumer = new WeborbConsumer();
  consumer.destination = "mqtoflex";
  consumer.addEventListener( MessageEvent.MESSAGE, receivedMessage );
  consumer.subscribe();
}

Processing received messages takes place in the receivedMessage function:

public function receivedMessage( event:MessageEvent ):void
{
  // store the value in a local 'bindable' variable
  // UI will display properties through the data binding

  car = Car( event.message.body );
}

Arrived messages contain instances of the ActionScript Car class. It is important to instruct the client runtime to map server-side objects to the corresponding client-side type. The function call shown below accomplishes that:

// init is called through the creationComplete event
public
function
init():void
{
  // map server-side to the client-side type
  // ORBExamples.Car is a full type name of the class
  // of the objects sent by the server
  // Car is a client-side class the remote objects
  // should be mapped to

  flash.net.registerClassAlias( "ORBExamples.Car", Car );
}

The Car class used in the client program has the same structure and field names as the remote counterpart:

package
{
  [Bindable]
  public class Car
  {
    public var Make:String;
    public var Model:String;
    public var Mileage:Number;
  }
}

Full source code listing and a Flex Builder project are available in the Resources section of the article.

Running the Example

Follow the steps below to run the example:

  1. Download publisher and 'shared classes' projects, compile and run Windows Publisher.
  2. Download and install WebORB. Make sure WebORB messaging destination is added to messaging-config.xml.
  3. Deploy shared classes assembly into weborb, by copying the DLL into the /bin folder under WebORB installation root directory.
  4. Open a command prompt window and change the directory to the WebORB product installation (/Inetpub/wwwroot/weborb30)
  5. Run weborbee.exe. This is the standalone mode of the WebORB Messaging Server. It runs as an independent process and does not require IIS.
  6. Download flex project, compile and run Flex client.
  7. Click 'Connect' in the Flex client interface. You should see some activity in the weborbee process.
  8. Click 'Start' in the Windows Publisher window. Messages will be published to MSMQ and delivered to Flex.

Things to try:

  • Add additional Flex clients, connect and see messages delivered to all Flex clients;
  • Try stopping and starting Windows Publisher;
  • Open Control Panel > Administrative Tools > Computer Management > Services and Applications > Message Queing > Private Queues. Locate the weborb-mppush queue and check the queue messages.

Conditional Message Delivery

In the example above WebORB unconditionally  delivers all MSMQ messages to every Flex client. It is also possible to add conditional logic in the message delivery chain. Starting with the version 3.2.0.0, WebORB supports message selectors. A selector is a special server-side class associated with a messaging destination. If a selector is configured, WebORB passes every message received from the queue to the selector object. The selector can either transform the message or instruct WebORB to cancel message delivery to a consumer.

A selector class must implement the following interface:

namespace Weborb.Messaging.V3
{
  public interface IMessageSelector
  {
    /**
     * Passes the selector value from consumer.
     * Consumer instances can assign a value to the
     * 'selector' property of the Consumer class
     */

    void setClientSelectorValue( String selectorValue );

    /**
     * Process a message originally sent by a Flex publisher.
     * Return null to cancel message delivery.
     */

    Object processClientMessage( V3Message message );

    /**
     * Process a message sent from a non-Flex client.
     * Return null to cancel message delivery.
     */

    Object processServerMessage( Object message );

    /**
     * Set the id of a client associated with this selector
     */

    void setClientID( String clientID );
  }
}

Below is a sample implementation which can be used with the example from this article. Selector is invoked every time before a message is sent to a client. The selector can either change the message to be sent to the client or return null to cancel message delivery.

using System;
using
Weborb.Messaging.V3;
using
Weborb.V3Types;

namespace
ORBExamples.Messaging
{
    public class CustomSelector : IMessageSelector
    {
        private string clientID;


       
public void setClientSelectorValue( String selectorValue )
         {
         }

        public object processClientMessage( V3Message message )
        {
            // no filtering for messages published from Flex clients
            return message;
        }

        public object processServerMessage( object message )
        {
            Car carObj = (Car) message;
          
            // rollback a few miles.
            // don't tell anyone we did it:
            carObj.Mileage /= 2;
            return carObj;
        }

        public void setClientID( string clientID )
        {
            this.clientID = clientID;
        }
    }
}

To configure a selector class, enter its full type name in the node of your destination configuration in WEB-INF/flex/messaging-config.xml. For example, to register the selector shown above, use the following configuration:

<destination id="mqtoflex">
  <properties>
    <selector>
ORBExamples.Messaging.CustomSelector</selector>
    <msmq>
      <path>.\private$\weborb-mqpush</path>
      <!-- zero means 'do not send past messages'.
           Set to -1 to receive previously sent messages -->
      <deliverPastMessages>0</deliverPastMessages>
      <BasePriority>0</BasePriority>
      <Category>00000000-0000-0000-0000-000000000000</Category>
      <Label>WebORB MessageQueue for Messages from Windows client</Label>
      <MaximumQueueSize>4294967295</MaximumQueueSize>
      <UseJournalQueue>false</UseJournalQueue>
      <MaximumJournalSize>4294967295</MaximumJournalSize>
    </msmq>
  </properties>
  <channels>
    <channel ref="weborb-rtmp"/>
  </channels>
</destination>

It is also possible to identify a client with an ID. The subscribe() method can optionally accept client ID as a string value. WebORB passes client ID to the message selector using the setClientID() call. Additionally, if a consumer needs to pass a value into the selector in the runtime, it can use the selector property available in the consumer class. As soon as a value is assigned, the client sends it to the server and WebORB passes it to the destination's selector object.