ActionScriptからJavaScriptを呼び出すにはExternalInterfaceを使う。
Rhinoを使うとJavaからJavaScriptを呼び出せるので、
クライアント側がFlex、サーバー側がJavaの構成のとき、
クライアント側とサーバー側とで同じJavaScriptを用いることが出来る。
前回のプログラムをFlexで書き換えてみた。
まずはいくつかハマった点、気になった点などを。
・ExternalInterface.callがIE8でnullを返してくる(Firefox、SafariではOK)
→2,3時間悩んだが、ググって解決。
swfを埋めこんでいるHTMLのobjectのidはexternalという文字を含んでいないとIEでは動かない
http://quality.ekndesign.com/archives/2006/07/externalinterfa.html
・AMF通信でServletContextが欲しい場合
→BlazeDSを使っている場合はflex.messaging.FlexContext.GetServletContext
→T2実装の場合はActionメソッドの本来の引数の後ろにServletContextを追加すると、
T2が呼び出し時に自動でセットしてくれた。Flex側では本来の引数だけ指定すればよい。
結果的にJava側とFlex側で引数の個数が異なっても動作する。
・T2の@FormのDTOとAMF通信のDTOは共用できる
→まあ当然といえば当然か。Fieldを持っているだけのクラスだから。
但しT2のFormがサポートする型、Flex→Javaの変換でサポートされる型の考慮は必要。
・一つのT2Pageクラス内にAMF通信のActionメソッドと通常のPostメソッドが混在していると、
AMFの方を呼んだつもりがPostの方が呼ばれてエラー???
→分けた方が無難っぽい
以下、サンプルのソース
Flex Main.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300">
<mx:RemoteObject id="remote" destination="/amf" endpoint="t2.amf" />
<mx:Script>
<![CDATA[
import flash.external.ExternalInterface;
import mx.controls.Alert;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.AsyncResponder;
import mx.rpc.AsyncToken;
import examples.dto.PostalCodeDTO;
public function onButtonClick(): void {
var arg: String = postalcodeEdit.text;
var result :Boolean = ExternalInterface.call("isValidPostalCode", arg);
if (!result) {
Alert.show("NG");
return;
}
var dto:PostalCodeDTO = new PostalCodeDTO();
dto.postalcode = postalcodeEdit.text;
dto.address = addressEdit.text;
var token:AsyncToken = remote.amf(dto);
token.addResponder(new AsyncResponder(onSuccess, onFault));
}
private function onSuccess(e:ResultEvent, object:Object = null):void {
Alert.show("OK");
}
private function onFault(e:FaultEvent, object:Object = null):void {
Alert.show(e.message.toString());
}
]]>
</mx:Script>
<mx:Canvas>
<mx:Label x="0" y="10" text="郵便番号:" textAlign="right" />
<mx:TextInput x="50" y="10" id="postalcodeEdit" width="80" maxChars="8" />
<mx:Label x="20" y="40" text="住所:" textAlign="right" />
<mx:TextInput x="50" y="40" id="addressEdit" width="300" maxChars="40" />
<mx:Button x="50" y="70" label="送信" click="onButtonClick()" />
</mx:Canvas>
</mx:Application>
Flexを埋め込んでいるJSP
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "">http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="Content-Script-Type" content="text/JavaScript" />
<script type="text/javascript" src="js/postalcodeutil.js"></script>
</head>
<body>
<object data="swf/main.swf" width="400" height="300"
type="application/x-shockwave-flash"
allowScriptAccess="always"
id="anexternal" >
<param name="movie" value="swf/main.swf" />
<param name="FlashVars" value="value" />
<param name="allowScriptAccess" value="always" />
<embed src="swf/main.swf" width="400" height="300"
allowScriptAccess="always"
type="application/x-shockwave-flash"
pluginspage="http://www.macromedia.com/go/getflashplayer" />
</object>
</body>
</html>
Flex側DTO(Java側のDTOは前回と同じ)
package examples.dto {
[RemoteClass(alias="examples.dto.PostalCodeDTO")]
public class PostalCodeDTO {
public var postalcode :String;
public var address: String;
public function PostalCodeDTO() {}
}
}
Java側Pageクラス
package examples.page;
import javax.servlet.ServletContext;
import org.t2framework.commons.util.Logger;
import org.t2framework.t2.annotation.core.Amf;
import org.t2framework.t2.annotation.core.Page;
import org.t2framework.t2.format.amf.navigation.AmfResponse;
import org.t2framework.t2.spi.Navigation;
import examples.dto.PostalCodeDTO;
import examples.util.PostalCodeUtil;
@Page("/amf")
public class AmfPage {
@SuppressWarnings("unused")
private static Logger logger = Logger.getLogger(PostalCodePage.class);
@Amf
public Navigation amf(PostalCodeDTO dto, ServletContext context) throws Exception{
PostalCodeUtil util = PostalCodeUtil.getInstance();
util.setJSPath(context.getRealPath("js/postalcodeutil.js"));
Boolean result;
if (util.isValidPostalCode(dto.getPostalcode())){
result = true;
/*
* 正常時の処理をここに処理を書く
*/
} else {
result = false;
/*
* エラー時の処理をここに処理を書く
*/
}
return AmfResponse.to(result);
}
}