This blog post makes an attempt to guide you through how to create a simple chat application using Flex3 and Red5. The application supports both public and private chat rooms. Red5 server will stream real-time message data to other clients connected based on scope. The application allows users to send messages to all users who have the application connected to the same scope. The public chat option connects users to web application scope and private chat connects them to a room scope.
For sending text formatted chat messages, see blog post here.
The private chat works in the same way as the public chat, except that all the participants in the same room share a dedicated shared object on the server to which messages are written, and to which only they listen to.
The application does not represent a real world situation and allows users to chat with each other without having to login or signup. But it demonstrates how the Red5 server can be connected in both application and room level scopes.
Creating Server Application in Red5
At first, we’ll write some code in the backend Red5 server to handle the sending and receiving of messages to all chat clients connected. We’ll create a new Dynamic Web Project Red5Chat in eclipse to do this. Create a new class file in the src directory of the project and name it Application.java. The file Application.java extends MultiThreadedApplicationAdapter and acts as base class for the server side application. Add the following code to Application.java.
package com.mycompany.ind.red5;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.red5.server.adapter.MultiThreadedApplicationAdapter;
import org.red5.server.api.IConnection;
import org.red5.server.api.IScope;
import org.red5.server.api.Red5;
import org.red5.server.api.so.ISharedObject;
public class Application extends MultiThreadedApplicationAdapter
{
@Override
public boolean appStart(IScope app)
{
this.createSharedObject(app, "ApplTSO", false);
return super.appStart(app);
}
@Override
public boolean appConnect(IConnection conn, Object[] params)
{
return super.appConnect(conn, params);
}
@Override
public boolean roomStart(IScope room)
{
this.createSharedObject(room, "RoomTSO", false);
return super.roomStart(room);
}
@Override
public boolean roomConnect(IConnection conn, Object[] roomUserInfo)
{
return super.roomConnect(conn, roomUserInfo);
}
@Override
public void appDisconnect(IConnection conn)
{
super.appDisconnect(conn);
}
public void sendMessage( Map chatMessageInfoMap)
{
int keyId=0;
ISharedObject chatMessageTSO = getSharedObject(Red5.getConnectionLocal().getScope(), "ApplTSO", false);
Map chatMessageInfoMapTemp = new ConcurrentHashMap();
if(chatMessageTSO.getAttribute("ChatMessageInfoMap") == null)
{
keyId=0;
}
else
{
chatMessageInfoMapTemp = (Map)chatMessageTSO.getAttribute("ChatMessageInfoMap");
keyId = chatMessageInfoMapTemp.size();
}
chatMessageInfoMapTemp.put(new Integer(keyId).toString(), chatMessageInfoMap);
chatMessageTSO.setAttribute("ChatMessageInfoMap", chatMessageInfoMapTemp);
}
public void sendMessageToRoom( Map chatMessageInfoMap)
{
int keyId=0;
ISharedObject chatMessageTSO = getSharedObject(Red5.getConnectionLocal().getScope(), "RoomTSO",
false);
Map chatMessageInfoMapTemp = new ConcurrentHashMap();
if(chatMessageTSO.getAttribute("ChatMessageInfoMap") == null)
{
keyId=0;
}
else
{
chatMessageInfoMapTemp = (Map)
chatMessageTSO.getAttribute("ChatMessageInfoMap");
keyId = chatMessageInfoMapTemp.size();
}
chatMessageInfoMapTemp.put(new Integer(keyId).toString(), chatMessageInfoMap);
chatMessageTSO.setAttribute("ChatMessageInfoMap", chatMessageInfoMapTemp);
}
}
The method appStart is called during Red5 start up and within this method we create a non persistent server side shared object named ApplTSO which serves the purpose of broadcasting chat messages to clients connected to application scope. The roomStart method is called when the first client connects to room scope or when a room is created and this method creates another non persistent server side shared object RoomTSO which propagates chat messages to clients connected to room scope. Both shared objects has an attribute named ChatMessageInfoMap which keeps all chat messages as well as the names of users who sent those messages.
To send chat messages in application (public) scope, the client side code will be calling the method sendMessage. The parameter chatMessageInfoMap of this method will represent both chat text and name of the user who sent the chat message. This map is put as a new entry to the existing ChatMessageInfoMap attribute of shared object. The statement
chatMessageTSO.setAttribute("ChatMessageInfoMap", chatMessageInfoMapTemp);
fires a sync event on all clients in application scope who are subscribed to this remote shared object. In a similar way, chat messages to a room (private) scope, will be accepted by a method sendMessageToRoom and the execution of setAttribute statement dispatches sync events to all subscribed clients and they will be notified about the changed attribute.
Creating Client Application in Flex3
Create a new flex project FlexRed5Chat in Flex Builder 3. Edit application main file FlexRed5Chat.mxml by adding the following:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" >
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.controls.Alert;
[Bindable] private var privateChatSelected:Boolean = false;
[Bindable] private var chatMessageInfoArrayCollection:ArrayCollection;
[Bindable] private var userRoomStatus:String;
[Bindable] private var sendButtonEnable:Boolean = false;
private var ncApplScope:NetConnection;
private var ncRoomScope:NetConnection;
private var chatMessageTSO:SharedObject;
private var chatMessageRoomTSO:SharedObject;
private var currentRoom:String = "";
private var currentRoomLabel:String = "";
private function handlePublicChat(event:Event):void
{
privateChatSelected = false;
userRoomStatus = "You are in public chat!"
if(chatMessageInfoArrayCollection != null)
{
chatMessageInfoArrayCollection.removeAll();
}
currentRoom = "";
currentRoomLabel == "";
if(ncRoomScope != null)
{
//ncRoomScope.close();
//ncRoomScope = null;
}
ncApplScope = new NetConnection();
ncApplScope.objectEncoding = ObjectEncoding.AMF0;
ncApplScope.addEventListener(NetStatusEvent.NET_STATUS, onNetApplStatus);
ncApplScope.connect("rtmp://localhost:1935/Red5Chat");
}
private function onNetApplStatus(event:NetStatusEvent):void
{
switch(event.info.code)
{
case "NetConnection.Connect.Success" :
sendButtonEnable = true;
ncApplScope.client = this;
chatMessageTSO = SharedObject.getRemote("ApplTSO", ncApplScope.uri, false);
chatMessageTSO.addEventListener(SyncEvent.SYNC, doOnApplTSOSync);
chatMessageTSO.connect(ncApplScope);
break;
case "NetConnection.Connect.Failed" :
ncApplScope = null;
Alert.show("Could not connect to server.");
break;
case "NetConnection.Connect.Closed" :
break;
case "NetConnection.Connect.InvalidApp" :
ncApplScope = null;
Alert.show("An error occured.");
break;
case "NetConnection.Connect.AppShutDown" :
break;
case "NetConnection.Connect.Rejected" :
break;
default:
break;
}
}
private function doOnApplTSOSync(event:SyncEvent):void
{
var data:Object;
var item:Object;
data = chatMessageTSO.data;
for(item in data)
{
if(item == "ChatMessageInfoMap")
{
var chatMessageInfoMapDataItem:Object = data[item];
var chatMessageInfoArrayTemp:Array = new Array();
for(var chatMessageInfoMapItem:String in chatMessageInfoMapDataItem)
{
chatMessageInfoArrayTemp.push({userMessage :
chatMessageInfoMapDataItem[chatMessageInfoMapItem]["userName"] + ": " +
chatMessageInfoMapDataItem[chatMessageInfoMapItem]["message"]});
}
chatMessageInfoArrayCollection = new ArrayCollection(chatMessageInfoArrayTemp.reverse());
}
}
}
private function handlePrivateChat(event:Event):void
{
if(currentRoom == "")
{
userRoomStatus = "You are in private chat. Double click on a room to enter!";
}
else
{
userRoomStatus = "You are in private chat room - " + currentRoom + "!";
}
privateChatSelected = true;
}
private function changeEvt(event:Event):void
{
if(chatMessageInfoArrayCollection != null)
{
chatMessageInfoArrayCollection.removeAll();
}
if(ncApplScope != null)
{
//ncApplScope.close();
//ncApplScope = null;
}
if(ncRoomScope != null)
{
if(currentRoom != event.currentTarget.selectedItem.label)
{
//ncRoomScope.close();
//ncRoomScope = null;
}
}
userRoomStatus = "You are in private chat room - " + event.currentTarget.selectedItem.label + "!";
currentRoomLabel = event.currentTarget.selectedItem.label;
ncRoomScope = new NetConnection();
ncRoomScope.objectEncoding = ObjectEncoding.AMF0;
ncRoomScope.addEventListener(NetStatusEvent.NET_STATUS, onNetRoomStatus);
var chatMessageInfo:Object = {userName:userNameTxt.text};
ncRoomScope.connect("rtmp://localhost:1935/Red5Chat" + "/" + event.currentTarget.selectedItem.label,
chatMessageInfo);
}
private function onNetRoomStatus(event:NetStatusEvent):void
{
switch(event.info.code)
{
case "NetConnection.Connect.Success" :
currentRoom = currentRoomLabel;
ncRoomScope.client = this;
chatMessageRoomTSO = SharedObject.getRemote("RoomTSO", ncRoomScope.uri, false);
chatMessageRoomTSO.addEventListener(SyncEvent.SYNC, doOnRoomTSOSync);
chatMessageRoomTSO.connect(ncRoomScope);
break;
case "NetConnection.Connect.Failed" :
ncRoomScope = null;
Alert.show("Could not connect to room.");
break;
case "NetConnection.Connect.Closed" :
break;
case "NetConnection.Connect.InvalidApp" :
ncRoomScope = null;
Alert.show("An error occured.");
break;
case "NetConnection.Connect.AppShutDown" :
break;
case "NetConnection.Connect.Rejected" :
break;
default:
break;
}
}
private function doOnRoomTSOSync(event:SyncEvent):void
{
var data:Object;
var item:Object;
data = chatMessageRoomTSO.data;
for(item in data)
{
if(item == "ChatMessageInfoMap")
{
var chatMessageInfoMapDataItem:Object = data[item];
var chatMessageInfoArrayTemp:Array = new Array();
for(var chatMessageInfoMapItem:String in chatMessageInfoMapDataItem)
{
chatMessageInfoArrayTemp.push({userMessage :
chatMessageInfoMapDataItem[chatMessageInfoMapItem]["userName"] + ": " +
chatMessageInfoMapDataItem[chatMessageInfoMapItem]["message"]});
}
chatMessageInfoArrayCollection = new ArrayCollection(chatMessageInfoArrayTemp.reverse());
}
}
}
private function sendMessage():void
{
if(userNameTxt.text == "")
{
Alert.show("Please Enter name of user!");
return;
}
if(chatTxt.text == "")
{
Alert.show("Please Enter a message to send!");
return;
}
var chatMessageInfo:Object = {userName:userNameTxt.text, message:chatTxt.text};
if(privateChatSelected == false)
{
if(ncApplScope == null)
{
Alert.show("Please select a chat mode!");
return;
}
else
{
chatTxt.text = "";
ncApplScope.call("sendMessage", new Responder(onResult, onStatus), chatMessageInfo);
}
}
if(privateChatSelected == true)
{
if(ncRoomScope == null)
{
Alert.show("Please enter a room!");
return;
}
else
{
chatTxt.text = "";
ncRoomScope.call("sendMessageToRoom", new Responder(onResult, onStatus), chatMessageInfo);
}
}
}
private function onStatus(event:NetStatusEvent):void
{ }
private function onResult(obj:Object):void
{ }
private function onCRPress(e:KeyboardEvent):void
{
if (e.keyCode != Keyboard.ENTER)
{
return;
}
if (e.type == KeyboardEvent.KEY_DOWN)
{
sendMessage();
}
}
]]>
</mx:Script>
<mx:HBox width="100%" height="100%" horizontalAlign="center" verticalAlign="middle" borderStyle="outset">
<mx:VBox width="50%" height="70%" >
<mx:HBox width="100%" height="5%" horizontalAlign="center" verticalAlign="middle" borderColor="#FFFFFF"
borderStyle="inset">
<mx:Label text="User Name" />
<mx:TextInput id="userNameTxt" />
</mx:HBox>
<mx:HBox width="100%" height="90%" horizontalAlign="center" verticalAlign="middle" borderStyle="none"
borderColor="#FFFFFF">
<mx:VBox width="5%" height="100%" borderStyle="outset" borderColor="#FFFFFF">
<mx:RadioButton groupName="chatType" id="publicChatType" label="Public Chat" width="150"
click="handlePublicChat(event);"/>
<mx:RadioButton groupName="chatType" id="privateChatType" label="Private Chat" width="150"
click="handlePrivateChat(event);"/>
<mx:List width="200" height="200" change="changeEvt(event)" enabled="{privateChatSelected}">
<mx:Object label="Room1" data="Room1"/>
<mx:Object label="Room2" data="Room2"/>
<mx:Object label="Room3" data="Room3"/>
<mx:Object label="Room4" data="Room4"/>
<mx:Object label="Room5" data="Room5"/>
<mx:Object label="Room6" data="Room6"/>
<mx:Object label="Room7" data="Room7"/>
<mx:Object label="Room8" data="Room8"/>
<mx:Object label="Room9" data="Room9"/>
</mx:List>
</mx:VBox>
<mx:VBox width="95%" height="100%" borderStyle="inset" borderColor="#FFFFFF">
<mx:HBox width="100%" height="5%" horizontalAlign="center">
<mx:Label text="{userRoomStatus}" color="#A22252" fontWeight="bold" />
</mx:HBox>
<mx:HBox width="100%" height="5%" >
<mx:TextInput id="chatTxt" width="100%" height="100%" keyDown="onCRPress(event)">
</mx:TextInput>
<mx:Button id="sendBtn" label="Send" click="sendMessage()" enabled="{sendButtonEnable}"/>
</mx:HBox>
<mx:HBox width="100%" height="90%" >
<mx:DataGrid id="chatTxtOutput" width="100%" height="100%" textAlign="center"
showHeaders="false" dataProvider="{chatMessageInfoArrayCollection}">
<mx:columns>
<mx:DataGridColumn textAlign="left" dataField="userMessage"/>
</mx:columns>
</mx:DataGrid>
</mx:HBox>
</mx:VBox>
</mx:HBox>
<mx:HBox width="100%" height="5%" horizontalAlign="center" verticalAlign="middle" borderStyle="inset"
borderColor="#FFFFFF">
<mx:Label text="Double click on a Room to enter the room" />
</mx:HBox>
</mx:VBox>
</mx:HBox>
</mx:Application>
A click on radio button labeled “Public Chat” connects to Red5 server side application Red5Chat in web application scope. After the connection is established, the client subscribes to server side shared object ApplTSO in application scope so that any changes made to the attributes of this shared object will be synched to all clients connected to the same scope. By this, whenever a change occurs to the application scope shared object ApplTSO, the method doOnApplTSOSync will be called and the data grid control will be updated with new messages. When a user sends a message, the client application forwards both message and user name to the server side application through method sendMessage. The sendMessage calls the server side sendMessage and server side method code writes them to the attribute ChatMessageInfoMap of remote shared object ApplTSO.
In the same way, after a successful connection to room, the client subscribes to the non persistent shared object RoomTSO in that room scope. The chat messages are sent by invoking a method sendMessageToRoom on the server side which updates the room scope shared object RoomTSO and notifies the change to all clients in that scope.

