Chapter 14. Building a Real-Time Messaging System

IN THIS CHAPTER

  • Understanding the application process

  • Writing the Java code

  • Writing the Flex code

  • Connecting the Java and Flex pieces

A real-time messaging system allows users to talk with one another in real time as though they were in the same room. This functionality can be used in such diverse applications as chat or instant messaging programs, customer support systems, and multiplayer games.

Understanding the Application Process

This simple chat application allows users to type a username to use during the chat or generates a random username for the user. Once the username has been typed, a note is sent saying that the user has entered the chat. The user types messages in a text input field. When the user clicks the Send button or presses the Enter key while the text input field has focus, the message is sent to the chat server. When the chat server receives the message, it publishes the message to all clients connected to the chat server.

The Flex client for this application consists of text input fields to type a username and the messages to be sent during the chat, a list control to display all the messages in the chat room, and buttons for saving the username and sending the chat message.

On the Java side, a single Java class acts as a message receiver and sender. It takes any messages it receives from a single chat client and broadcasts them to every chat client connected to the server.

This application uses BlazeDS as its messaging system. On the Flex side, the MXML file includes a publisher and consumer to send and receive messages, respectively. On the Java side, a custom BlazeDS message adapter handles all the receipt and repackaging of the messages.

Note

For more on downloading, installing, and configuring BlazeDS, see Chapter 11.

Writing the Java Code

The Java portion of this application consists of a single Java file that acts as the chat server, the Web application configuration, and the BlazeDS configuration.

Setting up the Eclipse project

The first thing to do is to set up an Eclipse project for the chat application. The Eclipse project includes the Java class file, all the Web application and BlazeDS configuration files, and the MXML and HTML files for the Flex application itself. You can build the MXML file into an SWF file by using a combination of Ant and the Flex SDK.

Before creating the Eclipse project, you need to unzip the blazeds.war file found inside your BlazeDS distribution. You'll use a number of JAR files found inside this WAR file in the build path of your Eclipse project. Because WAR files are essentially just ZIP files containing a Web application structure, you can use any ZIP utility to unzip the blazeds.war file to a location of your choosing (for example, c:lazeds.war).

Note

For more on installing and configuring Ant, see Chapter 1. For more on creating an Ant build file, see Chapter 6. For more information on BlazeDS, see Chapter 11.

Open Eclipse by navigating to the Eclipse install directory in Windows Explorer and double-clicking eclipse.exe. To create and configure an Eclipse project, follow these steps:

  1. Right-click inside the Project Explorer view and then choose New

    Setting up the Eclipse project
    Project from the popup menu. The New Project dialog box, as shown in Figure 14.1, opens.

  2. Click the arrow next to Java to expand it, click the Java Project item below Java, and then click Next. The Create a Java Project wizard, as shown in Figure 14.2, opens.

  3. Type jfib-ch14-p01 in the Project name text field and then click Next. The Java Settings screen opens.

  4. Click the Libraries tab. The Library list appears.

  5. Click the Add External JARs button. The JAR Selection dialog box, as shown in Figure 14.3, opens.

    The New Project dialog box

    Figure 14.1. The New Project dialog box

    The Create a Java Project wizard contains options and settings for new Java projects.

    Figure 14.2. The Create a Java Project wizard contains options and settings for new Java projects.

  6. Navigate to the folder where you unzipped the blazeds.war file, double-click the WEB-INF folder, double-click the lib folder, select all the JAR files in that lib folder, and then click Open. The 12 JAR files are added to the Library list, as shown in Figure 14.4.

  7. Click Finish. The Create a Java Project wizard closes, and the newly created project appears in the Project Explorer view.

The JAR Selection dialog box

Figure 14.3. The JAR Selection dialog box

Only two of the BlazeDS JAR files that you added to the Library list — flex-messaging-core.jar and flex-messaging-common.jar — are needed to compile the project. Adding all of them now means that the others are immediately available should you need them in the future when expanding on the project.

The chat server

Now you can create the Java class that acts as the chat server for this application. The Java class extends BlazeDS's ServiceAdapter class. The ServiceAdapter class is an abstract class that requires you to implement a single method called invoke(). The invoke() method receives messages from publishers in the Flex application. For this application, you want the chat server to take the message it receives and republish it so that every chat client connected to the chat server can display the message.

The 12 JAR files are added to the Library list when you select them in the JAR Selection dialog box.

Figure 14.4. The 12 JAR files are added to the Library list when you select them in the JAR Selection dialog box.

