tanamonの稀に良く書く日記

KEEP CALM AND DRINK BEER

はじめてのFlex その12

YUI FrameworkにはAMF3を使ったサーバ通信機能が(こっそりと)実装されているので、それを使ってサーバとデータ交換を行ってみます。

サーバ側の仕様を先に決めておきます。


このサーバ情報を元に各クラスを変更していきます。

src/dto/HelloDto.as

package dto {
	
	[RemoteClass(alias="examples.dto.HelloDto")]
	[Bindable]
	public class HelloDto {
		public var myName:String = "Hello World!";
		public var message:String;
	}
}

[RemotingClass()]のメタデータタグにデータクラス名を指定しています。
また、せっかくなのでmyNameを追加しました。

src/view/HelloView.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:yui="http://akabana.seasar.org/yui/mxml" xmlns:logic="logic.*" width="400" height="300">
	
	<yui:RemotingService id="amf" destination="helloService"/>
	
	<mx:VBox>
		<mx:FormItem label="お名前" required="true">
			<mx:TextInput id="myName"/>
		</mx:FormItem>
		<mx:Button label="click me!" id="clickMe"/>
	</mx:VBox>

	<mx:StringValidator id="messageValidator" required="true" source="{myName}" property="text" requiredFieldError="名前を入れてください。"/>

</mx:Canvas>

yui:RemotingServiceタグのdestinationにサービスクラス名を指定しています。

src/logic/HelloViewLogic.as

package logic {
	
	import dto.*;
	
	import flash.events.*;
	import flash.utils.*;
	
	import mx.controls.*;
	import mx.core.*;
	import mx.rpc.events.*;
	import mx.utils.*;
	
	import org.seasar.akabana.yui.service.rpc.event.*;
	import org.seasar.akabana.yui.service.rpc.remoting.*;
	
	import view.*;
	
	public class HelloViewLogic {
		
		[View]
		public var helloView:HelloView;
		
		[Model(bindView="helloView")]
		public var helloDto:HelloDto; 
		
		[Service]
		public var helloService:RemotingService;
		
		/**
		 * ボタン押下
		 */
		public function clickMeClickHandler(event:MouseEvent):void {
			if (helloDto.myName == "") {
				return;
			}
			helloService.remotingAction(helloDto);
		}
		
		/**
		 * 通信成功
		 */
		public function helloServiceRemotingActionResultHandler(event:RpcResultEvent):void {
			var result:HelloDto = event.result as HelloDto;
			if (result != null) {
				helloDto.message = result.message;
				Alert.show(helloDto.message);
			}
		}
		
		/**
		 * 通信失敗(RpcFaultEvent)
		 */
		public function helloServiceRemotingActionFaultHandler(event:RpcFaultEvent):void {
			trace(ObjectUtil.toString(event.faultStatus));
		}
		
		/**
		 * 通信失敗(SecurityErrorEvent)
		 */
		public function helloServiceNetStatusEventHandler(event:NetStatusEvent):void {
			trace(ObjectUtil.toString(event.info));
		}
		
		/**
		 * 通信失敗(NetStatusEvent)
		 */
		public function helloServiceSecurityErrorEventHandler(event:SecurityErrorEvent):void {
			trace(ObjectUtil.toString(event));
		}
		
		/**
		 * 通信失敗(IOErrorEvent)
		 */
		public function helloServiceioErrorEventHandler(event:SecurityErrorEvent):void {
			trace(ObjectUtil.toString(event));
		}

	}
}

ロジックはいろいろと追記しています。


まずRemotingServiceの定義に[Service]メタデータタグを付けます。
この時、インスタンス名はHelloView.mxmldestinationと一致している必要があります。
(つまり、サービスクラス名 == インスタンス名 == destination名、になります)


次に、通信はclickMeボタン押下時に行っています。
ここではサーバ側メソッド名のremotingActionと、引数のHelloDtoを合わせています。


最後に、ボタンハンドラ以降のメソッド名が長ったらしいですが、YUI命名規則に従っているためこれが仕様です。呼ばれるメソッド名は、サーバとの通信が行われた場合、サービスインスタンス名 + 実行メソッド名 + 結果イベント名 + Handlerとなります。

  • 成功時のメソッド名:"helloService" + "RemotingAction" + "Result" + "Handler"
  • 失敗時のメソッド名:"helloService" + "RemotingAction" + "Fault" + "Handler"


また、通信エラーなどでサーバとのやりとり自体が正しく行えなかった場合は、別のイベントが発生します。このメソッド名も長いですが、サービスインスタンス名 + エラーイベント名 + "Handler"となります。

  • NetStatusEventのメソッド名:"helloService" + "netStatusEvent" + "Handler"
  • SecurityErrorEventのメソッド名:"helloService" + "securityErrorEvent" + "Handler"
  • IOErrorEventのメソッド名:"helloService" + "ioErrorEvent" + "Handler"

YUI Frameworkの内部でdispatchEvent()しているのはこの3つなので、ハンドラははこの3つでOKだと思います。


今回は、この他にFlashプレイヤーの呼び出しHTMLにも追記します。

bin-debug/HelloYuiWorld.html

	AC_FL_RunContent(
			"src", "HelloYuiWorld",
			"width", "100%",
			"height", "100%",
			"align", "middle",
			"id", "HelloYuiWorld",
			"quality", "high",
			"bgcolor", "#869ca7",
			"name", "HelloYuiWorld",
			"flashvars",'remoting.defaultGateway=http://127.0.0.1:8080/HelloAmf3World/gateway',
			"allowScriptAccess","sameDomain",
			"type", "application/x-shockwave-flash",
			"pluginspage", "http://www.adobe.com/go/getflashplayer"
	);
  	<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
			id="HelloYuiWorld" width="100%" height="100%"
			codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">
			<param name="movie" value="HelloYuiWorld.swf" />
			<param name="quality" value="high" />
			<param name="bgcolor" value="#869ca7" />
			<param name="allowScriptAccess" value="sameDomain" />
			<param name="FlashVars" value="remoting.defaultGateway=http://127.0.0.1:8080/HelloAmf3World/gateway" />	
			<embed src="HelloYuiWorld.swf" quality="high" bgcolor="#869ca7"
				width="100%" height="100%" name="HelloYuiWorld" align="middle"
				play="true"
				loop="false"
				quality="high"
				allowScriptAccess="sameDomain"
				type="application/x-shockwave-flash"
				pluginspage="http://www.adobe.com/go/getflashplayer">
			</embed>
	</object>

長いので、必要な箇所だけにしていますが、
「"remoting.defaultGateway=http://127.0.0.1:8080/HelloAmf3World/gateway"」
が含まれる行をそれぞれ追記するだけです。


これでFlex側は完了です。


それにしてもYUI Frameworkはドキュメントが少なく、ほとんどがソースを追っかけていって調べています。
あまり使っている人がいないのだろうか。