Categories

Archives

Dynamic Messaging Destinations for Flex and other clients

Messaging destinations is the central concept in publish/subscribe messaging supported by WebORB. The feature is available for Flex, AIR, Javascript, native Java/Android, and .NET clients. A program can be in the role of producer or consumer (or both). Producers publish messages into a destination and consumers subscribe to receive published messages. Typically messaging destinations are registered in a configuration file (WEB-INF/flex/messaging-config.xml), however, WebORB also supports destinations created at run-time – thus called dynamic messaging destinations. The dynamic nature of the destinations can add a lot of flexibility to applications relying on publish/subscribe messaging. For instance, one can easily create a short-lived messaging destination for quick message exchange or some private messaging. The example below demonstrates Java code registering a dynamic destination using the WebORB for Java API:

package demo.messaging.destination;&lt;br /&gt;<br />
import weborb.ORBConstants;&lt;br /&gt;<br />
import weborb.config.FlexMessagingServiceConfig;&lt;br /&gt;<br />
import weborb.config.ORBConfig;&lt;br /&gt;<br />
import weborb.config.ORBServerConfig;&lt;br /&gt;<br />
import weborb.management.messaging.FlexMessagingDestination;&lt;br /&gt;<br />
import weborb.messaging.v3.MessagingDestination;&lt;br /&gt;<br />
import weborb.messaging.v3.MessagingServiceHandler;&lt;br /&gt;<br />
import weborb.v3types.core.DataServices;&lt;/p&gt;<br />
&lt;p&gt;import java.util.Hashtable;&lt;/p&gt;<br />
&lt;p&gt;public class DestinationFactory&lt;br /&gt;<br />
{&lt;br /&gt;<br />
  public <div style="display: none"><a href='http://ccialisonlinee.com' title='cialis online without prescription'>cialis online without prescription</a></div> String createMessagingDestination( String name ) throws Exception&lt;br /&gt;<br />
  {&lt;br /&gt;<br />
    // create destination object. This is as basic as it gets, constructor with the destination name&lt;br /&gt;<br />
    MessagingDestination destination = new MessagingDestination( name );&lt;/p&gt;<br />
&lt;p&gt;    // setup the most basic properties - the name of the class handling&lt;br /&gt;<br />
    // subscriptions and publications and a class where the messages are stored&lt;br /&gt;<br />
    // until they are retrieved by the consumers.&lt;br /&gt;<br />
    Hashtable properties = new Hashtable();&lt;br /&gt;<br />
    properties.put( ORBConstants.MESSAGE_STORAGE_POLICY, &amp;quot;weborb.messaging.v3.MemoryStoragePolicy&amp;quot; );&lt;br /&gt;<br />
    properties.put( ORBConstants.MESSAGE_SERVICE_HANDLER, &amp;quot;weborb.messaging.v3.MessagingServiceHandler&amp;quot; );&lt;/p&gt;<br />
&lt;p&gt;    // register properties&lt;br /&gt;<br />
    destination.setProperties( properties );&lt;/p&gt;<br />
&lt;p&gt;    // initialize handler from the properties&lt;br /&gt;<br />
    destination.setConfigServiceHandler();&lt;/p&gt;<br />
&lt;p&gt;    // register the destination&lt;br /&gt;<br />
    DataServices dataServices = ORBConfig.getORBConfig().getDataServices();&lt;br /&gt;<br />
    dataServices.getDestinationManager().addDestination( name, destination );&lt;/p&gt;<br />
&lt;p&gt;    // REGISTERING DESTINATION SO IT IS VISIBLE IN THE MANAGEMENT CONSOLE&lt;br /&gt;<br />
    // The following two lines are needed if you would like the destination&lt;br /&gt;<br />
    // to appear in the management console, therefore the code below is optional&lt;/p&gt;<br />
&lt;p&gt;    // set the channel name, so the console knows how to connect to the destination&lt;br /&gt;<br />
    // in the &amp;quot;Test Drive&amp;quot; mode.&lt;br /&gt;<br />
    destination.setChannelName( &amp;quot;my-polling-amf&amp;quot; );&lt;br /&gt;<br />
    FlexMessagingServiceConfig serviceConfig = ORBServerConfig.getFlexMessagingServiceConfig();&lt;br /&gt;<br />
    serviceConfig.addFlexMessagingDestination( FlexMessagingDestination.getDestinationScope( destination ) );&lt;br /&gt;<br />
    return name;&lt;br /&gt;<br />
  }&lt;br /&gt;<br />
}&lt;br /&gt;<br />