To create the Java chat server class, follow these steps:

  1. Right-click the src folder under the jfib-ch14-p01 project in the Project Explorer view and then choose New

    The 12 JAR files are added to the Library list when you select them in the JAR Selection dialog box.
    Class from the popup menu. The New Java Class dialog box opens.

  2. Click the Browse button next to the Superclass text field. The Superclass Selection dialog box, as shown in Figure 14.5, opens.

    The Superclass Selection dialog box allows you to choose the class that you want your class to extend.

    Figure 14.5. The Superclass Selection dialog box allows you to choose the class that you want your class to extend.

  3. Type ServiceAdapter in the Choose a type text field. The Matching items list box fills in with classes whose names match your entry.

  4. Choose ServiceAdapter-flex.messaging.services from the list box and then click OK. The Superclass Selection dialog box closes, and the Superclass text field in the New Java Class dialog box is filled in with the ServiceAdapter class.

  5. Type com.wiley.jfib.ch14 in the Package text field, type ChatServer in the Name text field, and then click the check box next to Generate comments, as shown in Figure 14.6.

  6. Click Finish. The New Java Class dialog box closes, and the newly created com.wiley.jfib.ch14 package and ChatServer class appear in the src folder under the jfib-ch14-p01 project. The ChatServer class opens in the editor, as shown in Figure 14.7.

The New Java Class dialog box as it appears once all the appropriate values have been filled in for the Package and Name text fields and the Generate comments check box has been selected.

Figure 14.6. The New Java Class dialog box as it appears once all the appropriate values have been filled in for the Package and Name text fields and the Generate comments check box has been selected.

The ChatServer class opens in the editor once the New Java Class dialog box closes. The inherited invoke() method has been created for you.

Figure 14.7. The ChatServer class opens in the editor once the New Java Class dialog box closes. The inherited invoke() method has been created for you.

Now edit the ChatServer class so that it matches this code listing:

/**
 *
 */
package com.wiley.jfib.ch14;

import flex.messaging.messages.AsyncMessage;
import flex.messaging.messages.Message;
import flex.messaging.services.MessageService;
import flex.messaging.services.ServiceAdapter;

/**
 * @author Chuck
* The ChatServer class implements a very basic chat
 * server using a custom BlazeDS* service adapter. The ChatServer class receives
 * a message from a Flex publisher
 * and republishes that message to any Flex consumer
 * that subscribes to this service.
 */
public class ChatServer extends ServiceAdapter {

  /* (non-Javadoc)
   * @see flex.messaging.services.ServiceAdapter#invoke(flex.messaging.
  messages.Message)
   */
  @Override
  public Object invoke(Message arg0) {
          AsyncMessage chatMessage = (AsyncMessage)arg0;
          chatMessage.setBody(arg0.getBody());
          MessageService messageService =
                  (MessageService)getDestination().getService();
          messageService.pushMessageToClients(chatMessage, false);
          return null;
  }

}

The import statements import some BlazeDS messaging classes necessary for the ChatServer class to receive and republish messages. The invoke() method is where the entirety of the chat server functionality is found. Take a look at each line of the invoke() method. The first line casts the incoming message to a variable of type AsyncMessage. The AsyncMessage class is the Flex asynchronous message used for publish-and-subscribe messaging. In asynchronous messaging, publishers of messages don't wait for responses to each message before continuing with other tasks. This is the opposite of synchronous messaging, in which publishers take no further action after sending a message until a response is received. In the case of a chat client and server, it's necessary for the server to be able to process messages from many clients without waiting for each one.

Similarly, the chat client should be able to receive many messages from the chat server without waiting for a response to a specific message it sends. In the Flex code for this application, there's an equivalent type in the MXML code that's sent to this Java class.

The second line sets the message body of this AsyncMessage to the value of the body of the incoming message. Remember, the chat server is simply taking the incoming message and republishing it to all chat clients.

The next line of the invoke() method establishes the MessageService class that's used to republish the message. The MessageService class is retrieved from the BlazeDS configuration file you create later. This code doesn't know anything about the specifics of the configuration being used. If the BlazeDS destination that this class publishes to needs to change, only the configuration file needs to change, not the chat server code itself.

The fourth line of the invoke() method publishes the message to all subscribing clients. The second parameter (false) is the evalSelector value. In addition to the message body text, a message can include one or more headers that subscribers can use to filter out messages they're not interested in. For example, if your chat application includes multiple chat rooms, clients currently logged into one chat room can use these message headers to publish messages to the correct room and to ignore messages from rooms they're not currently logged into. The server can check each client to see whether it needs to receive each message by setting this evalSelector value to true. In this case, your chat application includes only a single chat room; thus, the evalSelector value is set to false. Every client, therefore, receives every message from the chat server without checking.

Finally, the invoke() method returns null. Because the only actual data of value coming from this application is the messages being published, the return value of the method itself isn't used.

Writing the Flex Code

The client for this chat application is a single MXML application file that's compiled into an SWF file and an HTML file that embeds the SWF file. As discussed previously, the MXML file contains the following elements:

  • A TextInput control and a Button control for typing a username for the chat. These are hidden once the user has chosen a username.

  • A List control for displaying each chat message as it arrives from the server.

  • A TextInput control and a Button control for typing messages to send to the chat server.

Figure 14.8 shows what the user interface for the chat application looks like when run in a browser.

The user interface for the chat application. It consists of two Flex TextInput controls, two Flex Button controls, and a Flex List control.

Figure 14.8. The user interface for the chat application. It consists of two Flex TextInput controls, two Flex Button controls, and a Flex List control.

