Categories

  • An excellent post on delivering real-time updates from .NET to JavaScript via WebSockets by using WebORB for .NET: http://t.co/8ONjyw59
  • We're working on some cool samples demonstrating Sencha component integration with WebORB's websockets and data management. Stay tuned.
  • For all Flexers out there, check out the following blog post, looks like a problem in ArrayCollection serialization: http://t.co/qbZuTEhy
  • none - intentionally blocks websocket handshake responses. Not only they do not support it, they do not allow others either

Archives

WebORB Data Services Plugin for Flash Builder

If you develop with Flash Builder and use WebORB, read on, you will greatly enjoy this new functionality. The functionality is not entirely new, we had the plugin for quite some time. The main problem most users have encountered with the plugin was the installation process. We have fully reimplemented the plugin and added better integration support in the product itself.

The plugin now can be installed using Eclipse’s standard plugin installation process. To get started, make sure to download and install the latest nightly build of the product (or version 4.5 once it becomes available). To install the plugin:

  1. From the main menu select Help and then ‘Install New Software’
  2. Enter the following address for the plugin’s “update site” and press Enter:
    http://dev.themidnightcoders.com/fb
  3. Select the checkbox next to “WebORB plugins for Flash Builder”. The window in Eclipse/Flash Builder should look as shown in the image below:
  4. Click through the installation wizard to complete the installation.
  5. Click OK if you get a security warning saying the software is unsigned.
  6. Once the installation is complete Flash Builder/Eclipse will offer a choice of applying the changes or restarting the application. Make sure to choose the restart option.

For the instructions on how to use the plugin, see WebORB documentation:

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;
import weborb.ORBConstants;
import weborb.config.FlexMessagingServiceConfig;
import weborb.config.ORBConfig;
import weborb.config.ORBServerConfig;
import weborb.management.messaging.FlexMessagingDestination;
import weborb.messaging.v3.MessagingDestination;
import weborb.messaging.v3.MessagingServiceHandler;
import weborb.v3types.core.DataServices;

import java.util.Hashtable;

