BLOGTIMES
2011/09/21

Java から MSMQ を使う

  java  mom  ruby 
このエントリーをはてなブックマークに追加

おそらくこういう事をやろうという人がいないのだろうと思いますが、ググっても情報が出てきません。やりたいのは以前に書いた「Ruby から MSMQ を使う」「JRuby と IronRuby と Ruby-mingw32 のスレッド実装の違い」のあわせ技のような感じなのですが、意外と時間がかかってしまいました。

大まかな話としては Java から COM を呼び出せれば目標達成なわけなので、JRubyも使っていると思っていたJACOBというライブラリを使ってみました。

JACOB - Java COM Bridge | Download JACOB - Java COM Bridge software for free at SourceForge.net

JACOB is a JAVA-COM Bridge that allows you to call COM Automation components from Java. It uses JNI to make native calls to the COM libraries. JACOB runs on x86 and x64 environments supporting 32 bit and 64 bit JVMs

これで最低限のことはできるのですが、どうしても既存のAPIだけでは定数が名前で呼び出せません。最初はちょっとダサいけど、ライブラリの制限なので仕方ないかなーと思いましたが、よくよく考えたら jruby-win32ole は WIN32OLE::const_load で定数取れてるじゃないかということに気づいたので、じゃあそのの実装はどうなってるんだろうと調べ始めてしまったのが、運の尽きでした。

JRuby に使われているのは racob

結論から述べると jruby-win32ole に使われているのは JACOB ではなくて、それをフォークしたと思われる racob というライブラリで、JACOBよりも格段に取れる情報が多くなっています。そもそもの追いかけ方が間違ってたんですね。

 ・enebo/jruby-win32ole - GitHub
 ・enebo/racob - GitHub

あとは jruby-win32ole の WIN32OLE::const_load を参考に実装しました。この racob は気合が入ったライブラリのようです。

サンプルコード

以前に書いたコードと同様のものが下記のコードになります。

MSMQPut.java

import org.racob.activeX.ActiveXComponent; import org.racob.com.Variant; public class MSMQPut { final static String QUEUE_NAME = ".\\private$\\test"; public static void main(String[] args){ System.out.println("QueueName: " + QUEUE_NAME); ActiveXComponent destination = new ActiveXComponent("MSMQ.MSMQDestination"); destination.setProperty("PathName", QUEUE_NAME); ActiveXComponent message = new ActiveXComponent("MSMQ.MSMQMessage"); message.setProperty("Label", "FooLabel"); message.setProperty("Body", "BarBody"); message.setProperty("Priority", 1); message.invoke("Send", new Variant[] { new Variant(destination) } ); System.out.println("Done !"); } }

MSMQGet.java

import java.util.HashMap; import java.util.Map; import org.racob.activeX.ActiveXComponent; import org.racob.com.TypeInfo; import org.racob.com.VarDesc; import org.racob.com.Variant; public class MSMQGet { final static String QUEUE_NAME = ".\\private$\\test"; public static void main(String[] args) { System.out.println("QueueName: " + QUEUE_NAME); ActiveXComponent queueInfo = new ActiveXComponent("MSMQ.MSMQQueueInfo"); queueInfo.setProperty("PathName", QUEUE_NAME); Map<String, Variant> constants = getConstantMap(queueInfo); ActiveXComponent queue = queueInfo.invokeGetComponent("Open", constants.get("MQ_RECEIVE_ACCESS"), constants.get("MQ_RECEIVE_ACCESS")); while (true) { ActiveXComponent message = queue.invokeGetComponent("Receive"); System.out.println("---"); System.out.println("Label:" + message.getProperty("Label")); System.out.println("Body:" + message.getProperty("Body")); System.out.println("Priority:" + message.getProperty("Priority")); } } public static Map<String, Variant> getConstantMap(ActiveXComponent component) { Map<String, Variant> constantMap = new HashMap<String, Variant>(); TypeInfo[] typeInfos = component.getTypeInfo().getContainingTypeLib().getTypeInfo(); for (TypeInfo typeInfo : typeInfos) { int varCount = typeInfo.getVarsCount(); for (int i = 0; i < varCount; i++) { VarDesc desc = typeInfo.getVarDesc(i); Variant constant = desc.getConstant(); if (constant != null) { String key = typeInfo.getNames(desc.getMemid())[0]; constantMap.put(key, constant); } } } return constantMap; } }

ただし、実行には jruby-win32ole に含まれる racob.jar, racob-x86.dll, racob-x64.dll が必要になります。さらに実行時にその配置の場所を java.library.path というパラメータで渡してやる必要があります。例えば libs というディレクトリにこれらのファイルをおいた場合には -Djava.library.path=./libs というパラメータを追加します。

Eclipseを使っている場合にはVM引数の欄に下記のような感じで書く必要があります。
MSMQ Put Run Configration - Java から MSMQ を使う

実行結果

MSMQPutの実行結果

QueueName: .\private$\testq Done !

MSMQGetの実行結果

QueueName: .\private$\testq --- Label:FooLabel Body:BarBody Priority:1 --- Label:FooLabel Body:BarBody Priority:1 --- Label:FooLabel Body:BarBody Priority:1 --- Label:FooLabel Body:BarBody Priority:1

    トラックバックについて
    Trackback URL:
    お気軽にどうぞ。トラックバック前にポリシーをお読みください。[policy]
    このエントリへのTrackbackにはこのURLが必要です→https://blog.cles.jp/item/4466
    Trackbacks
    このエントリにトラックバックはありません
    Comments
    愛のあるツッコミをお気軽にどうぞ。[policy]
    古いエントリについてはコメント制御しているため、即時に反映されないことがあります。
    コメントはありません
    Comments Form

    コメントは承認後の表示となります。
    OpenIDでログインすると、即時に公開されます。

    OpenID を使ってログインすることができます。

    Identity URL: Yahoo! JAPAN IDでログイン