To add the MXML and HTML file for the chat application client to the Eclipse project, follow these steps:

  1. Right-click the jfib-ch14-p01 project in the Project Explorer view and then choose New

    The user interface for the chat application. It consists of two Flex TextInput controls, two Flex Button controls, and a Flex List control.
    Folder from the popup menu. The New Folder dialog box, as shown in Figure 14.9, opens.

  2. Type webWEB-INFlib in the Folder name text field and then click Finish. The New Folder dialog box closes, and the newly created folder structure appears expanded beneath the jfib-ch14-p01 project in the Project Explorer view.

  3. Right-click the lib folder you just created and then choose Import from the popup menu. The Import wizard, as shown in Figure 14.10, opens.

  4. Click the arrow next to General in the Select an import source list box to expand it, click the File System item below General, and then click Next. The Import from File system screen, as shown in Figure 14.11, opens.

  5. Click the Browse button next to the From directory text field. The Import from directory dialog box, as shown in Figure 14.12, opens.

    The New Folder dialog box allows you to create new folders to hold files for the Web application.

    Figure 14.9. The New Folder dialog box allows you to create new folders to hold files for the Web application.

  6. Navigate to the lib directory below your BlazeDS installation directory, click it to select it, and then click OK. The Import from directory dialog box closes. The lib directory appears in the left pane of the File System screen, and the JAR files within the lib directory appear in the right pane, as shown in Figure 14.13. Adding the BlazeDS JAR files to the Web application's WEB-INFlib directory makes them available to the Web application at runtime. The Flex chat client uses these BlazeDS JAR files to create and send messages to the Java chat server.

    The Import wizard allows you to bring external resources into your project.

    Figure 14.10. The Import wizard allows you to bring external resources into your project.

    The File System screen lets you select resources from your computer's file system to bring into your project.

    Figure 14.11. The File System screen lets you select resources from your computer's file system to bring into your project.

    The Import from directory dialog box lets you choose a directory on your file system from which to import resources.

    Figure 14.12. The Import from directory dialog box lets you choose a directory on your file system from which to import resources.

    After you select the BlazeDS distribution's lib folder in the Import from directory dialog box, it appears in the left pane of the File System screen, and its contents appear in the right pane.

    Figure 14.13. After you select the BlazeDS distribution's lib folder in the Import from directory dialog box, it appears in the left pane of the File System screen, and its contents appear in the right pane.

  7. Click the check box next to the lib folder in the left pane of the Import from Directory screen and then click Finish. The Import from File system screen closes, and the JAR files appear below the webWEB-INFlib directory in the Project Explorer view, as shown in Figure 14.14.

  8. Right-click the web folder and then choose New

    After you select the BlazeDS distribution's lib folder in the Import from directory dialog box, it appears in the left pane of the File System screen, and its contents appear in the right pane.
    File from the popup menu. The New File dialog box, as shown in Figure 14.15, opens.

  9. Type Chat.mxml in the File name text field and then click Finish. The New File dialog box closes, and the Chat.mxml file appears below the web folder in the Project Explorer view.

    After you select the BlazeDS JAR files in the File System screen, they are copied into the webWEB-INFlib folder of your project.

    Figure 14.14. After you select the BlazeDS JAR files in the File System screen, they are copied into the webWEB-INFlib folder of your project.

  10. Right-click the web folder and then choose New

    After you select the BlazeDS JAR files in the File System screen, they are copied into the webWEB-INFlib folder of your project.
    File from the popup menu. The New File dialog box opens.

  11. Type chat.html in the File name text field and then click Finish. The New File dialog box closes, and the chat.html file appears below the web folder in the Project Explorer view.

The New File dialog box lets you create a new empty file of any type.

Figure 14.15. The New File dialog box lets you create a new empty file of any type.

First, edit the Chat.mxml file to match this code listing:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
   creationComplete="subscribeToChat();">
<mx:Script>
        <![CDATA[
           import flash.events.MouseEvent;
           import mx.collections.ArrayCollection;
           import mx.events.FlexEvent;
           import mx.messaging.events.MessageAckEvent;
           import mx.messaging.messages.AsyncMessage;
           import mx.messaging.events.MessageEvent;
           import mx.messaging.events.MessageFaultEvent;
           import mx.controls.Alert;
           import mx.rpc.events.FaultEvent;

           [Bindable]
           private var dp:ArrayCollection = new ArrayCollection();
[Bindable]
           private var uname:String = "";

           private function setUserName():void
           {
                   if(username.text == "")
                   {
                          uname = randomName();
                   }
                   else
                   {
                          uname = username.text;
                   }
                   unhb.visible = false;
                   var msg:AsyncMessage = new AsyncMessage();
                   msg.body = uname + " has entered the chat!";
                   producer.send(msg);
                   chatEntry.enabled = true;
                   chatEntry.setFocus();
                   sendMessageButton.enabled = true;
           }

           private function randomName():String
           {
                   var letters:String =
   "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
                   var alphabetArray:Array = letters.split("");
                   var name:String = "";
                   for (var x:Number = 0; x < 8; x++)
                   {
                       name += alphabetArray[Math.floor(Math.random()
                           * alphabetArray.length)];
                   }
                   return name;
           }

           private function subscribeToChat():void
           {
                   consumer.subscribe();
           }

           private function receiveChatMessages(event:MessageEvent):void
           {
                   dp.addItem(event.message.body.toString());
                   statusLabel.text = "";
           }

           private function sendChatMessage():void
           {
var msg:AsyncMessage = new AsyncMessage();
                   msg.body = uname + ":  " + chatEntry.text;
                   producer.send(msg);
                   chatEntry.text = "";
           }

           private function handleFault(event:MessageFaultEvent):void
           {
                   Alert.show(event.faultString);
           }

           private function acknowledgeSend(event:MessageAckEvent):void
           {
                   statusLabel.text = "Sending . . .";
           }

           private function acknowledgeRec(event:MessageAckEvent):void
           {
                   statusLabel.text = "";
           }
         ]]>
