1. Trang chủ >
  2. Công Nghệ Thông Tin >
  3. Hệ điều hành >

6  Use Publish/Subscribe Messaging for Chat Applications

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (8.09 MB, 764 trang )


The example that follows uses two different types of AMFChannel: StreamingAMFChan

nel and AMFChannel. The StreamingAMFChannel provides support for messaging and offers a different push model than the base AMFChannel. Instead of polling the server, the

streaming channel opens a HTTP connection to the server that is held open so that data

can be streamed down to the client.

The AMFChannel can be configured to poll a server at an interval. You can also use this

channel with polling disabled to send RPC messages to remote destinations to invoke

their methods. The AMFChannel relies on network services that are native to the Flash

Player and AIR and are exposed to ActionScript by the NetConnection class. The channel

creates a new NetConnection for each instance. Channels are created within the framework using the ServerConfig.getChannel() method and can be constructed directly and

assigned to a ChannelSet instance. Channels represent a physical connection to a remote

endpoint and are shared across destinations by default. This means that a client targeting different destinations may use the same channel to communicate with these

destinations.

In polling mode, AMFChannel polls the server for new messages at the pollingInterval

property, 3 seconds by default. To enable polling, the channel must be connected and

the polling-enabled property in the configuration file must be set to true, or the poll

ingEnabled property of the channel must be set to true.

The complete code listing is as follows:




xmlns:s="library://ns.adobe.com/flex/spark"

xmlns:mx="library://ns.adobe.com/flex/halo"

minWidth="1024" minHeight="768"

creationComplete=" initializeHandler()">










import spark.layouts.HorizontalLayout;

import spark.layouts.VerticalLayout;

]]>
















import

import

import

import



mx.messaging.channels.StreamingAMFChannel;

mx.messaging.ChannelSet;

mx.messaging.channels.AMFChannel;

mx.messaging.events.MessageEvent;



15.6 Use Publish/Subscribe Messaging for Chat Applications | 421



www.it-ebooks.info



import mx.messaging.messages.AsyncMessage;

import mx.messaging.messages.IMessage;



Here, you create the AMFChannel and StreamingAMFChannel instances that will poll the

service for new messages:

private function initializeHandler():void

{

var myStreamingAMF:AMFChannel = new

StreamingAMFChannel("my-streaming-amf",

"pathToService/streamingamf");

var myPollingAMF:AMFChannel = new

AMFChannel("my-polling-amf", "pathToService/amfpolling");

myPollingAMF.pollingEnabled = true;

myPollingAMF.pollingInterval = 1000;

var channelSet:ChannelSet = new ChannelSet();

channelSet.addChannel(myStreamingAMF);

channelSet.addChannel(myPollingAMF);



You then use the new ChannelSet instance to configure the Consumer and Producer

instances:

}



consumer.channelSet = channelSet;

producer.channelSet = channelSet;



public function set room(name:String):void

{

if (!name) return;



}



if (consumer && consumer.subscribed)

{

chatLogTextArea.text += "Leaving room " +

consumer.destination + "\n";

consumer.unsubscribe();

}

consumer.destination = name;

producer.destination = name;

consumer.subscribe();

chatLogTextArea.text += "Entering room " + name + "\n";



private function send():void

{

var message:IMessage = new AsyncMessage();

message.body = msgTextInput.text;

producer.send(message);

msgTextInput.text = "";

}

private function messageHandler(event:MessageEvent):void {

}



chatLogTextArea.text += event.message.body + "\n";



422 | Chapter 15: Working with Services and Server-Side Communication



www.it-ebooks.info



Here, the messages are sent via the Producer instance:

private function sendMsg():void {



}



var message:IMessage = new AsyncMessage();

message.body.chatMessage = msgTextInput.text;

producer.send(message);

msgTextInput.text = "";



]]>




layout="{new VerticalLayout()}">




width="100%" height="100%"/>

























In your service-config.xml file, you’ll need to define two channels for the service to use

(a StreamingAMFChannel and a PollingAMFChannel), like so:




class="mx.messaging.channels.StreamingAMFChannel">


class="flex.messaging.endpoints.StreamingAMFEndpoint"/>




class="mx.messaging.channels.AMFChannel">


class="flex.messaging.endpoints.AMFEndpoint"/>



true

4









15.6 Use Publish/Subscribe Messaging for Chat Applications | 423



www.it-ebooks.info



In the messaging-config.xml file, note that the default channels have been configured

and that the destination is not declared. This is because SimpleChat will dynamically

create destinations to which the messages will be sent:















SimpleChat defines a getRooms() method available over remoting that returns all the



rooms that have been created. In a more robust chat application, this method would

be implemented using messaging rather than a remoting call so that all clients would

be notified when a new room is created.

Here is the code of remoting-config.xml:





oreilly.cookbook.flex4.SimpleChat

application







The following is the code for a simple chat service (SimpleChat.java) for the BlazeDS

server. You might want to expand this service to allow users to dynamically add and

delete chat rooms or create private chat rooms, but for this recipe it suffices to show

how rooms can dynamically be created on the fly:

package oreilly.cookbook.flex4;

import

import

import

