Messaging from HTML to Flex 2

Inspired by a question that came across the internal mailing lists yesterday, I started kicking around the idea of having a Java servlet send a message available to a Flex application. With the new messaging subsystem of Flex 2, this type of communication (what I like to refer to as external push) is pretty straightforward. In the following post I will take a closer look at a simple JSP to Servlet to JMS to Flex 2 example.

To be sure, there’s already bountiful examples and documentation included with Flex 2 Beta 2 that is available on Adobe Labs, so this may very well be a reworking of something you’ve already seen before. I’m also not sure exactly what the use-case is for this scenario. Why would an HTML page delivered to one browser on some remote system, want to put data into a Flex application running in another browser on another remote system? In my case - because it can!

I started with the JSP as my HTML presentation for allowing the user to enter a message that’s sent to a servlet; and ultimately to Flex. In this case a simple form and input field will do the job nicely. I chose to have the form submit to a servlet, and also to use POST as the method of delivery. Once I’ve set up the form, I let the user know with a simple message as to whether or not the message was sent. The HTML code and rendering appears as follows.

<table>
  <tr>

    <!– Form that handles message value –>
    <form action=”/flex/servlet/PushServlet” method=”post”>
    <td>Send message:</td>
    <td><input type=”text” name=”txtMessage” /></td>
    <td><input type=”submit” value=”Send” /></td>
    </form>

  <tr>
  <tr>

    <!– Display context if no message has been sent –>
    <% if( request.getAttribute( “demo.fds2.message” ) == null ) { %>

      <td colspan=”3″>No message sent yet.</td>

    <!– If a message has been sent then display that value –>
    <% } else { %>

      <td>Last message:</td>
      <td colspan=”2″>
        <%= request.getAttribute( “demo.fds2.message” ) %>
      </td>

    <% } %>

  </tr>
</table>

jsp-message.gif

Now that I’ve got an HTML presentation for my simple application, I need a servlet to process that data on the server. This falls into two parts which cover handling the message from the HTTP POST operation, and also in putting the message on the JMS topic. When I’ve got the message handled, I forward the request onto a JSP for display. In this case, it’s the same JSP that we just covered. The real interesting piece of code here is in tying the servlet into JMS.

// Handles placing a message onto a JMS queue
public void doPush( String message ) {

  // Variables used by method are mostly JNDI and JMS related
  InitialContext context = null;
  Properties p = null;
  ObjectMessage objMessage = null;
  String ctxFactory = “jrun.naming.JRunContextFactory”;
  String url = “127.0.0.1:2907″;
  Topic topic = null;
  TopicSession pubSession = null;
  TopicPublisher publisher = null;
  TopicConnection connection = null;
  TopicConnectionFactory factory = null;

  try {

    // Get an initial context from the J2EE container
    p = new Properties();
    p.put( Context.PROVIDER_URL, url );
    p.put( Context.INITIAL_CONTEXT_FACTORY, ctxFactory );
    p.put( Context.SECURITY_PRINCIPAL, “admin” );
    p.put( Context.SECURITY_CREDENTIALS , “admin” );

    context = new InitialContext( p );

    // Get a reference to a specific JMS queue
    factory = ( TopicConnectionFactory )context.lookup( “jms/flex/TopicConnectionFactory” );
    connection = factory.createTopicConnection();
    pubSession = connection.createTopicSession( false, Session.AUTO_ACKNOWLEDGE );
    topic = ( Topic )context.lookup( “jms/topic/flex/simpletopic” );

    // Establish a means to send a message to the queue
    publisher = pubSession.createPublisher( topic );

    // Create an object message on which to place the request message
    // Place the request message on the JMS message
    objMessage = pubSession.createObjectMessage();
    objMessage.setStringProperty( “value”, message );

    // Put the JMS message on the queue
    publisher.publish( objMessage, Message.DEFAULT_DELIVERY_MODE, Message.DEFAULT_PRIORITY, 5 * 60 * 1000 );

  // Handle exceptions in as generic a form as possible (smile)
  } catch( NamingException ne ) {
    ne.printStackTrace();
  } catch( JMSException jmse ) {
    jmse.printStackTrace();
  }
}

Next I need a Flex application to listen for messages and to display those messages as they arrive. For the most part, I wanted to mirror my HTML presentation, but I got a little overzealous and leveraged the new states feature, and did a little styling. When first started, the Flex application displays a message the nothing has been received. Once a message arrives a new state is applied which reveals a label in which the messages are placed.