</mx:Script>
<mx:Producer id="producer"
   destination="ChatAdapter"
   acknowledge="acknowledgeSend(event);"
   fault="handleFault(event);"
/>

<mx:Consumer id="consumer"
   destination="ChatAdapter"
   message="receiveChatMessages(event);"
   acknowledge="acknowledgeRec(event);"
   fault="handleFault(event);"
/>

<mx:Panel width="80%" height="80%" title="Chatroom"
   paddingTop="10"
   paddingBottom="10"
   paddingLeft="10"
   paddingRight="10">
   <mx:HBox id="unhb" width="100%">
          <mx:Label id="unl"
                   text="User Name (leave empty for a random name): "/>
          <mx:TextInput id="username" width="50%"/>
          <mx:Button label="Set Name" click="setUserName()"/>
   </mx:HBox>
   <mx:List dataProvider="{dp}" id="chattranscript"
           width="100%" height="80%"/>
   <mx:TextInput enabled="false" enter="sendChatMessage()"
id="chatEntry" width="100%"/>
<mx:Button id="sendmessagebutton" enabled="false"
           click="sendChatMessage()" label="Send"/>
<mx:Label id="statuslabel" text=""/>
</mx:Panel>
</mx:Application>

Note

For more on Flex syntax and programming constructs, see Chapter 4.

Much of this code listing consists of ActionScript functions contained inside <mx:Script> tags. Most of these ActionScript functions are handlers for various events fired by the user interface controls, such as button clicks. Take a look at these functions one by one:

  • The setUserName() function handles the event fired when the user either clicks the Set Name button or presses the Enter key within the username TextInput control. This function takes the current value of the username text field and stores it in a variable. If the username text field has no value, another function is called to generate a random name, and that value is stored in the variable instead. Once the username is stored, the TextInput and Button controls are hidden, and the chat entry TextInput and Button controls are enabled, allowing the user to start chatting. A message is sent to the server to let everyone know that the user has logged in to the chat room.

  • The randomName() function is used to generate a random username if the user doesn't type one.

  • The subscribeToChat() function is called once the application has finished loading. The value of the creationComplete attribute of the <mx:Application> tag is set to this function. This function is what actually subscribes this client to receive messages from the chat server. The consumer variable name refers to the id attribute of the <mx:Consumer> tag.

  • The receiveChatMessages() function receives messages from the server and then adds them to the dp ArrayCollection variable. This variable is set as the dataProvider of the List control defined by the <mx:List> tag. Each time an item is added to this ArrayCollection, the List control updates to display the new item along with the other items in the ArrayCollection.

  • The sendChatMessage() function sends the current value of the chatEntry TextInput control to the server. The type of the message that's created and sent to the server is AsyncMessage, just as it was on the Java side. The message is sent by using the producer variable, which refers to the id attribute of the <mx:Producer> tag. The Flex AsyncMessage and the Java AsyncMessage are structured similarly so that translation between the Java and Flex versions is seamless.

  • The handleFault() function is called if an error occurs when sending or receiving a message. This error might be displayed, for instance, if the connection to the chat server is lost.

  • The acknowledgeSend() function is called whenever a message is successfully sent to the chat server from the client. This function sets a status message to let the user know that the message has been sent successfully.

  • The acknowledgeRec() function is called whenever a message is received from the client. This function simply clears the status message. This function is called in addition to the receiveChatMessage() function. The acknowledgeRec() function simply indicates that something has been received from the client, whereas receiveChatMessage() processes what was received.

The publish and subscribe functionality of the chat client is set up by the <mx:Producer> and <mx:Consumer> tags, respectively. These two tags both contain a destination attribute with a value of ChatAdapter. This destination is part of the BlazeDS configuration. It provides a gateway between the Java code and the Flex code. The producer sends messages to the destination and defines which functions handle the success and failure of sending a message. The consumer defines which functions handle the success and failure of receiving a message as well as a function for processing any message received from the chat server.

