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.
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.
For more on downloading, installing, and configuring BlazeDS, see Chapter 11.
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.
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
).
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:
Right-click inside the Project Explorer view and then choose New
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.
Type jfib-ch14-p01 in the Project name text field and then click Next. The Java Settings screen opens.
Click the Libraries tab. The Library list appears.
Click the Add External JARs button. The JAR Selection dialog box, as shown in Figure 14.3, opens.
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.
Click Finish. The Create a Java Project wizard closes, and the newly created project appears in the Project Explorer view.
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.
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.
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:
Right-click the src
folder under the jfib-ch14-p01
project in the Project Explorer view and then choose New
Click the Browse button next to the Superclass text field. The Superclass Selection dialog box, as shown in Figure 14.5, opens.
Type ServiceAdapter in the Choose a type text field. The Matching items list box fills in with classes whose names match your entry.
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.
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.
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.
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.
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.
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.
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:
Right-click the jfib-ch14-p01
project in the Project Explorer view and then choose New
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.
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.
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.
Click the Browse button next to the From directory text field. The Import from directory dialog box, as shown in Figure 14.12, opens.
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.
Figure 14.11. The File System screen lets you select resources from your computer's file system to bring into your project.
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.
Right-click the web
folder and then choose New
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.
Right-click the web
folder and then choose New
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.
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>
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.
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.
For more on Java WAR files and Web application configuration, see Chapter 6.
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:
Right-click the webWEB-INF
folder below the jfib-ch14-p01
project in the Project Explorer view and then choose New
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.
For more on BlazeDS channels, see Chapter 11.
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:
Right-click the webWEB-INF
folder below the jfib-ch14-p01
project in the Project Explorer view and then choose New
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.
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.
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.
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:
Choose Window
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.
Click the Ant Home Entries item in the Classpath tab and then click Add External JARs. The Open JAR dialog box opens.
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.
Click OK. The Preferences dialog box closes.
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.
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:
Right-click the jfib-ch14-p01
project in the Project Explorer view and then choose New
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.
Right-click the jfib-ch14-p01
project in the Project Explorer view and then choose New
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
Make sure that you set the value of the FLEX_HOME
property to the location of the Flex SDK on your machine.
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>
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:
Choose Window
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.
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.
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.
Figure 14.21. The Buildfile Selection dialog box allows you to choose build files to add to the Ant view.
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.
Figure 14.23. When the Ant build has run successfully, you see a BUILD SUCCESSFUL
message in the Console view.
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.
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.
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:
Choose Window
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.
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:
Open your favorite browser. This example uses Internet Explorer.
Press Ctrl+N. A second Internet Explorer window opens.
Type http://localhost:8080/chat
in the address bar of the first window and then press Enter. The chat application opens.
Type http://localhost:8080/chat
in the address bar of the second window and then press Enter. The chat application opens.
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.
Switch to the second browser window. Notice that the same message about entering the chat is displayed here.
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.
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.
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.
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.
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.
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.
18.218.123.227