public class DestinationFactory
{
  public String createMessagingDestination( String name ) throws Exception
  {
    // create destination object. This is as basic as it gets, constructor with the destination name
    MessagingDestination destination = new MessagingDestination( name );

    // setup the most basic properties - the name of the class handling
    // subscriptions and publications and a class where the messages are stored
    // until they are retrieved by the consumers.
    Hashtable properties = new Hashtable();
    properties.put( ORBConstants.MESSAGE_STORAGE_POLICY, "weborb.messaging.v3.MemoryStoragePolicy" );
    properties.put( ORBConstants.MESSAGE_SERVICE_HANDLER, "weborb.messaging.v3.MessagingServiceHandler" );

    // register properties
    destination.setProperties( properties );

    // initialize handler from the properties
    destination.setConfigServiceHandler();

    // register the destination
    DataServices dataServices = ORBConfig.getORBConfig().getDataServices();
    dataServices.getDestinationManager().addDestination( name, destination );

    // REGISTERING DESTINATION SO IT IS VISIBLE IN THE MANAGEMENT CONSOLE
    // The following two lines are needed if you would like the destination
    // to appear in the management console, therefore the code below is optional

    // set the channel name, so the console knows how to connect to the destination
    // in the "Test Drive" mode.
    destination.setChannelName( "my-polling-amf" );
    FlexMessagingServiceConfig serviceConfig = ORBServerConfig.getFlexMessagingServiceConfig();
    serviceConfig.addFlexMessagingDestination( FlexMessagingDestination.getDestinationScope( destination ) );
    return name;
  }
}

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.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
			   xmlns:s="library://ns.adobe.com/flex/spark"
			   xmlns:mx="library://ns.adobe.com/flex/mx"
			   width="100%" height="100%" creationComplete="init()">
  <s:layout>
    <s:FormLayout/>
  </s:layout>
  <s:states>
    <s:State name="InitialState"/>
    <s:State name="DestinationCreated"/>
  </s:states>
  <fx:Declarations>
    <!-- Place non-visual elements (e.g., services, value objects) here -->
  </fx:Declarations>
  <fx:Script>
    <![CDATA[
  import mx.controls.Alert;
  import mx.messaging.ChannelSet;
  import mx.messaging.Consumer;
  import mx.messaging.Producer;
  import mx.messaging.channels.AMFChannel;
  import mx.messaging.events.MessageEvent;
  import mx.messaging.messages.AsyncMessage;
  import mx.rpc.events.FaultEvent;
  import mx.rpc.events.ResultEvent;
  import mx.rpc.remoting.RemoteObject;
  import weborb.messaging.WeborbMessagingChannel;

  private var remoteService:RemoteObject;
  private var consumer:Consumer;
  private var producer:Producer;

  public function init():void
  {
    remoteService = new RemoteObject( "GenericDestination" );
    remoteService.source = "demo.messaging.destination.DestinationFactory";
    remoteService.createMessagingDestination.addEventListener( ResultEvent.RESULT, destinationCreated );
    remoteService.createMessagingDestination.addEventListener( FaultEvent.FAULT, gotError );
  }

  private function destinationCreated( evt:ResultEvent ):void
  {
    currentState = "DestinationCreated";

    consumer = new Consumer();
    consumer.destination = evt.result as String;
    //var channel:AMFChannel = new AMFChannel( "custom-amf-channel", "weborb.wo" );
    var channel:WeborbMessagingChannel = new WeborbMessagingChannel( "custom-rtmp-channel", "rtmp://localhost/root" );
    var channelSet:ChannelSet = new ChannelSet();
    channelSet.addChannel( channel );
    consumer.channelSet = channelSet;
    consumer.addEventListener( MessageEvent.MESSAGE, gotMessage );
    consumer.subscribe();

    producer = new Producer();
    producer.destination = evt.result as String;
    producer.channelSet = channelSet;
  }

  private function gotError( evt:FaultEvent ):void
  {
    Alert.show( "Server reported an error: " + evt.fault.faultDetail );
  }

  private function createDestination():void
  {
    remoteService.createMessagingDestination( destinationName.text );
  }

  private function sendMessage():void
  {
    var asyncMessage:AsyncMessage = new AsyncMessage( messageText.text );
    producer.send( asyncMessage );
  }

  private function gotMessage( evt:MessageEvent ):void
  {
    log.text = evt.message.body.toString() + "\n" + log.text;
  }
]]>
</fx:Script>
  <s:HGroup width="100%" paddingBottom="2" paddingTop="2" verticalAlign="middle">
    <s:Label width="150" text="Destination Name:"/>
    <s:TextInput id="destinationName"/>
    <s:Button label="Create Destination" click="createDestination()"/>
  </s:HGroup>
  <s:HGroup width="100%" paddingBottom="2" paddingTop="2" verticalAlign="middle">
    <s:Label width="150" text="Message:"/>
    <s:TextInput id="messageText"/>
    <s:Button label="Send" click="sendMessage()" enabled="false"
      enabled.DestinationCreated="true"/>
  </s:HGroup>
  <s:HGroup width="100%" height="200">
    <s:TextArea id="log" width="413" height="100%"/>
  </s:HGroup>
</s:Application>

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.

Data Paging for Flex - Efficient Server-Side Data Retrieval

Loading too much data into a Flex application can easily present a problem. Flex data components like lists or datagrids do not deal with very large data providers very well. Additionally, fetching a lot of data from the server may have a significant impact on the application’s performance as the client-side memory footprint of the application can grow to be quite large. A common solution for these problems is data paging. The entire dataset is split into blocks (pages) and a page of data is loaded on  the as-needed basis (for example, when the application user tries to scroll through the data in a datagrid).

To simplify this task for Flex developers, we introduced an API and a Flex data component which makes it possible to dynamically fetch data from Java. .NET or PHP services. The component can be used as a data provider for any Flex data-bound UI component. Additionally, we implemented a very powerful memory management system which makes sure that only specified number of pages is kept in memory. That way, you can easily visualize a data set with millions of records in a single data grid without loading all the records into memory.

The video below reviews an example illustrating the usage of the APIs. The example is also available live at the URL below:
http://examples.themidnightcoders.com/blog/findharley/FindHarleyWeb.html