Finally, edit the chat.html file to match this code listing:

<html>
<head>
<title>Flex/Java/BlazeDS Chat Room</title>
</head>
<body>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://
   download.macromedia.com/pub/shockwave/cabs/flash/swflash.
   cab#version=9,0,124,0" width="100%" height="100%"
id="Chat.swf">
  <param name="flashvars" value="versionChecked=true">
  <param name="src" value="Chat.swf">
  <embed pluginspage="http://www.macromedia.com/go/getflashplayer"
            width="100%" height="100%"
            flashvars="versionChecked=true"
            src="Chat.swf"
            name="Chat Room"
  />
</object>
</body>
</html>

The HTML file is a standard wrapper for an SWF file. It contains <object> and <embed> tags that define the source of the embedded SWF file as well as the URL for users to download the Flash Player browser plug-in if they don't already have it.

Connecting the Java and Flex Pieces

The Java chat server and Flex chat client are finished, but they still can't communicate with each other yet. First, you need to write Web application and BlazeDS configuration files to wire everything together. After the configuration files are written, you need an Ant build script to compile the Java source code into a class file and the Flex MXML file into an SWF file, and then package the compiled code and configuration together into a Web application archive (WAR) file.

Note

For more on Java WAR files and Web application configuration, see Chapter 6.

The Web application configuration

The configuration for the Web application lives in the web.xml file. This file sets up a servlet and some other code that BlazeDS uses to perform its messaging tasks. To create the web.xml configuration file, follow these steps:

  1. Right-click the webWEB-INF folder below the jfib-ch14-p01 project in the Project Explorer view and then choose New

    The Web application configuration
    File from the popup menu. The New File dialog box opens.

  2. Type web.xml in the File name text field and then click Finish. The New File dialog box closes, and the newly created web.xml file appears below the webWEB-INF folder in the Project Explorer view.

Edit the web.xml file to match this code listing:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//
   EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>

     <display-name>BlazeDS Chat</display-name>
     <description>BlazeDS chat application</description>

     <!-- Http Flex Session attribute and binding listener support -->
     <listener>
         <listener-class>flex.messaging.HttpFlexSession</listener-class>
     </listener>

     <!-- MessageBroker Servlet -->
     <servlet>
         <servlet-name>MessageBrokerServlet</servlet-name>
         <display-name>MessageBrokerServlet</display-name>
         <servlet-class>flex.messaging.MessageBrokerServlet</servlet-class>
         <init-param>
             <param-name>services.configuration.file</param-name>