import

import

import



java.util.ArrayList;

java.util.Collections;

java.util.List;

flex.messaging.MessageBroker;

flex.messaging.MessageDestination;

flex.messaging.services.MessageService;



public class SimpleChat {

private List rooms;

private final String firstChatRoom = "firstChatRoom";

private final String secondChatRoom = "secondChatRoom";

private final String serviceName = "message-service";

private MessageDestination firstDestination;

private MessageDestination secondDestination;

public SimpleChat() {

rooms = Collections.synchronizedList(new ArrayList());



424 | Chapter 15: Working with Services and Server-Side Communication



www.it-ebooks.info



}

// note: not really the sleekest Java code, but has simplicity + readability

public List getRoomList() {

MessageBroker broker = MessageBroker.getMessageBroker(null);

MessageService service = (MessageService) broker.getService(serviceName);

if(firstDestination == null)

{

firstDestination = (MessageDestination)

service.getDestination(firstChatRoom);

if(service.getDestination(firstChatRoom) == null) {

firstDestination = (MessageDestination)

service.createDestination(firstChatRoom);

if (service.isStarted())

{

firstDestination.start();

}

}

rooms.add(firstChatRoom);

}

if(secondDestination == null)

{

secondDestination = (MessageDestination)

service.getDestination(secondChatRoom);

if(secondDestination == null) {

secondDestination = (MessageDestination)

service.createDestination(secondChatRoom);

if (service.isStarted())

{

secondDestination.start();

}

}

rooms.add(secondChatRoom);

}



}



}



return rooms;



You’ll also need to make sure that you set the following compiler arguments:

-locale en_US -services={$BLAZE_ROOT}/webapps/samples/WEB-INF/flex/services-config.xml



To see how to fully configure the services-config.xml file, refer back to the two previous

recipes.



See Also

Figures 15.4 and 15.5



15.6 Use Publish/Subscribe Messaging for Chat Applications | 425



www.it-ebooks.info



15.7 Use the IExternalizable Interface for Custom Serialization

Contributed by Peter Farland



Problem

You want to customize which properties are sent over the wire when sending strongly

typed data via a RemoteObject or DataService component.



Solution

Use the ActionScript 3 API flash.utils.IExternalizable, which is compatible with

Java’s java.io.IExternalizable API.



Discussion

A common scenario for using externalizable classes is to include read-only properties

in serialization. Although there are other approaches to achieve this for server code,

there aren’t many approaches available for client code. So, for an elegant solution that

works for both the client and the server, you can make your classes externalizable for

two-way custom serialization.

This approach is relatively straightforward. The client ActionScript class simply

implements flash.utils.IExternalizable. This API requires two methods,

readExternal() and writeExternal(), which take flash.utils.IDataInput and

flash.utils.IDataOutput streams, respectively. The implementations of these methods

mirror the server Java class, which implements java.io.Externalizable. java.io.Exter

nalizable also has readExternal() and writeExternal() methods that take

java.io.ObjectInput and java.io.ObjectOutput streams, respectively.

Although the IDataInput and IDataOutput classes let you design your own protocol and

write such fundamental data types as byte, int, and UTF-8-encoded Strings, most

implementations take advantage of the readObject() and writeObject() methods,

respectively, as these use AMF 3 to efficiently deserialize and serialize ActionScript

objects. (Remember that AMF 3 has three advantages. First, you can send objects by

reference to avoid redundant instances from being serialized, to retain object relationships, and to handle cyclical references. Second, you can send object traits so that the

description of a type is sent only once rather than repeated for each instance. Finally,

you can send reoccurring strings by reference to again avoid redundant information

being sent.) You may even decide to omit property names altogether in your externalizable classes’ custom serialization code and rely on a fixed order to send just the

property values.



426 | Chapter 15: Working with Services and Server-Side Communication



www.it-ebooks.info



This example focuses on serializing read-only properties, but there may

be many other usages for custom serialization, such as omitting properties, avoiding redundant serialization of information, or including

properties from custom namespaces.



Notice how the following Java writeExternal() method:

public void writeExternal(ObjectOutput out) throws IOException

{

out.writeObject(id);

out.writeObject(name);

out.writeObject(description);

out.writeInt(price);

}



mirrors the client readExternal() method in ActionScript:

public function readExternal(input:IDataInput):void

{

_id = input.readObject() as String;

name = input.readObject() as String;

description = input.readObject() as String;

price = input.readInt();

}



A similar relationship exists for the reverse situation, sending instances back from the

client to the server.



15.8 Track Results from Multiple Simultaneous Service Calls

Contributed by Andrew Alderson



Problem

You need to determine what returned data belongs to which of your multiple simultaneous service calls.



Solution

Use ASyncToken to add a variable to each call to identify it.



Discussion

Because mx.rpc.ASyncToken is a dynamic class, you can add properties and methods to

it at runtime. The Flex documentation states that it is “a place to set additional or tokenlevel data for asynchronous rpc operations.”



15.8 Track Results from Multiple Simultaneous Service Calls | 427



www.it-ebooks.info



Xem Thêm
Tải bản đầy đủ (.pdf) (764 trang)

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×