The source code for the example and the sample database is available at the bottom of this post. Enjoy!

Source code and Database resources:

Deployment instructions:

  1. Download and install WebORB for Java.
  2. Create ‘findharley’ database schema (database) and restore the database by using the SQL script. The server side code uses the root/sa userid and password. You can grant access permissions for the database to another user and modify the Java code to use different credentials.
  3. Compile the server-side code. Make sure to update the JDBC connection string with the updated userid and password – line 221 in FHService.java (see the item above).
  4. The compiled server-side code can be deployed as .class files into WebORB’s WEB-INF/classes folder or as a jar file into WEB-INF/lib
  5. Open the client-side project in Flash Builder, adjust the server-side path, the path to weborb-services-config.xml for the -services compiler argument and Flash Build Path.
  6. Obtain a Google Maps API key from the following page: http://code.google.com/apis/maps/signup.html
  7. Replace the following string PUT-YOUR-GOOGLE-MAPS-API-KEY-HERE in src/FindHarleyWeb.mxml with your Google Maps API key.

Flex Remoting URLs and Understanding the 'Send Failed' error

One of the most frequently talked about subjects on our discussion forums is the one about the Flex’s ‘Send Failed’ error. Pretty much in all of the cases, the error is due to misconfiguration. The observation I made is the configuration problems arose primarily because of the lack of understanding on the developer’s part of how Flex resolves the remoting URLs. To clarify the subject we recorded a short video/presentation which you can access below. The video also describes how one might receive the Send Failed error and what can be done to solve it. Enjoy!

Flex to .NET Chat Client Using Remote Shared Objects

Integrating .NET applications with other client technologies (or even .NET to .NET) may not seem to be a trivial task. I believe Microsoft has done a great job providing a fairly closed technology stack where things work as long as you stick to Microsoft’s prescription of how to go about solving problems. Take for example the task of creating a multi client messaging system between a .NET application and Flex, AIR, Android or iOS client and you will shortly feel the pain. The real challenge is the .NET messaging framework is not very open to accomodate client applications of other than native .NET or ASP.NET. As a result, you will need a messaging server which will serve the purpose of routing broker and messaging “translator” between heterogeneous client applications.

Earlier this month I wrote about Remote Shared Objects and the benefits the feature provides. Since remote shared objects are no longer a feature exclusive to Flash, Flex and AIR clients I put together a messaging example demonstrating how .NET applications can efficiently communicate with Flex and AIR  (and thus Android,  iOS and Blackberry Playbook). The .NET application is a simple (console-based) chat program which uses remote shared objects to exchange data with a Flex client. The Remote Shared Object API and RTMP connectivity comes with the RTMPClient class available in WebORB for .NET. Here’s the full listing of the C# code with an explanation right after the listing:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Weborb.Client;
using Weborb.Messaging.Net.RTMP;
using Weborb.Messaging.Api.Service;
using Weborb.Messaging.Api.SO;

namespace WeborbClientTest
{
  class Program : IPendingServiceCallback, ISharedObjectListener
  {
    private ThreadStart threadStart;
    private Thread chatThread;
    private AutoResetEvent rsoIsReady = new AutoResetEvent( false );

    private RTMPClient rtmpClient;
    private IClientSharedObject rso;

    static void Main( string[] args )
    {
      Program chatClient = new Program();
      chatClient.StartChat();
    }

    public void StartChat()
    {
      rtmpClient = new RTMPClient();
      rtmpClient.setServiceProvider( this );

      System.Console.WriteLine( "Connecting to the RTMP server running at localhost:2037" );
      rtmpClient.connect( "localhost", 2037, "Chat", null, this );

      threadStart = new ThreadStart( MainChat );
      chatThread = new Thread( threadStart );
      chatThread.Start();
      chatThread.IsBackground = false;
    }

