JavaとFlexの連携その3(やっとつながる)
前回は前準備だけで終わってしまったので、今回ようやく繋げる。
まず前回のエントリーで、任意のサーブレットをJettyに組み込めたので、
これにBlazeDSを組み込んでみる。
BlazeDSはTomcatとセットで配布されているバージョンもあり、
Web上のサンプルはそれをとりあえず動かしてみる、みたいのが多かったが、
自分のWebアプリにBlazeDSでのメッセージング/リモーティング機能を組み込むサンプルをやっと見つけた。
必要なファイルにクラスパスを通し、前回のエントリーのコードを以下のように修正した
// サーブレットを作成 // 「MessageBrokerServlet」を使用 ServletHolder messageBrokerServletHolder = new ServletHolder(MessageBrokerServlet.class); // サーブレットに初期パラメータを渡す場合は、以下の処理でできる // まずはHashMapで初期パラメータを作成 HashMap<String, String> servletInitMap = new HashMap<String, String>(); servletInitMap.put( "services.configuration.file", "/WEB-INF/flex/services-config.xml" ); // サーブレットに初期パラメータ用HashMapで設定 messageBrokerServletHolder.setInitParameters(servletInitMap); Server server = new Server(); // Serverオブジェクトにコネクタを設定 server.addConnector(connector); Context hogeContext = new Context(server, "/", Context.SESSIONS); // サーブレットを追加 // "/messagebroker"というパスにmessageBrokerServletHolderを割り当てる hogeContext.addServlet(messageBrokerServletHolder, "/messagebroker/*");
通常ではweb.xmlで設定するBlazeDSの初期パラメータ("services.configuration.file")を、
あらかじめ作っておいたBlazeDS用の設定XMLファイル("/WEB-INF/flex/services-config.xml")を指定して、
HashMapに格納して設定してる。
で、実行してみると、怒られた。
上で設定したXMLファイルが見つからないらしい。
イロイロ設定を試したが、やっぱりファイルが見つからない。
# 実は、ここで一度BlazeDSの使用は見送り、
# JettyのContinuation機能を使って独自にCometを実装したが、
# あまりにショボイ実装のため不具合多発、結局再度BlazeDSに戻ってきた
さて設定ファイルをXMLファイルにして、それをうまく指定するには何かわからない設定があるらしい。
なので、BlazeDSがXMLファイルを読んだ後に、どういう処理をやっているのか、を調べるため
BlazeDSのソースを追っかけてみた。
すると、"services.configuration.manager"という初期パラメータが浮かび上がってきた。
Web上のサンプルではそれほどみないパラメータ。
これを指定しない(つまり一般的なサンプル)と、デフォルトでflex.messaging.config.FlexConfigurationManagerというクラスが使用され、
このflex.messaging.config.FlexConfigurationManagerクラスが
という流れらしい。
なるほど、じゃあ、FlexConfigurationManagerの代わりを作って、そいつを"services.configuration.manager"で指定するといいんじゃね?
と言うわけでやってみた。
まずHashMapに追加する値を書き換える。
HashMap<String, String> servletInitMap = new HashMap<String, String>(); servletInitMap.put( "services.configuration.manager", "CustomFlexConfigurationManager" );
次にCustomFlexConfigurationManagerを実装して、
XMLファイルで記述する内容をそのままJavaでハードコードする。
# 今回はハードコードで十分なのですm(__)m
package org.pollux.messaging.config; import javax.servlet.ServletConfig; import flex.messaging.config.AdapterSettings; import flex.messaging.config.ChannelSettings; import flex.messaging.config.ConfigMap; import flex.messaging.config.DestinationSettings; import flex.messaging.config.FlexConfigurationManager; import flex.messaging.config.LoggingSettings; import flex.messaging.config.LoginCommandSettings; import flex.messaging.config.MessagingConfiguration; import flex.messaging.config.ServiceSettings; import flex.messaging.config.SystemSettings; import flex.messaging.config.TargetSettings; public class CustomFlexConfigurationManager extends FlexConfigurationManager { @Override public MessagingConfiguration getMessagingConfiguration(ServletConfig servletConfig) { // TODO Auto-generated method stub MessagingConfiguration config = new MessagingConfiguration(); // ここで、BlazeDSの設定(services-config.xmlに書いてあるやつ)を作れば、 // XML設定ファイル群は不要になる ChannelSettings msgChannelSettings = new ChannelSettings("my-polling-amf"); msgChannelSettings.setClientType( "mx.messaging.channels.AMFChannel" ); msgChannelSettings.setEndpointType( "flex.messaging.endpoints.AMFEndpoint" ); msgChannelSettings.setUri( "http://{server.name}:{server.port}/messagebroker/pollingamf" ); ConfigMap propertyMap = new ConfigMap(); propertyMap.addProperty("polling-enabled", "true"); propertyMap.addProperty("polling-interval-millis", "0"); propertyMap.addProperty("wait-interval-millis", "-1"); propertyMap.addProperty("max-waiting-poll-requests", "300"); msgChannelSettings.addProperties(propertyMap); config.addChannelSettings("my-polling-amf", msgChannelSettings); SystemSettings ss = new SystemSettings(); ss.setRedeployEnabled("false"); config.setSystemSettings(ss); LoggingSettings loggingSettings = new LoggingSettings(); TargetSettings t = new TargetSettings("flex.messaging.log.ConsoleTarget"); t.setLevel("Error"); t.addProperty("prefix","[BlazeDS]"); t.addProperty("includeDate","false"); t.addProperty("includeTime","false"); t.addProperty("includeLevel","false"); t.addProperty("includeCategory","false"); t.addFilter("Endpoint.*"); t.addFilter("Service.*"); t.addFilter("Configuration"); loggingSettings.addTarget(t); config.setLoggingSettings(loggingSettings); ServiceSettings messageSettings = new ServiceSettings("message-service"); messageSettings.setClassName("flex.messaging.services.MessageService"); AdapterSettings adptSetting = new AdapterSettings("actionscript"); adptSetting.setClassName( "flex.messaging.services.messaging.adapters.ActionScriptAdapter" ); adptSetting.setDefault(true); messageSettings.addAdapterSettings(adptSetting); messageSettings.addDefaultChannel(msgChannelSettings); DestinationSettings dstSetting = new DestinationSettings("actionscript-message"); dstSetting.setAdapterSettings(adptSetting); messageSettings.addDestinationSettings(dstSetting); config.addServiceSettings(messageSettings); LoginCommandSettings lcs = new LoginCommandSettings(); lcs.setClassName("flex.messaging.security.TomcatLoginCommand"); lcs.setServer("Tomcat"); config.getSecuritySettings().addLoginCommandSettings(lcs); config.getSecuritySettings().setServerInfo( servletConfig.getServletContext().getServerInfo() ); return config; } @Override public void reportTokens() { // TODO Auto-generated method stub } }
ちなみに以下のXMLファイルと同じ設定になる
<?xml version="1.0" encoding="UTF-8"?> <services-config> <services> <service id="message-service" class="flex.messaging.services.MessageService"> <adapters> <adapter-definition id="actionscript" class="flex.messaging.services.messaging.adapters.ActionScriptAdapter" default="true" /> </adapters> <default-channels> <channel ref="my-polling-amf" /> </default-channels> <destination id="actionscript-message"> <adapter ref="actionscript"/> </destination> </service> </services> <security> <login-command class="flex.messaging.security.TomcatLoginCommand" server="Tomcat" /> </security> <channels> <channel-definition id="my-polling-amf" class="mx.messaging.channels.AMFChannel"> <endpoint url="http://{server.name}:{server.port}/messagebroker/amfpolling" class="flex.messaging.endpoints.AMFEndpoint" /> <properties> <polling-enabled>true</polling-enabled> <polling-interval-millis>0</polling-interval-millis> <wait-interval-millis>-1</wait-interval-millis> <max-waiting-poll-requests>300</max-waiting-poll-requests> </properties> </channel-definition> </channels> <logging> <target class="flex.messaging.log.ConsoleTarget" level="Error"> <properties> <prefix>[BlazeDS] </prefix> <includeDate>false</includeDate> <includeTime>false</includeTime> <includeLevel>false</includeLevel> <includeCategory>false</includeCategory> </properties> <filters> <pattern>Endpoint.*</pattern> <pattern>Service.*</pattern> <pattern>Configuration</pattern> </filters> </target> </logging> <system> <redeploy> <enabled>false</enabled> </redeploy> </system> </services-config>
これで組み込みJetty上でBlazeDSが動作する(はず)。
ここまでやったサンプルはあまりWebで見ないので(需要がない、と言うことか。。。)、
今回は頑張って調べました。
参考サイト