<param-value>/WEB-INF/services-config.xml</param-value>
        </init-param>
         <load-on-startup>1</load-on-startup>
     </servlet>

     <servlet-mapping>
         <servlet-name>MessageBrokerServlet</servlet-name>
         <url-pattern>/messagebroker/*</url-pattern>
     </servlet-mapping>

     <welcome-file-list>
         <welcome-file>chat.html</welcome-file>
    </welcome-file-list>
</web-app>

This is a fairly standard web.xml file. The <listener> tag sets up a FlexHttpSession object that listens for messaging requests on BlazeDS HTTP channels and keeps track of sessions between the clients and server. The <servlet> tag registers the Flex MessageBrokerServlet. The MessageBrokerServlet provides message destination endpoints for the various BlazeDS channels in the BlazeDS configuration. The value of the services.configuration.file parameter points to the location of this BlazeDS configuration. The <load-on-startup> tag's value of 1 indicates that this servlet is loaded when JBoss starts. The <servlet-mapping> tag maps the MessageBrokerServlet class to the URL pattern /messagebroker/*, meaning that any URL that matches this pattern is handled by the MessageBrokerServlet. The endpoint URLs in the BlazeDS configuration file match this URL pattern. Finally, the <welcome-file-list> tag contains one entry that specifies the default file to load when accessing this application if no file is specified. This application has only one HTML file — chat.html — so it's the default welcome file.

Note

For more on BlazeDS channels, see Chapter 11.

The BlazeDS configuration

The web.xml file contains a reference to the BlazeDS configuration file services-config.xml. This configuration file defines the BlazeDS channels available for the chat application and the messaging service for the chat server.

To create the services-config.xml file, follow these steps:

  1. Right-click the webWEB-INF folder below the jfib-ch14-p01 project in the Project Explorer view and then choose New

    The BlazeDS configuration
    File from the popup menu. The New File dialog box opens.

  2. Type services-config.xml in the File name text field and then click Finish. The New File dialog box closes, and the newly created services-config.xml file appears below the webWEB-INF folder in the Project Explorer view.

Edit the services-config.xml file so that it matches this code listing:

<?xml version="1.0" encoding="UTF-8"?>
<services-config>
     <services>
         <default-channels>
             <channel ref="my-http"/>
         </default-channels>
            <service id="message_hyphen_service"
                     class="flex.messaging.services.MessageService">
                     <adapters>
                             <adapter-definition id="ch14chatadapter"
                                       class="com.wiley.jfib.ch14.ChatServer"/>
                     </adapters>
                     <destination id="chatadapter">
                             <adapter ref="Ch14ChatAdapter"/>
                     </destination>
            </service>
     </services>
     <channels>
               <!-- Simple HTTP -->
               <channel-definition id="my_hyphen_http"
                    class="mx.messaging.channels.HTTPChannel">
                    <endpoint uri="http://localhost:8080/chat/messagebroker/http"
                        class="flex.messaging.endpoints.HTTPEndpoint"/>
              </channel-definition>
     </channels>
</services-config>

This configuration file defines two things: services and channels. The <services> tag defines the message service that's used to send and receive messages as well as a set of default channels that those messages are sent and received on. For the chat application, there's only a single message service. It uses an adapter provided by the ChatServer class you wrote and makes that adapter available at the ChatAdapter destination. Remember that this is the same destination specified by the <mx:Producer> and <mx:Consumer> tags in the MXML file. The <channels> tag defines the set of channels that are available to all services in this application. This application has only one service and uses only one channel, which is a standard HTTP channel.

Configuring Ant and Eclipse to build the application

The final task in tying everything together is creating an Ant build script that can compile both the Java file and the MXML file, package the application up, and deploy it to the JBoss server. Before writing the build file, you need to provide Ant a JAR file, flexTasks.jar, from your Flex SDK. This JAR file defines Ant tasks for compiling Flex MXML files into SWF files.

The flexTasks.jar file can be found in the antlib subfolder of your Flex SDK installation. Copy the flexTasks.jar file from the antlib subfolder of your Flex SDK installation into the lib subfolder of your Ant installation directory.

Note

The Flex Ant Tasks are available only in Flex SDK version 3 and later. Older versions of the SDK don't include these Ant tasks.

Note

For more on installing the Flex SDK, see Appendix A.

To run the Ant build from within Eclipse, you also need to add the flexTasks.jar file to your Eclipse Ant configuration. To modify the Eclipse Ant configuration to include this file, follow these steps:

  1. Choose Window

    Configuring Ant and Eclipse to build the application
    Preferences in Eclipse. The Preferences dialog box, as shown in Figure 14.16, opens.

  2. Click the arrow next to Ant in the left pane to expand it and then click the Runtime item below Ant. The Runtime dialog box opens in the right pane with the Classpath tab selected, as shown in Figure 14.17.

    The Preferences dialog box allows you to configure a variety of preferences for Eclipse.

    Figure 14.16. The Preferences dialog box allows you to configure a variety of preferences for Eclipse.

  3. Click the Ant Home Entries item in the Classpath tab and then click Add External JARs. The Open JAR dialog box opens.

  4. Navigate to the lib folder in the antlib directory below your Flex SDK installation directory, click the flexTasks.jar file, and then click Open. The Open JAR dialog box closes, and the flexTasks.jar file appears with the rest of the Ant JARs in the Classpath tab, as shown in Figure 14.18.

  5. Click OK. The Preferences dialog box closes.

The Runtime dialog box lets you set runtime properties for Ant. On the Classpath tab, JAR files used by Ant can be added.

Figure 14.17. The Runtime dialog box lets you set runtime properties for Ant. On the Classpath tab, JAR files used by Ant can be added.

The flexTasks.jar file appears with the rest of the Ant JAR files once it has been selected in the Open JAR dialog box.

Figure 14.18. The flexTasks.jar file appears with the rest of the Ant JAR files once it has been selected in the Open JAR dialog box.

Now that the setup is finished, you can create the Ant build properties file and the build.xml file. To create these two files, follow these steps:

  1. Right-click the jfib-ch14-p01 project in the Project Explorer view and then choose New

    The flexTasks.jar file appears with the rest of the Ant JAR files once it has been selected in the Open JAR dialog box.
    File from the popup menu. The New File dialog box opens.

  2. Type chat-build.properties in the File name text field and then click Finish. The New File dialog box closes, and the newly created chat-build.properties file appears below the jfib-ch14-p01 project in the Project Explorer view.

  3. Right-click the jfib-ch14-p01 project in the Project Explorer view and then choose New

    The flexTasks.jar file appears with the rest of the Ant JAR files once it has been selected in the Open JAR dialog box.
    File. The New File dialog box opens.

  4. Type build.xml in the File name text field and then click Finish. The New File dialog box closes, and the newly created build.xml file appears below the jfib-ch14-p01 project in the Project Explorer view.

The properties contained in the chat-build.properties file are used by the build.xml build file, so first edit the chat-build.properties file to match this code listing:

# Ant build properties for chat
src.dir=src
web.dir=web
build.dir=${web.dir}/WEB-INF/classes

name=chat

appserver.home=${env.JBOSS_HOME}/server/default
deploy.path=${appserver.home}/deploy

APP_ROOT=web
FLEX_HOME=c:/flex/sdk

Note

Make sure that you set the value of the FLEX_HOME property to the location of the Flex SDK on your machine.

Note

For more on Ant build properties files, see Chapter 6.

This properties file contains properties for the Java source and Web file directories in the project, the build output directory, the application name, the JBoss home and application deployment path, and the Web application root and Flex SDK home for compiling the Flex MXML file.

Now edit the build.xml file to match this code listing:

<?xml version="1.0" encoding="UTF-8"?>
<project name="chat" basedir="." default="usage">
   <property environment="env"/>
    <property file="chat-build.properties"/>

    <path id="cp">
        <fileset dir="${web.dir}/WEB-INF/lib">
           <include name="*.jar"/>
        </fileset>
        <pathelement path="${build.dir}"/>
    </path>

    <taskdef resource="flexTasks.tasks"
        classpath="${FLEX_HOME}/ant/lib/flexTasks.jar"/>

     <target name="usage">
        <echo message=""/>
<echo message="${name} build file"/>
        <echo message="-----------------------------------"/>
        <echo message=""/>
        <echo message="Available targets are:"/>
        <echo message=""/>
        <echo message="build     --> Build the Java code and the Flex app"/>
        <echo message="deploy      --> Deploy application as a WAR file"/>
        <echo message=""/>
    </target>

    <target name="build" description="Compile main source tree java files">
        <mkdir dir="${build.dir}"/>
        <javac destdir="${build.dir}"
                   source="1.5"
                   target="1.5"
                   debug="true"
                   deprecation="false"
                   optimize="false"
                   failonerror="true">
            <src path="${src.dir}"/>
            <classpath refid="cp"/>
        </javac>
        <mxmlc file="${APP_ROOT}/Chat.mxml"
                   keep-generated-actionscript="false">
            <load-config filename="${FLEX_HOME}/frameworks/flex-config.xml"/>
            <source-path path-element="${FLEX_HOME}/frameworks"/>
              <services>web/WEB-INF/services-config.xml</services>
        </mxmlc>
    </target>
    <target name="build-and-deploy"
                    depends="build"
                    description="Deploy application as a WAR file">
        <war destfile="${name}.war"
                    webxml="${web.dir}/WEB-INF/web.xml">
            <fileset dir="${web.dir}">
                <include name="**/*.*"/>
            </fileset>
        </war>
        <copy todir="${deploy.path}" preservelastmodified="true">
            <fileset dir=".">
                <include name="*.war"/>
            </fileset>
        </copy>
    </target>