Resources
Download Red5 application source
Download Flex application source
Related Links
http://osflash.org/red5
http://www.adobe.com/products/flex/
http://trac.red5.org/wiki/Red5Plugin


Hey, this is really nice..
The code just run perfecly in my local machine..
Looking forward to see more challenging Red 5 Apps in your blog
Thanks a Lot
[...] myself « Chat Application with Red5 and Flex [...]
Hi,
I am new to RED5, and I would like to thank you for this great example. It’s exactly what I needed for my project.
Best regards,
Igor Skuhar
Hi i want to ask you, where do i place the Red5 Folder.
Second when i run code in flexbuilder and i insert my name it gives me cannot connect to server, sometimes it doesnt give me this error but when i press send no message appears
Can you help? thanks
@Red.
first) If you have eclipse IDE with Red5 plugin installed, you can import Red5 side project code and when you start the server, the project will be deployed under the webapps folder of Red5 server directory ({Red5 installation directory}/webapps/Red5Chat).
second) If the chat message is not appearing, it may be because application was not deployed correctly or Red5 server not started.
Thanks for your quick reply, but i have some more questions, this problem seems to happen with others
1- What version of eclipse do u have??
2-What version of eclipse red5 plugin u have?
3-What version of red5 standalone do u have 0.8 or 0.9
Finally i will tell u steps and what went wrong and maybe u can help me
In eclipse i installed red5plugin which is version 0.2 but import does not recognize red5 and i dont know why
Any ideas? and can u tell me how guide me on how to set it up correctly
Many thanks to u ^^
i fixed the my previous inquiry however i have 1 simple problem my Red5 server gives me a 1067 error which says cannot start server any ideas??
Thanks i bothered u alot :S
I figured most of it but, something weird happens i dont know if u face it or not, when i try to find RED5 runtime enviroment it doesnt exist?? only apache and ibm and websphere appear, how can i make red5 option appear, i have red5plugin installed and the jars and also i have server running plz help
If Red5 plugin is installed correctly, you could see Red5 Server Runtime under server type Infrared5.
Please see this link http://trac.red5.org/wiki/Red5Plugin/CreatingRed5Projects for a detailed description
Almost done
their is 1 small problem, i have imported the red5server from svn and executed the dist default thing, but their is this class that has error called
import ch.qos.logback.classic.selector.ContextSelector;
it does not recognize selector altho i have the red5 jar and some jar called logging added, did u face this problem?
Dont mind it, i really thank u for all ur efforts, seems RED5 is really a pain
, however thanks for ur amazing cooperation and ur amazing amazing blog!, Keep up the great work!!!
hi…im just following that u told.
i have my eclipse and flex builder and red5 server install.
all 3 software are individual. so when i run my flex builder and wana chat then some connection error will occer like:(” Could not connect to server.”)…so waht i will do to run the project .
plz solve my problem
thanks
its very good but i want to know how to deply the project i mean java and flex code and xml files at red5 server plz explain stem by step
thanks in advance
@Gourav Shivhare. Thanks. Please see http://www.tharas.in/2009/11/tracking-online-status-of-users-with-red5-and-flex-3/ for a step-by-step description of deploying and configuring Flex and Red5 projects.
I have read ur article “tracking online status of users with red5 and flex 3″.
In that project u use cairngorm to develop the flex project,
I want to know why u didn’t use it in this chat project?
In what case should we use the cairngorm architecture?
thanks.
hello!
I have a question!
U use SharedObject to implement the public chat.
But in the flex project, u also use the function “call”.
Why don’t u use the method “setProperty”?
Hi,I have finished studying ur code of this project!
I have a question!
U use “call” method in client side to pass the message content to the server side, then update the “sharedobject” in server side! The flex also has the “setProperty” method to update the sharedobject! So I want to update the sharedobject in client side!
When I tried it! I always got the error:”error 1009 cannot access a property or method of a null object reference”.
It seemed that the update in client side is not successful, So the sharedobject I got is null. I am troubled for almost a week!
Can u give me an example with sharedobject updated in client side. Thank u!
hello,
I have one problem.
As you mentioned I configure Flex,Eclipse and RED5.
After running Red5Chat from Eclipse ,my RED5 server is started.It’s work fine.
But when I run FlexRed5Chat from Flex builder
i got the status
NetConnection.Connect.Closed
NetConnection.Connect.Rejected
and also I got a warning in Eclipse console as follows
[WARN] [Red5_Scheduler_Worker-8] org.red5.server.net.rtmp.RTMPConnection – Closing RTMPMinaConnection from 127.0.0.1 : 1555 to localhost (in: 3334 out 3215 ), with id 24356426 due to long handshake
If anyone knows this please help me ASAP.
Thanks & Regards
Aneesh PS
[...] 2, 2010 by tharas This post is in continuation with the previous post Chat Application with Red5 and Flex which was about creating a simple chat application using Flex3 and Red5. Here the post goes a step [...]
Hi,
i am getting the exception ” Missing classpath entry \Applications\Red5\red5.jar” While set up the project in eclipse.
Thanks in advance
i have new to the Red5 with flexapplication implementation.i want to implement the public chat application with flex.So i have faced the issue while doing the setup for the environment.
i have installed the eclipse and then i tried to plug in the red5 into eclpse and i have used the below url for red5 plug in installtion,but i got the errors while doing the eclpse plug in.
eclise red 5 plug in URL:
——————————-
http://trac.red5.org/chrome/site/projects/red5plugin/update_0.2.x/
exception:
————-
An error occurred while collecting items to be installed
Error closing the output stream for org.red5.wizard/osgi.bundle/0.2.0 on repository file:/C:/manik/Softwares/eclipse-jee-ganymede-SR2-win32/eclipse/.
Error unzipping C:\Users\MANIKA~1\AppData\Local\Temp\org.red5.wizard_0.2.02489446225611667178.jar: Unexpected end of ZLIB input stream
can you please help me on this.
there isn’t other reason for me to say thanks. nice post bro!!
Hi, how about chat with audio, have you some sample or tutorial?
[...] A to Z of Computers also recommends the below two links for reading more about business chat software Link 1 & Link 2 [...]
[...] A to Z of Computers also recommends the below two links for reading more about mobile phone chat software Link 1 & Link 2 [...]
@Lynn Hogan if you want to update the sharedObject you may be update in flash or in the server…
What do you need?
@Lynn Hogan. The updation to sharedobject is done in server side and changes will be synched to flash.
When i am running that FlexRed5Chat.mxml in my internet explorer blank page is opening why this is happen? reply
Thanks for your insights. Would be great if you can advise on the below:
1. Can I have a portable Red5 server ?.. preferably for both Windows & Linux ?
2. Can you dynamically assign an IP address whenever one user connects to the chat application
Cheers.
how hard would it be to maintain a list of all the clients connected ?
Hi, Thanks for this great tutorial !
Is it a way to not store old messages in SO for users arriving later ?
What are the other options to create a chat application using flex and java? Is red5 a must?
Hi Thara,
I am facing some problem in order to use this application.
- I have flash builder 4.5 and Red5 server but I don’t have eclipse, is it necessary to have eclipse?
- And other this am confuse that where to put your server-side red5 code means that red5chat folder . I put it inside Red5 webapps folder and run the flexRed5Chat code from my flash builder then it shows connection rejected
and connection failed.
- another thing I want to know how to deploy a app inside Red5 server.
Please help me, I really need your help.
Thanks
Hi,
I try to get your code running on the latest Red5. The problem is that i get the SYNC event on the flex side only once, after connecting to a private room.
When the ‘setAttribute’ method is called on the server side, client code do not get SYNC event.
‘setAttribute’ change sharedObject attributes, because when new client connects it gets updated so (first sync event).
I need to know is there a bug in the latest Red5 version, because i have a deadline soon! Already i spend few days trying to get this work:/
Is there any chance for you to try to run your code on latest Red5 dist?
What version of Red5 do you use?
Thank share. But can used netbean edit code.
I m building Flex application it gives an error , Error: The style ‘borderColor’ is only supported by type ‘mx.containers.HBox’ with the theme(s) ‘halo, spark’. Don’t Know Where m i wrong