JavaとFlexの連携その3(やっとつながる)

前回は前準備だけで終わってしまったので、今回ようやく繋げる。


まず前回のエントリーで、任意のサーブレットをJettyに組み込めたので、
これにBlazeDSを組み込んでみる。
BlazeDSTomcatとセットで配布されているバージョンもあり、
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ファイルにして、それをうまく指定するには何かわからない設定があるらしい。
なので、BlazeDSXMLファイルを読んだ後に、どういう処理をやっているのか、を調べるため
BlazeDSのソースを追っかけてみた。
すると、"services.configuration.manager"という初期パラメータが浮かび上がってきた。


Web上のサンプルではそれほどみないパラメータ。
これを指定しない(つまり一般的なサンプル)と、デフォルトでflex.messaging.config.FlexConfigurationManagerというクラスが使用され、
このflex.messaging.config.FlexConfigurationManagerクラスが

  1. "services.configuration.file"で指定される設定用XMLファイルを読み込む
  2. XMLファイルに従ってメッセージング/リモーティングの設定を行う

という流れらしい。


なるほど、じゃあ、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で見ないので(需要がない、と言うことか。。。)、
今回は頑張って調べました。

参考サイト