</project>

Note

For more on the structure of Ant build.xml files, see Chapter 6.

Much of this build.xml file is like others you've seen in previous chapters. There are two elements of this file that are new. First, the <taskdef> tag near the top of the file imports the Flex Ant tasks contained in the flexTasks.jar file for use in this build file. Second, the <mxmlc> tag makes use of that imported Flex Ant task to compile the MXML file into an SWF file. It uses the standard flex-config.xml file that's included with the Flex SDK and loads the Flex framework files to use during compilation. The <services> tag inside the <mxmlc> tag points the compiler to the BlazeDS configuration file. The compiler includes the information in the configuration file about messaging services and destinations in the compiled SWF file so that the SWF knows how to call into the messaging services on the server. Without this tag, the compiled SWF file wouldn't know how to communicate with the Java server.

The final piece of setup to perform is adding the Ant build.xml file to the Eclipse Ant view. To add the build.xml file to the Ant view, follow these steps:

  1. Choose Window

    The flexTasks.jar file appears with the rest of the Ant JAR files once it has been selected in the Open JAR dialog box.
    Show View
    The flexTasks.jar file appears with the rest of the Ant JAR files once it has been selected in the Open JAR dialog box.
    Other in Eclipse
    . The Show View dialog box, as shown in Figure 14.19, opens.

  2. Click the arrow next to Ant to expand it, click the Ant item below the expanded Ant item, and then click OK. The Ant view, as shown in Figure 14.20, opens.

  3. Click the Add Buildfiles button in the Ant view. The Add Buildfiles button is the leftmost button in the Ant view and has a + sign next to an ant. The Buildfile Selection dialog box, as shown in Figure 14.21, opens.

  4. Click the arrow next to the jfib-ch14-p01 project to expand it, click the build.xml file, and then click OK. The Buildfile Selection dialog box closes, and the build file appears in the Ant view, as shown in Figure 14.22.

The Show View dialog box lets you select an Eclipse view to open.

Figure 14.19. The Show View dialog box lets you select an Eclipse view to open.

The Ant view opens with no build files available until you add one.

Figure 14.20. The Ant view opens with no build files available until you add one.

The Buildfile Selection dialog box allows you to choose build files to add to the Ant view.

Figure 14.21. The Buildfile Selection dialog box allows you to choose build files to add to the Ant view.

The build file appears in the Ant view once it's selected in the Buildfile Selection dialog box. Each of the targets in the build file is displayed.

Figure 14.22. The build file appears in the Ant view once it's selected in the Buildfile Selection dialog box. Each of the targets in the build file is displayed.

To compile, package, and deploy the application, double-click the build-and-deploy target in the Ant view. Eclipse switches to the Console view, and you can see the output from the Ant tasks as they run. When the build-and-deploy process is complete, Ant displays the message BUILD SUCCESSFUL, as shown in Figure 14.23.

