BlazeDSで特定の相手とPush通信する

2011.09.06

今回はBlazeDSで特定の相手とPush通信する方法を調べました。
以下が手順になります。BlazeDSのバージョンは4.0を使ってます。

Push通信にはProducerクラスとConsumerクラスを使いますが、これらクラスのsubtopicというプロパティに共通の文字列を設定します。
サンプルでは[部の名前].[課の名前]のような形式の文字列を設定していて、同じ課の人にのみメッセージが送信されるようにしています。
[部の名前].* のようにワイルドカードを使うと、同じ部のすべてのメッセージを受信することができるようになります。
区切り文字はmessaging-config.xmlで設定できます。

■ MXMLのソース

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
		xmlns:s="library://ns.adobe.com/flex/spark" 
		xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
		creationComplete="creationCompleteHandler(event)">
	
	<fx:Declarations>
		<s:Producer id="producer" destination="st"/>
		<s:Consumer id="consumer" destination="st" message="messageHandler(event)"/>
		
		<s:ArrayCollection id="organization">
			<fx:Object label="開発部全体" name="develop.*"/>
			<fx:Object label="開発部1課" name="develop.develop1"/>
			<fx:Object label="開発部2課" name="develop.develop2"/>
			<fx:Object label="営業部全体" name="sales.*"/>
			<fx:Object label="営業部1課" name="sales.sales1"/>
			<fx:Object label="営業部2課" name="sales.sales2"/>
		</s:ArrayCollection>
	</fx:Declarations>
	
	<fx:Script>
		<![CDATA[
			import mx.events.FlexEvent;
			import mx.messaging.ChannelSet;
			import mx.messaging.channels.AMFChannel;
			import mx.messaging.events.MessageEvent;
			import mx.messaging.messages.AsyncMessage;
			import mx.messaging.messages.IMessage;
		
			private var channelSet:ChannelSet;
			private const URL:String = "http://localhost:8080/SampleBlazeDS/messagebroker/amfpolling";
			
			private function creationCompleteHandler(event:FlexEvent):void{
				
				var channel:AMFChannel = new AMFChannel(null, URL);
				channelSet = new ChannelSet();
				channelSet.addChannel(channel);
				
				consumer.channelSet = channelSet;
				producer.channelSet = channelSet;
				
				consumer.subscribe();
			}
		
			private function clickHandler(event:Event):void{
				
				if(groupCmb.selectedIndex != -1) {
					var subtopic:String = groupCmb.selectedItem.name;
					producer.subtopic = subtopic;
					consumer.subtopic = subtopic;
				}

				var message:IMessage = new AsyncMessage();
				message.body = "Hello World!";
				producer.send(message);
			}
			
			private function groupCmbChangeHandler(event:Event):void {
				var subtopic:String = groupCmb.selectedItem.name;
				producer.subtopic = subtopic;
				consumer.subtopic = subtopic;
				consumer.subscribe();
			}
			
			private function messageHandler(event:MessageEvent):void{
				textArea.text +=  String(event.message.body) + "\n";
			}
		]]>
	</fx:Script>
	
	<s:VGroup>
		<s:ComboBox id="groupCmb" width="100"
			change="groupCmbChangeHandler(event)"
			selectedIndex="-1" prompt=""
			dataProvider="{organization}"/>
		
		<s:Button click="clickHandler(event)" label="Click!"/>
		<s:TextArea id="textArea"/>
	</s:VGroup>
</s:Application>


■ messaging-config.xml
messaging-config.xmlでdestinationを設定します。
subtopicプロパティを使う場合、messaging-config.xml の allow-subtopics属性 を true にする必要があります。
subtopicを区切り文字で分けたい場合はsubtopic-separator属性を指定します。

<?xml version="1.0" encoding="UTF-8"?>
<service id="message-service" 
    class="flex.messaging.services.MessageService">

    <adapters>
        <adapter-definition id="actionscript" class="flex.messaging.services.messaging.adapters.ActionScriptAdapter" default="true" />
        <!-- <adapter-definition id="jms" class="flex.messaging.services.messaging.adapters.JMSAdapter"/> -->
    </adapters>

    <default-channels>
        <channel ref="my-polling-amf"/>
    </default-channels>

	<destination id="st">
		<properties>
			<server>
				<allow-subtopics>true</allow-subtopics>
				<subtopic-separator>.</subtopic-separator>
			</server>
		</properties>
	</destination>
</service>