TANGOSOL Coherence
仕事ネタも日記にしてしまいましょう.(^^;
Coherenceというのは,米TANGOSOL社の製品です.オープンソースではなく,いい値段のする商品(1995$/CPU〜)なのですが,評価版をダウンロードすることが出来ます.
このCoherenceを使うと何が出来るかというと,JVM間でメモリのレプリケーションを行ってくれるんですね.Coherenceというのは一貫性とかそういう意味を持つ単語です.この業界(どこ?)でよく耳にするところでは,SGIやIBMのサーバに使われているCC-NUMA(Chache Coherent-Non Uniform Memory Access)というのがありますね.これは,分割された(不均一な)メモリ間でキャッシュの一貫性を保つというアーキテクチャです.CoherenceはこれのJava版といった感じです.もっと身近なところだと,OracleのRACに使われているキャッシュ・フュージョンも似ているかな.
ということで,Coherenceもキャッシュの実装クラスを用意してくれています.このキャッシュは,他のJVMとネットワークを越えて内容の一貫性を維持してくれます.つまり,分散キャッシュなんですね.その実装方法(フルレプリケーションとかマスタースレーブとか)やポリシー(悲観的ロックとか楽観的ロックとか)は何種類か用意されていて,必要に応じて選択することが出来るようです.おもしろいことに,この分散キャッシュに対するJCAが提供されていて,分散トランザクションに参加することも出来るのだとか.分散システム全体でトランザクショナルに共有できるキャッシュなんてものが実現できる? 素晴らしいかも!
詳しく調べるのはこれからなのですが,Coherenceに単純なサンプルがついているので眺めてみました.このサンプルはコマンドライン・インタフェースを持っていて,分散キャッシュの内容を表示したり変更したりすることが出来ます.そのコードを見ると,使い方はとても簡単なんですね.
まずは初期化のところで分散キャッシュのインスタンスを取得します.
NamedCache cache = CacheFactory.getCache("VirtualCache");
NamedCache
クラスは,java.util.Map
をimplements
しています.ですから,後はget(Object)
やput(Object, Object)
なんかを使えばいいだけなんですね.超簡単!*1
このサンプル,後はコマンドラインから命令を読み込んでキャッシュ(Map
)を操作するだけです.ということで,動かしてしまいしょう.
サンプルを実行すると,コピーライトなどの表示の後に
Command:
と聞いてくるので,まずはコマンドの一覧を確認.
Command: help clear get <key> keys info put <key> <value> quit remove <key> Command:
楽勝っぽい.
では,キャッシュの内容が空なのを確認した上でエントリを追加してみましょう.
Command: keys Command: put name koichik >> Put Complete Command: keys >> name Command: get name >> Value is koichik Command:
キャッシュに値が入りました.
ここで,もう一つのプロセスを起動して,キャッシュの内容を確認します.
Command: keys >> name Command: get name >> Value is koichik Command:
おぉ,ちゃんと共有できていますね.こちらからもエントリを追加してみます.
Command: put birthday 08/18 >> Put Complete Command:
そして元のプロセスで確認.
Command: keys >> name >> birthday Command: get birthday >> Value is 08/18 Command:
いい感じ.
なお,この分散キャッシュはレプリケーションで共有されているので,サーバプロセスは不要です(サーバを使う構成も出来るようです).プロセスが一つでも生きていれば,内容は保持されます.ということで,最初のプロセスを終了してから2番目のプロセスでキャッシュを確認.
Command: keys >> name >> birthday Command: get name >> Value is koichik Command: get birthday >> Value is 08/18 Command:
アイディア次第でいろいろな使い方が出来そうです.幸か不幸か来期の予算に含められているらしいので,なんとか使いこなしたいと思います.
でも連載は無理です... たぶん.
Spring Framework 入門記 Contextその2 MessageSource
Contextパッケージの2回目です.前回はBeanFactory
の代わりにApplicationContext
を使いました.今回は,BeanFactory
にはない,ApplicationContext
特有の機能を使ってみます.
まずは「3.10.1. Using the MessageSource
」です.
ApplicationContext
は,MessageSource
インタフェースもextends
しています.MessageSource
は,国際化(i18n)対応のメッセージを提供するためのインタフェースらしいです.苦手なんですよね,国際化.いやその,日本語化も苦手なんですけどね...
それでその,MessageSource
には次の3つのメソッドがあります.
getMessage(String code, Object[] args, Locale loc)
getMessage(String code, Object[] args, String default, Locale loc)
getMessage(MessageSourceResolvable resolvable, Locale locale)
最初の2つのメソッドの第1引数code
はリソースバンドルで言うところのキーで,java.text.MessageFormat
で扱うパターン(フォーマット)文字列を得るために使われます.第2引数args
はそのMessageFormat
に渡される引数ですね.
3番目のメソッドのMessageSourceResolvable
は,2番目のメソッドの引数であるcode
,args
,default
を取得するgetterをメソッドして持つインタフェースです.つまり,このインタフェースをimplements
したクラスは,ごく普通のBeanとして扱えるようなクラスです.こちらを使うと,メッセージに含める引数などもBean定義XMLファイルで様々に定義できるため,より柔軟性を高めることが出来るということでしょう.
さて,ApplicationContext
はMessageSource
をimplements
しているわけですが,だからといってFileSystemXmlApplicationContext
*1は直接MessageSource
の機能を実装しているわけではないようです.本物のMessageSource
実装クラスに委譲するだけなんですね.ではその本物の実装は? というと,StaticMessageSource
とResourceBundleMessageSource
の2つが用意されています.このうち前者はプログラマティック*2にメッセージを設定するというもので,あまりうれしくない実装です.一方後者はおなじみのリソースバンドルを使うタイプです.うん,この方が素敵(キラッ).
ちょっと意外だったのが,ApplicationContext
がMessageSource
の実装を入手する手段です.どうやら,messageSource
という名前のBeanが定義されていれば,それを使ってくれるのだとか.ふーん,コンテナが予約しているも同然の名前があるってことですね.ちなみにmessageSource
という名前のBeanが見つからない場合はApplicationContext
が空のStaticMessageSource
を作成します.
国際化に対応したアプリケーションを作るなら,こういうものは必須なのでしょうね.国際化するわけではなくても,エラーメッセージやロギングのメッセージがそこら中のソースに散らばってしまうと大変です.でもこれ,ApplicationContext
の機能なんですよね.ということは,これを使うとそのクラスはApplicationContext
に依存してしまいます.うーん,あちら立てればこちらたたず.今回はあくまでもApplicationContext
の学習がメインなので,その問題には触れずにいくことにしましょう.えっ? 逃げてるわけじゃありませんよっ(ドキドキ).
とにもかくにもですね,この機能を使うにはApplicationContext
を入手しなければいけません.大体予想がつきますね.一貫性っていいなぁ.そうです,ApplicationContextAware
インタフェースをimplements
すればいいのです.BeanFactory
を入手するのにBeanFactoryAware
を使ったのと同じですね.
ということで,例によって実験コーナーの始まりです.
せっかくなので(何が?),MessageSource
第3のメソッドを使ってみることにします.
まずは,MessageSourceResolvable
をimplements
した単純なクラスを用意します.
package study; import org.springframework.context.MessageSourceResolvable; public class Headline implements MessageSourceResolvable { private Object arguments; private String codes; private String defaultMessage; public Object getArguments() { return arguments; } public void setArguments(Object objects) { arguments = objects; } public String getCodes() { return codes; } public void setCodes(String strings) { codes = strings; } public String getDefaultMessage() { return defaultMessage; } public void setDefaultMessage(String string) { defaultMessage = string; } }
これで,様々なメッセージフォーマットのキーとそのパラメータをBeanとして扱うことが出来ます.
次に,このHeadline
をプロパティとして持ち,ApplicationContext
にフォーマットしてもらって出力するdisplay()
メソッドを持つクラスを作ります.
package study; import java.util.Locale; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.MessageSourceResolvable; public class Billboard implements ApplicationContextAware { private ApplicationContext context; private MessageSourceResolvable headline; public void setApplicationContext(ApplicationContext context) throws BeansException { this.context = context; } public MessageSourceResolvable getHeadline() { return headline; } public void setHeadline(MessageSourceResolvable resolvable) { headline = resolvable; } public void display() { System.out.println(context.getMessage(headline, Locale.getDefault())); } }
次に,これらのクラスを定義したXMLファイルを作成します(<bean>
要素のみ抜粋).
<bean name="headline" class="study.Headline"> <property name="codes"><value>headline</value></property> <property name="defaultMessage"><value>Spring is commig.</value></property> </bean> <bean name="billboard" class="study.Billboard"> <property name="headline"><ref bean="headline"/></property> </bean>
次に実行用のクラス.いつものとあまり変わりません.
package study; import org.springframework.context.support.FileSystemXmlApplicationContext; public class Main { public static void main(String args) { try { FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext( new String { "factory.xml", "beans.xml" }); Billboard billboard = (Billboard) context.getBean("billboard"); billboard.display(); context.close(); } catch (Exception e) { e.printStackTrace(); } } }
これを実行すると,次のようになります.
Spring is commig.
おかしいですねぇ,もう春は来てるのに.
... すみません,わざとです.ごめんなさい.
これは,messageSource
というBeanを定義していないため,空のStaticMessageSource
が使われ,そこにはメッセージはまったく登録されていないのでデフォルトのメッセージが出力されたわけですね.
ということで,ResourceBundleMessageSource
をBean定義XMLに組み込みましょう(<bean>
要素のみ抜粋).
<bean name="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource" > <property name="basenames"> <list> <value>headline</value> </list> </property> </bean>
ResourceBundleMessageSource
は,リソースバンドルのベース名のリストを受け取るのですが,ここでは一つ(headline
)だけ指定しています.
そしてリソースバンドルを日本語用と英語用にそれぞれ作成します.
まず日本語用(headline_ja.properties
).native2ascii済みです.
headline=\u6625\u304c\u6765\u305f\uff0e
それから英語用(headline_en.properties
).
headline=Spring is here.
これを普通に(ロケールを指定しないで)実行すると,次のようになります(日本語環境だもん).
春が来た.
来てます!
次に,-Duser.language=en -Duser.country=US
を付けて実行すると,次のようになります.
Spring is here.
いいねぇ!
Lakers 115 - 91 Kings
\(^o^)/
すげー,キングスに圧勝だよ.