    public void MainChat()
    {
      rsoIsReady.WaitOne();

      System.Console.WriteLine( "Connecting to the 'ChatSO' remote shared object" );
      rso = rtmpClient.getSharedObject( "ChatSO", false );
      rso.addSharedObjectListener( this );

      while( true )
      {
        System.Console.WriteLine( "Enter a message to put into RSO. Press \"Enter\" to stop the loop:" );
        String messageText = System.Console.ReadLine();

        if( messageText.Equals( "" ) )
          break;

        Hashtable messageObject = new Hashtable();
        messageObject[ "imText" ] = messageText;
        messageObject[ "username" ] = ".NET Client";
        messageObject[ "color" ] = 0;
        messageObject[ "isBold" ] = false;
        messageObject[ "isItalics" ] = false;
        messageObject[ "isUnderline" ] = false;

        rso.setAttribute( "UserMessage", messageObject );
      }
    }

    public void resultReceived( IPendingServiceCall call )
    {
      System.Console.WriteLine( "RTMP client connected" );
      rsoIsReady.Set();
    }

    public void onSharedObjectClear( ISharedObjectBase so )
    {
      System.Console.WriteLine( "EVENT: onSharedObjectClear" );
    }

    public void onSharedObjectConnect( ISharedObjectBase so )
    {
      System.Console.WriteLine( "EVENT: onSharedObjectConnect" );
    }

    public void onSharedObjectDelete( ISharedObjectBase so, string key )
    {
      System.Console.WriteLine( "EVENT: onSharedObjectDelete" );
    }

    public void onSharedObjectDisconnect( ISharedObjectBase so )
    {
      System.Console.WriteLine( "EVENT: onSharedObjectDisconnect" );
    }

    public void onSharedObjectSend( ISharedObjectBase so, string method, IList parms )
    {
      System.Console.WriteLine( "EVENT: onSharedObjectSend" );
    }

    public void onSharedObjectUpdate( ISharedObjectBase so, IDictionary<string, object> values )
    {
      System.Console.WriteLine( "EVENT: onSharedObjectUpdate" );
    }

    public void onSharedObjectUpdate( ISharedObjectBase so, Weborb.Messaging.Api.IAttributeStore values )
    {
      System.Console.WriteLine( "EVENT: onSharedObjectUpdate" );
    }

    public void onSharedObjectUpdate( ISharedObjectBase so, string key, object value )
    {
      System.Console.WriteLine( "EVENT: onSharedObjectUpdate" );

      Hashtable messageData = (Hashtable) value;
      System.Console.WriteLine( "property " + key + ",  imText value " + messageData[ "imText" ] );
    }
  }
}

The StartChat method is where the program connects to the localhost server running on port 2037 (WebORB’s default RTMP port). The “Chat” parameter is the name of the messaging application the client connects to. The main chat logic is in the MainChat method. As you can see from the code the MainChat method is executed by a separate thread. The reason for this is the process of establishing a connection and receiving a notification that the connection has been established (lines 34 and 72) is asynchronous. As a result, a separate thread is required so the main method of the application does not end prematurely.

Inside of the MainChat method, the code uses the getSharedObject method to obtain a reference to the specified remote shared object – ChatSO (line 47). A listener object is added to the remote shared object instance so the application receives all the RSO events, including the one when the RSO is updated (lines 111-117).

You can download the complete project from the following URL: http://examples.themidnightcoders.com/blog/RSOClient.zip

To run the example and experience the feature:

  1. Compile the example code (you might need to set the weborb.dll assembly reference)
  2. Run the WebORB Management Console
  3. Run the .NET application
  4. In the management console switch to the Help/Resources tab, then click the Examples link
  5. In the examples tree in the console navigate to: FLEX Examples > Real-time Messaging (RTMP) > Basic Text Chat
  6. Type in a send messages both in the Flex and .NET clients – both send and receive data

To see the contents of the Remote Shared Object used in the sample .NET application switch to the Messaging Server tab in the Management Console, select the Chat node in the tree, then select the Shared Objects tab. As the clients send data, the console shows the internal state of the shared object.

Exactly the same approach and APIs are applicable if you build Android and iOS mobile applications. I plan to write a similar post demonstrating cross platform connectivity and messaging between .NET and Android and iOS clients.

Here’s a brief video showing the example in action:

Building a Data-Driven Flex and Java Application with WebORB for Java

If you are looking for an alternative to Live Cycle Data Services (LCDS) to do Flex data management, WebORB for Java (Enterprise Edition or Community Edition) is a great alternative. Ken Nelson from San Clemente Technology wrote an excellent tutorial on how to do data management using WebORB, which is posted on the Adobe Developer Connection site. Here is an excerpt from his article:

“In this article I will show you how to build a data driven application in Flex using WebORB for Java. You will learn how to connect WebORB to your database, use WebORB for Java to generate your database access code, and integrate the generated code with your Flex project.”

The complete article with sample code can be viewed here:

http://www.adobe.com/devnet/flex/articles/datadriven-flex-java-applications.html

Tell us what additional tutorial and topics would be of interest to you.

Java Object Access in Google App Engine from Flex/Flash, Silverlight, JavaScript and Android

One of the new features in WebORB for Java v.4.1 is support for Google App Engine integration. With the integration any Java class or Spring bean deployed into a Google App Engine application can be accessed by all the client types supported by WebORB. The list of the supported clients includes: Flex/Flash, Silverlight, JavaScript/AJAX, Android, Windows Phone and in the very near future iOS clients. The clients can invoke methods on the deployed Java services and exchange data using primitive and complex types, arrays, collections, etc. By using WebORB as the client/server integration tier, your application will greatly benefit from the superior performance enabled by the product as well as significantly streamlined application development process.

To learn more about WebORB for Google App Engine, see the WebORB Documentation and/or watch the video below:

Accessing remote shared objects from Flex with WebORB for .NET

If you have a need to build a multi-user application that is automatically updated and synchronized across multiple clients whenever a change is made to the data, you may benefit from using Remote Shared Objects (RSO). A recent tutorial written by Damian Piccolo and Esteban Yofre at Anden Solutions may be just what you need to get started with using WebORB for client-to-server, server-to-client and client-to-client communication and synchronization with RSOs. Here is an excerpt from the article:

“RSOs are particularly useful when they are used on several clients at the same time. When one client changes data that updates the RSO on the server, the server sends the change to all other connected clients, enabling you to synchronize many different clients with the same data. RSOs can also be updated and accessed by the server, giving developers more options for application development. In this tutorial, you will use RSOs to create a simple online version of the Add-a-word game. The object of this game is to add a word to a sentence, one user at a time, and eventually come up with a very long sentence (that still makes sense)”.

Here is the link to the full tutorial:

http://www.adobe.com/devnet/flex/articles/flex-dotnet-remote-shared-objects.html

Integrating Flex Applications with NHibernate

Are you using NHibernate as your object-relational mapper? If so, did you know that WebORB provides an easy integration between Flex clients and NHibernate models? Enterprise Architect Joseph Magley demonstrates how to use WebORB with NHibernate and Flex in a recent technical article he wrote for the Adobe Developer Connection. Here is an excerpt from this article:

“In this tutorial I demonstrate a particularly easy-to-use combination of technologies that do a very good job at allowing you to focus on developing your features rather than maintaining plumbing. Modern development tools coupled with WebORB for .NET and NHibernate make it easier to maintain integration points. Development frameworks for data access such a NHibernate eliminate much of the glue code that developers often need to write and maintain. This decreases complexity and creates a solid environment for rapid development of RIAs.”

The complete article with sample code can be viewed here: http://www.adobe.com/devnet/flex/articles/flex-nhibernate.html

Pushing Data from Flex to .NET Using WebORB, Apache NMS and ActiveMQ

Developer Gaurav Pandey recently wrote a technical article that shows how to use WebORB with Apache NMS and Apache ActiveMQ. Here is an excerpt from his article.

“The WebORB for .NET messaging framework has been integrated with Apache NMS and is capable of connecting messaging destinations with NMS destinations. This enables Flex applications to deliver data to and retrieve data from any NMS-compatible messaging provider such as Apache ActiveMQ or Microsoft Messaging Queue (MSMQ) with minimal configuration. WebORB acts as a proxy between the Flex clients and the NMS destination. This article provides an overview of pushing data from a Flex publisher client to a Flex consumer client using an ActiveMQ messaging provider.”

To view the entire article with sample code, please visit http://www.adobe.com/devnet/flex/articles/flex-apache-nms.html