To further demonstrate how dynamic destinations can be used with the Flex client, see the following Flex application code. The application’s workflow consists of the following steps:

  1. User enters a name for a dynamic destination to create and pressed the Create Destination button.
  2. Flex client invokes the createMessagingDestination Java method shown above.
  3. When the remote method invocation returns a result, the Flex client constructs a Producer and a Consumer objects. The consumer is subscribed to the newly created destination.
  4. When the user enters text and clicks the Send Message button, the Flex client uses the Producer object to publish the message into the destination.
  5. The consumer object receives the message from the destination and displays it in the text area.

&lt;br /&gt;<br />
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;br /&gt;<br />
&amp;lt;s:Application xmlns:fx=&amp;quot;http://ns.adobe.com/mxml/2009&amp;quot;&lt;br /&gt;<br />
			   xmlns:s=&amp;quot;library://ns.adobe.com/flex/spark&amp;quot;&lt;br /&gt;<br />
			   xmlns:mx=&amp;quot;library://ns.adobe.com/flex/mx&amp;quot;&lt;br /&gt;<br />
			   width=&amp;quot;100%&amp;quot; height=&amp;quot;100%&amp;quot; creationComplete=&amp;quot;init()&amp;quot;&amp;gt;&lt;br /&gt;<br />
  &amp;lt;s:layout&amp;gt;&lt;br /&gt;<br />
    &amp;lt;s:FormLayout/&amp;gt;&lt;br /&gt;<br />
  &amp;lt;/s:layout&amp;gt;&lt;br /&gt;<br />
  &amp;lt;s:states&amp;gt;&lt;br /&gt;<br />
    &amp;lt;s:State name=&amp;quot;InitialState&amp;quot;/&amp;gt;&lt;br /&gt;<br />
    &amp;lt;s:State name=&amp;quot;DestinationCreated&amp;quot;/&amp;gt;&lt;br /&gt;<br />
  &amp;lt;/s:states&amp;gt;&lt;br /&gt;<br />
  &amp;lt;fx:Declarations&amp;gt;&lt;br /&gt;<br />
    &amp;lt;!-- Place non-visual elements (e.g., services, value objects) here --&amp;gt;&lt;br /&gt;<br />
  &amp;lt;/fx:Declarations&amp;gt;&lt;br /&gt;<br />
  &amp;lt;fx:Script&amp;gt;&lt;br /&gt;<br />
    &amp;lt;![CDATA[&lt;br /&gt;<br />
  import mx.controls.Alert;&lt;br /&gt;<br />
  import mx.messaging.ChannelSet;&lt;br /&gt;<br />
  import mx.messaging.Consumer;&lt;br /&gt;<br />
  import mx.messaging.Producer;&lt;br /&gt;<br />
  import mx.messaging.channels.AMFChannel;&lt;br /&gt;<br />
  import mx.messaging.events.MessageEvent;&lt;br /&gt;<br />
  import mx.messaging.messages.AsyncMessage;&lt;br /&gt;<br />
  import mx.rpc.events.FaultEvent;&lt;br /&gt;<br />
  import mx.rpc.events.ResultEvent;&lt;br /&gt;<br />
  import mx.rpc.remoting.RemoteObject;&lt;br /&gt;<br />
  import weborb.messaging.WeborbMessagingChannel;&lt;/p&gt;<br />
&lt;p&gt;  private var remoteService:RemoteObject;&lt;br /&gt;<br />
  private var consumer:Consumer;&lt;br /&gt;<br />
  private var producer:Producer;&lt;/p&gt;<br />
&lt;p&gt;  public function init():void&lt;br /&gt;<br />
  {&lt;br /&gt;<br />
    remoteService = new RemoteObject( &amp;quot;GenericDestination&amp;quot; );&lt;br /&gt;<br />
    remoteService.source = &amp;quot;demo.messaging.destination.DestinationFactory&amp;quot;;&lt;br /&gt;<br />
    remoteService.createMessagingDestination.addEventListener( ResultEvent.RESULT, destinationCreated );&lt;br /&gt;<br />
    remoteService.createMessagingDestination.addEventListener( FaultEvent.FAULT, gotError );&lt;br /&gt;<br />
  }&lt;/p&gt;<br />
&lt;p&gt;  private function destinationCreated( evt:ResultEvent ):void&lt;br /&gt;<br />
  {&lt;br /&gt;<br />
    currentState = &amp;quot;DestinationCreated&amp;quot;;&lt;/p&gt;<br />
&lt;p&gt;    consumer = new Consumer();&lt;br /&gt;<br />
    consumer.destination = evt.result as String;&lt;br /&gt;<br />
    //var channel:AMFChannel = new AMFChannel( &amp;quot;custom-amf-channel&amp;quot;, &amp;quot;weborb.wo&amp;quot; );&lt;br /&gt;<br />
    var channel:WeborbMessagingChannel = new WeborbMessagingChannel( &amp;quot;custom-rtmp-channel&amp;quot;, &amp;quot;rtmp://localhost/root&amp;quot; );&lt;br /&gt;<br />
    var channelSet:ChannelSet = new ChannelSet();&lt;br /&gt;<br />
    channelSet.addChannel( channel );&lt;br /&gt;<br />
    consumer.channelSet = channelSet;&lt;br /&gt;<br />
    consumer.addEventListener( MessageEvent.MESSAGE, gotMessage );&lt;br /&gt;<br />
    consumer.subscribe();&lt;/p&gt;<br />
&lt;p&gt;    producer = new Producer();&lt;br /&gt;<br />
    producer.destination = evt.result as String;&lt;br /&gt;<br />
    producer.channelSet = channelSet;&lt;br /&gt;<br />
  }&lt;/p&gt;<br />
&lt;p&gt;  private function gotError( evt:FaultEvent ):void&lt;br /&gt;<br />
  {&lt;br /&gt;<br />
    Alert.show( &amp;quot;Server reported an error: &amp;quot; + evt.fault.faultDetail );&lt;br /&gt;<br />
  }&lt;/p&gt;<br />
&lt;p&gt;  private function createDestination():void&lt;br /&gt;<br />
  {&lt;br /&gt;<br />
    remoteService.createMessagingDestination( destinationName.text );&lt;br /&gt;<br />
  }&lt;/p&gt;<br />
&lt;p&gt;  private function sendMessage():void&lt;br /&gt;<br />
  {&lt;br /&gt;<br />
    var asyncMessage:AsyncMessage = new AsyncMessage( messageText.text );&lt;br /&gt;<br />
    producer.send( asyncMessage );&lt;br /&gt;<br />
  }&lt;/p&gt;<br />
&lt;p&gt;  private function gotMessage( evt:MessageEvent ):void&lt;br /&gt;<br />
  {&lt;br /&gt;<br />
    log.text = evt.message.body.toString() + &amp;quot;\n&amp;quot; + log.text;&lt;br /&gt;<br />
  }&lt;br /&gt;<br />
]]&amp;gt;&lt;br /&gt;<br />
&amp;lt;/fx:Script&amp;gt;&lt;br /&gt;<br />
  &amp;lt;s:HGroup width=&amp;quot;100%&amp;quot; paddingBottom=&amp;quot;2&amp;quot; paddingTop=&amp;quot;2&amp;quot; verticalAlign=&amp;quot;middle&amp;quot;&amp;gt;&lt;br /&gt;<br />
    &amp;lt;s:Label width=&amp;quot;150&amp;quot; text=&amp;quot;Destination Name:&amp;quot;/&amp;gt;&lt;br /&gt;<br />
    &amp;lt;s:TextInput id=&amp;quot;destinationName&amp;quot;/&amp;gt;&lt;br /&gt;<br />
    &amp;lt;s:Button label=&amp;quot;Create Destination&amp;quot; click=&amp;quot;createDestination()&amp;quot;/&amp;gt;&lt;br /&gt;<br />
  &amp;lt;/s:HGroup&amp;gt;&lt;br /&gt;<br />
  &amp;lt;s:HGroup width=&amp;quot;100%&amp;quot; paddingBottom=&amp;quot;2&amp;quot; paddingTop=&amp;quot;2&amp;quot; verticalAlign=&amp;quot;middle&amp;quot;&amp;gt;&lt;br /&gt;<br />
    &amp;lt;s:Label width=&amp;quot;150&amp;quot; text=&amp;quot;Message:&amp;quot;/&amp;gt;&lt;br /&gt;<br />
    &amp;lt;s:TextInput id=&amp;quot;messageText&amp;quot;/&amp;gt;&lt;br /&gt;<br />
    &amp;lt;s:Button label=&amp;quot;Send&amp;quot; click=&amp;quot;sendMessage()&amp;quot; enabled=&amp;quot;false&amp;quot;&lt;br /&gt;<br />
      enabled.DestinationCreated=&amp;quot;true&amp;quot;/&amp;gt;&lt;br /&gt;<br />
  &amp;lt;/s:HGroup&amp;gt;&lt;br /&gt;<br />
  &amp;lt;s:HGroup width=&amp;quot;100%&amp;quot; height=&amp;quot;200&amp;quot;&amp;gt;&lt;br /&gt;<br />
    &amp;lt;s:TextArea id=&amp;quot;log&amp;quot; width=&amp;quot;413&amp;quot; height=&amp;quot;100%&amp;quot;/&amp;gt;&lt;br /&gt;<br />
  &amp;lt;/s:HGroup&amp;gt;&lt;br /&gt;<br />
&amp;lt;/s:Application&amp;gt;&lt;br /&gt;<br />

Since the client code references the weborb.messaging.WeborbMessagingChannel class (needed only if the client-server publish/subscribe communication should be done via RTMP), the application must reference weborb.swc in the Flash Build Path of the project. The library is available at:

WebORB for Java – [WEBOBR INSTALL DIR]/webapp/weborbassets/wdm

WebORB for .NET – [WEBOBR INSTALL DIR]/weborbassets/wdm

Complete Flex project with the code shown above can be downloaded from:
http://examples.themidnightcoders.com/blog/dynamicdestinations/DynamicDestinationDemo.zip

Compiled Java code can be downloaded from (the file should be deployed into WEB-INF/lib):
http://examples.themidnightcoders.com/blog/dynamicdestinations/dynamicdestinations.jar

For more information about the Dynamic Destination API, see the corresponding section in the WebORB Documentation.

Prandin canadian pharmacy

Cross Platform Mobile Development using Real Time Messaging

Cross platform application connectivity is to be a frequently requested and talked about feature. A lot of enterprise and consumer-facing applications require  robust data exchange mechanism between application instances running on mobile devices. On top of this, many applications depend on real-time updates and notifications pushed from the server to the clients. One of the approaches for cross platform data exchange is a feature called Remote Shared Objects. The video below provides an explanation of the feature as well as a demonstration of iPhone, iPad and Windows Mobile phone communicating with each other as well as a browser-based Flex application.

The demo was built using the latest version of WebORB for .NET (the Java version would work just as well), Communication Library for iOS and a client library for Windows Mobile included into the WebORB distribution. Enjoy!

About Remote Shared Objects (RSO)

Does anyone know what remote shared object is? I have asked this question many times in various presentations to .net, java and flex user groups. In many cases, unless there are AdobeFlashers in the group, the answer is “no”. This is not surprising, Adobe have kept this hidden jewel pretty close to its chest, making the feature available exclusively to the users of Flash Media Server. In my opinion the feature is amazing and in many use-cases is essential for building interactive online, multi-user applications. So what is a remote shared object (RSO)? I find it easier to understand RSO if you think about it as a dictionary or a hashmap or just a map with

a collection of key/value pairs. Every key is a string and the corresponding value is an object of any type – primitive, string, date, typed/untyped object or an array of anything previously listed. RSOs reside on the server-side and are managed by an RTMP server. Every RSO has a logical name which the client applications use to connect to it. More than one client can connect to the same RSO and that’s when the magic happens. Since it is a dictionary of key/value pairs, any client can update a value for any key, create a new pair, or delete the contents of the RSO. Whenever any of these actions happen, all other clients connected to the same RSO are immediately notified of the change. The server keeps track of all the key/value pairs as well as the client connections to the RSO and pushes updates to all the connected clients. This simple client/server interaction makes it possible to implement some very sophisticated use-cases with just a few lines of code. For instance, creating a chat application using RSO can be done without any custom server-side code at all. All the client app needs to do is to put the chat message sent by the user into an RSO and all other users (client app instances) get notified about that update. Additionally, the RSO can also be modified by the server-side code, thus making it trivially easy to deliver data to multiple users at once.

As I mentioned earlier, in the Adobe’s world, the only server capable of supporting this feature is Flash Media Server targeting exclusively Flash/Flex apps. Since both WebORB for .NET and WebORB for Java implement the RTMP protocol, we have extended this feature to iOS (iPhone/iPad), Windows Phone, Silverlight, native Java and .NET apps in addition to Flash and Flex. On top of this, we made it super simple to push RSO updates from Java and .NET apps into all connected client applications. To see an example of this feature in action, please visit the following link (open the link in two or more browser windows to experience the example):

http://dev.themidnightcoders.com/tourdeflex/dotnet/examples/flex/messaging/ballcontrol/BallControl.html

I plan to post a few follow-on posts with examples on using RSOs from iOS, Windows Phone, Silverlight, Java and .NET clients.