This use of states is pretty minimal, but it opens the door for me to apply transitions that increase the effectiveness of the UI – rather than just displaying the message, I could add fade, move or other effects as visual queues.

Listening for messages in Flex 2 is as easy as adding a Consumer object to your application and telling it where to listen for messages (specified by a destination). You also need to capture the message event and do something with it to make the application useful. In this case, I’m getting the message and simply placing it in a label for display. With the hooks establish however, it should be pretty clear as to how this might get applied in your next application.

<mx:Application pageTitle=”External Push (JSP)” layout=”absolute” creationComplete=”doCreationComplete( event )” xmlns:mx=”http://www.adobe.com/2006/mxml”>

  <!– Styles used on application to increase text readability –>
  <mx:Style>
    Application {
      color: #000000;
      background-color: #FFFFFF;
      font-size: 12;
    }
  </mx:Style>

  <mx:Script>
    <![CDATA[
      // Strongly type message event
      import mx.messaging.events.MessageEvent;

      // Subscribe to message queue on application start
      public function doCreationComplete( event:Event ):void {
        consumer.subscribe();
      }

      // Handle message event from consumer
      public function doMessage( event:MessageEvent ):void {

        // Check for current state to show message
        if( currentState != “message” ) {
          currentState = “message”;
        }

        // Assign message text
        txtMessage.text = event.message.headers.value;
      }
    ]]>
  </mx:Script>

  <!– Listens for simple text messages –>
  <mx:Consumer id=”consumer” destination=”contactsmess” message=”doMessage( event )” />

  <!– Let the user know what messages are available –>
  <mx:Label id=”lblMessage” left=”10″ top=”10″ right=”10″ text=”No message sent yet.” />

  <mx:states>

    <!– Change state to show messages –>
    <!– Adjusts informational label positioning and sizing –>
    <!– Adds a new label to display the message value –>
    <mx:State name=”message”>
      <mx:SetProperty target=”{lblMessage}” name=”text” value=”Last message:” />
      <mx:SetStyle target=”{lblMessage}” name=”right” />
      <mx:SetProperty target=”{lblMessage}” name=”width” value=”100″ />
      <mx:AddChild position=”lastChild”>
        <mx:Label id=”txtMessage” left=”110″ right=”10″ top=”10″ />
      </mx:AddChild>
    </mx:State>

  </mx:states>

</mx:Application>

mxml-message.gif

There’s one last step that needs to happen before this application will work, and that’s the configuration of the JMS topic itself. A JMS topic can be configured by modifying the appropriate configuration files within your J2EE server. In this case however, this is already done for us in the context of the samples that ship with the Flex Data Services. For the purposes of this example, I simply tell my Flex configuration that it needs to listen to that same topic.

<destination id=”contactsmess”>

  <properties>

    <server>
      <durable>false</durable>
      <durable-store-manager>flex.messaging.durability.FileStoreManager</durable-store-manager>
    </server>

    <jms>
      <destination-type>Topic</destination-type>
      <message-type>javax.jms.TextMessage</message-type>
      <connection-factory>jms/flex/TopicConnectionFactory</connection-factory>
      <destination-jndi-name>jms/topic/flex/simpletopic</destination-jndi-name>
      <destination-name>FlexTopic</destination-name>
      <durable-consumers>false</durable-consumers>
      <delivery-mode>NON_PERSISTENT</delivery-mode>
      <message-priority>DEFAULT_PRIORITY</message-priority>
      <acknowledge-mode>AUTO_ACKNOWLEDGE</acknowledge-mode>
      <transacted-sessions>false</transacted-sessions>
    </jms>

  </properties>

  <channels>
    <channel ref=”my-rtmp” />
    <channel ref=”my-polling-amf” />
  </channels>

  <adapter ref=”jms” />

</destination>

Note that since this example, as well as all the Flex 2 samples, point to the same JMS topic, I’m not sure I’d want to run them all at once. Realistically, you’d define a different topic per application, or even several different topics per single application. A Captivate recording of this example in action follows, and the source for this is also available. The configuration file is not included as you can cut/paste from this post, or cut/paste from the sample configuration file.

WordPress database error: [Can't open file: 'wp_comments.MYI' (errno: 145)]
SELECT * FROM wp_comments WHERE comment_post_ID = '35' AND comment_approved = '1' ORDER BY comment_date

Leave a Reply