When the Ant build has run successfully, you see a BUILD SUCCESSFUL message in the Console view.

Figure 14.23. When the Ant build has run successfully, you see a BUILD SUCCESSFUL message in the Console view.

Note

As of this writing, an incompatibility between the Flex SDK 3.1 Ant tasks and Ant 1.7.1 may result in the build's failing. If Ant displays errors and finishes with BUILD FAILED, it may be due to this incompatibility. A workaround for this problem is to navigate to the lib folder below your Flex SDK installation and rename the file xercesPatch.jar to xercesPatch.backup. Once you rename this file, double-click the build-and-deploy target again. The build should run successfully.

Connecting to the chat server

The chat Web application is now deployed to the JBoss server as chat.war, which means that it's available on JBoss in the /chat Web application context. To test the chat application, first start up JBoss and then open the chat application in a browser to send and receive messages from the server.

Note

For more on installing JBoss and configuring it to run inside Eclipse, see Chapter 1. For more on Web application contexts, see Chapter 6.

To start JBoss inside Eclipse, follow these steps:

  1. Choose Window

    Connecting to the chat server
    Show View
    Connecting to the chat server
    Servers in Eclipse
    . The Servers view, as shown in Figure 14.24, opens.

  2. Click the Start the Server button. Eclipse switches to the Console view, and JBoss startup information appears there, as shown in Figure 14.25. Once JBoss has started up, Eclipse switches back to the Servers view.

The Servers view shows a list of the application servers that have been configured in Eclipse and their current state (Stopped or Started).

Figure 14.24. The Servers view shows a list of the application servers that have been configured in Eclipse and their current state (Stopped or Started).

When starting JBoss, Eclipse switches to the Console view so that you can see the JBoss startup information. Once JBoss has started up, Eclipse switches back to the Servers view.

Figure 14.25. When starting JBoss, Eclipse switches to the Console view so that you can see the JBoss startup information. Once JBoss has started up, Eclipse switches back to the Servers view.

Testing the chat application

A chat application is hard to test alone, but it can be done by opening two browser windows and switching between them to type messages. To test the chat application, follow these steps:

  1. Open your favorite browser. This example uses Internet Explorer.

  2. Press Ctrl+N. A second Internet Explorer window opens.

  3. Type http://localhost:8080/chat in the address bar of the first window and then press Enter. The chat application opens.

  4. Type http://localhost:8080/chat in the address bar of the second window and then press Enter. The chat application opens.

  5. Type a name in the username text field of the first chat window and then either press Enter or click the Set Name button. The username text field and Set Name button disappear, and the chat text field and Send button become available. A message appears in the list control stating that you've entered the chat.

  6. Switch to the second browser window. Notice that the same message about entering the chat is displayed here.

  7. Type a name in the username text field of the second chat window and then either press Enter or click the Set Name button. The username text field and Set Name button disappear, and the chat text field and Send button become available. A message appears in the list control stating that you've entered the chat.

  8. Type a message in the chat text field and then press Enter or click Send. The Sending message appears briefly in the status area and then the message appears in the list control, preceded by the username you typed in this window.

  9. Switch back to the first browser window. The message you sent in the second browser window has appeared in the list control in this window.

  10. Type a message in the chat text field and then press Enter or click Send. The Sending message appears briefly in the status area and then the message appears in the list control, preceded by the username you typed in this window.

  11. Switch back to the second browser window. The message from the user in the first browser window appears here.

Figure 14.26 shows what a chat session in two browsers might look like. If this application were deployed to a public JBoss server, people on different machines could open Web browsers and also chat across different machines.

This application is a great starting point for future expansion. For example, it could be expanded to use different chat rooms and filter messages based on header information. The back end could be enhanced to require the user to log in before chatting or to keep a friends list for each user so that only messages from friends are accepted. Use this application as a reference for building your own communications applications with Java and Flex.

A demonstration of two browser windows open to a chat application

Figure 14.26. A demonstration of two browser windows open to a chat application

Summary

In this chapter, you wrote a basic chat application to demonstrate the real-time messaging capabilities of Java and Flex connected by BlazeDS. First, you set up an Eclipse project for developing the application and then configured it to use the BlazeDS Java libraries. Next, you extended the BlazeDS ServiceAdapter Java class to create the simple ChatServer Java class. After that, you set up the structure of the Web application archive (WAR) file in Eclipse and then wrote the MXML chat client, which used the <mx:Producer> and <mx:Consumer> MXML tags to set up publish and subscribe relationships with the chat server code. Next, you wired together the communication lines between the Java code and the Flex code by creating some Web application and BlazeDS configuration files. To package up the application, you configured Ant in Eclipse to use the Flex Ant tasks included with the Flex SDK and then wrote an Ant build script to compile, package, and deploy the application to JBoss. Finally, you tested the application by running JBoss in Eclipse and then used two browser windows to simulate multiple users chatting.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.218.123.227