カスタム検索

2009年4月7日火曜日

GrailsでblazeDSプッシュ配信!その1

blazeDSといえばプッシュ機能がついていますが、grailsのflex pluginでは定義されてないので使う事が出来ません。

せっかくあるんだし、サーバから一斉にメッセージ配信とかなんかカッコイイ(ここ重要)ので実装してみました。
まずは plugin を改良して streaming と polling の定義を追加します。

service-config.xml を編集します。

services の中に以下の定義を追加。
  1. <service id="message-service" class="flex.messaging.services.MessageService">  
  2.   <adapters>  
  3.     <adapter-definition id="actionscript" class="flex.messaging.services.messaging.adapters.ActionScriptAdapter" default="true" />  
  4.   </adapters>  
  5.   
  6.   <default-channels>  
  7.     <channel ref="grails-streaming-amf"/>  
  8.     <channel ref="grails-polling-amf"/>  
  9.   </default-channels>  
  10.   
  11.   <destination id="sb-1" />  
  12. </service>  


*デフォで入っている default-channels が services 全体になっているので、はじめから定義されている remoting-service の中に正しく入れてやる

desitination ってのが接続するキーになります、このタグの中にある security って項目を使うと別のユーザ管理と認証が出来ます。
(acegi と連動出来たら素敵ですが、とりあえず認証無しで)

channelsに以下を追加
  1. <channel-definition id="grails-streaming-amf" class="mx.messaging.channels.StreamingAMFChannel">  
  2.     <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/streamingamf" class="flex.messaging.endpoints.StreamingAMFEndpoint"/>  
  3.     <properties>  
  4.         <idle-timeout-minutes>0</idle-timeout-minutes>  
  5.         <max-streaming-clients>10</max-streaming-clients>  
  6.         <server-to-client-heartbeat-millis>5000</server-to-client-heartbeat-millis>  
  7.         <user-agent-settings>  
  8.             <user-agent match-on="MSIE" kickstart-bytes="2048" max-streaming-connections-per-session="1"/>  
  9.             <user-agent match-on="Firefox" kickstart-bytes="2048" max-streaming-connections-per-session="1"/>  
  10.         </user-agent-settings>  
  11.     </properties>  
  12. </channel-definition>  
  13.   
  14. <channel-definition id="grails-polling-amf" class="mx.messaging.channels.AMFChannel">  
  15.     <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amfpolling" class="flex.messaging.endpoints.AMFEndpoint"/>  
  16.     <properties>  
  17.         <polling-enabled>true</polling-enabled>  
  18.         <polling-interval-seconds>4</polling-interval-seconds>  
  19.     </properties>  
  20. </channel-definition>  


FlexPlugin では GrailsBootstrapService というクラスが BlazeDS の起動時に読み込まれるので、ここで MessageClientListener を登録してやります。

  1. MessageClient.addMessageClientCreatedListener(new ClientWatcher())  


ClientWatcher は MessageClientListener を implements したクラス、サンプルでこんなのを用意してみました。

  1. package org.codehaus.groovy.grails.plugins.flex;  
  2.   
  3. import flex.messaging.MessageClient;  
  4. import flex.messaging.MessageClientListener;  
  5.   
  6. public class ClientWatcher implements MessageClientListener {  
  7.  /** 
  8.   * クライアントが接続したときに呼ばれる。 
  9.   */  
  10.  public void messageClientCreated(MessageClient msgClient) {  
  11.    println "connect client"  
  12.     
  13.   // 自身をクライアントの切断を監視するリスナとしても登録する。  
  14.   msgClient.addMessageClientDestroyedListener(this);  
  15.  }  
  16.   
  17.  /** 
  18.   * クライアントが切断したときに呼ばれる。 
  19.   */  
  20.  public void messageClientDestroyed(MessageClient msgClient) {  
  21.   println "disconnect client"  
  22.   
  23.   // 明示的にセッションを破棄する。  
  24.   msgClient.getFlexSession().timeout();  
  25.  }  
  26. }  


でもクラスを直指定はいけてないので、Acegi風にDefaultConfigで対応するクラスを乗せ変えられるようにしてみました。

  1. // Configのロード  
  2. GroovyClassLoader classLoader = new GroovyClassLoader(getClass().getClassLoader())  
  3. ConfigObject config  
  4. ConfigObject flexConfig  
  5. try {  
  6.   flexConfig=new ConfigSlurper().parse(classLoader.loadClass('FlexConfig'))  
  7. catch(Exception e) {  
  8. }  
  9.   
  10. if(flexConfig) {  
  11.   config=flexConfig  
  12. else {  
  13.   config=new ConfigSlurper().parse(classLoader.loadClass('DefaultFlexConfig'))  
  14. }  
  15.   
  16. // クライアントの接続を監視する  
  17. def className="${config.flex.blazeDs.messageClientListener}"  
  18. def clientListener=classLoader.loadClass(className).newInstance()  
  19. MessageClient.addMessageClientCreatedListener(clientListener)  


ここをやっている時、Class.forName() でエラー出てハマっていたので Google先生に聞いてみたら自分が教えてくれた あるあるw
でも GroovyClassLoader を定義してるんでそっちを使ってみた

これで下準備は完了!
次回は接続&メッセージ送信編

この件の事もあるし、要望あれば plugin 公開してもいいかな・・・)

0 件のコメント: