JRuby調査(続)

Javaクラスの読み込み方

まず require 'java'
次に、3つの方法がある。

  1. FQCNで直接指定
    • 1回しか出てこないとかのクラスに便利。
    • エイリアスしてもよい。
    • ってかこれできんのかよーw
  2. include_class('FQCN') {|pack,name| "J#{name}"}
    • よく出てくるクラスに便利。
    • エイリアスするのと同じ(?)
  3. include_package 'FQCN'
    • トップレベルでは使えない
    • パッケージ内のすべてのクラスを読み込むので、名前空間を汚染するかも

例外

Javaの例外は、NativeExceptionにラップされる。

Javaの例外クラスを指定してrescueすることもできちゃう。これもできんのかよーww

http://www.michaelstudman.com/fullfathomfive/articles/2006/09/26/handling-java-exceptions-in-jruby

begin
  f = java.io.FileReader.new 'hogehoge'
  ...
rescue java.io.FileNotFoundException
  puts 'file not found!'
end

Javaのクラス情報

JavaUtilities.print_class

irb(main):049:0> JavaUtilities.print_class java.util.ArrayList.java_class
Name:  java.util.ArrayList, access: public  Interfaces:
  Name:  java.util.List, access: public  Interfaces:
    Name:  java.util.Collection, access: public  Interfaces:
      Name:  java.lang.Iterable, access: public  Interfaces:
      SuperClass:
    SuperClass:
  SuperClass:
  Name:  java.util.RandomAccess, access: public  Interfaces:
  SuperClass:
  Name:  java.lang.Cloneable, access: public  Interfaces:
  SuperClass:
  Name:  java.io.Serializable, access: public  Interfaces:
  SuperClass:
SuperClass:
  Name:  java.util.AbstractList, access: public  Interfaces:
    Name:  java.util.List, access: public  Interfaces:
      Name:  java.util.Collection, access: public  Interfaces:
        Name:  java.lang.Iterable, access: public  Interfaces:
        SuperClass:
      SuperClass:
    SuperClass:
  SuperClass:
    Name:  java.util.AbstractCollection, access: public  Interfaces:
      Name:  java.util.Collection, access: public  Interfaces:
        Name:  java.lang.Iterable, access: public  Interfaces:
        SuperClass:
      SuperClass:
    SuperClass:
      Name:  java.lang.Object, access: public  Interfaces:
      SuperClass:
    Name:  java.lang.Object, access: public  Interfaces:
    SuperClass:
  Name:  java.util.AbstractCollection, access: public  Interfaces:
    Name:  java.util.Collection, access: public  Interfaces:
      Name:  java.lang.Iterable, access: public  Interfaces:
      SuperClass:
    SuperClass:
  SuperClass:
    Name:  java.lang.Object, access: public  Interfaces:
    SuperClass:
  Name:  java.lang.Object, access: public  Interfaces:
  SuperClass:
Name:  java.util.AbstractList, access: public  Interfaces:
  Name:  java.util.List, access: public  Interfaces:
    Name:  java.util.Collection, access: public  Interfaces:
      Name:  java.lang.Iterable, access: public  Interfaces:
      SuperClass:
    SuperClass:
  SuperClass:
SuperClass:
  Name:  java.util.AbstractCollection, access: public  Interfaces:
    Name:  java.util.Collection, access: public  Interfaces:
      Name:  java.lang.Iterable, access: public  Interfaces:
      SuperClass:
    SuperClass:
  SuperClass:
    Name:  java.lang.Object, access: public  Interfaces:
    SuperClass:
  Name:  java.lang.Object, access: public  Interfaces:
  SuperClass:
Name:  java.util.AbstractCollection, access: public  Interfaces:
  Name:  java.util.Collection, access: public  Interfaces:
    Name:  java.lang.Iterable, access: public  Interfaces:
    SuperClass:
  SuperClass:
SuperClass:
  Name:  java.lang.Object, access: public  Interfaces:
  SuperClass:
Name:  java.lang.Object, access: public  Interfaces:
SuperClass:
=> false

あんまり便利くない。オブジェクトが対象なら、

JavaUtilities.print_class obj.java_object.java_class

javasupport.rb

見てみたけど、内部的なサポート機能を持つものらしい。

  • JavaProxy
  • ArrayJavaProxyCreator
  • ArrayJavaProxy

Javaオブジェクトの配列

以下のようにして作る。

a = java.lang.String[3].new
a[0] = 'foo'
a[1] = 'bar'
a[2] = 'baz'

代入できない型を与えたときの挙動はちょっとよくわからない。

irb(main):031:0> ints = java.lang.Integer[3].new
=> #<#:0xe99ce5 @java_object=[Ljava.lang.Integer;@13b9fae>
irb(main):032:0> ints[0] = 100
=> 100
irb(main):033:0> ints[1] = 'abc'
=> "abc"
irb(main):034:0> ints[2] = Date.new
NativeException: java.lang.IllegalArgumentException: array element type mismatch
  (以下略)
irb(main):037:0* ints.each {|i| puts i}
100
0
nil
=> 0...3
irb(main):038:0>

JBoss-JMS

http://labs.jboss.org/wiki/Ja_Ejb3TbMessageDrivenBeans
http://docs.jboss.org/jbossas/jboss4guide/r5/html/ch6.chapt.html#d0e13187

キューを作るには、${JBOSS_HOME}/server/default/deploy/jms/*-service.xml を以下のような内容で作る。作ると、サーバーが自動的にロードしてくれる。


  
    jboss.mq:service=DestinationManager
  

元は、jboss-destinations-service.xmlから。設定項目の例として参照すること。

EJB3MDBは、

  • @javax.jms.MessageDrivenを付けて
  • javax.jms.MessageListenerをimplements
  • public void onMessage(Message message)を実装

して作る。

@MessageDrivenのパラメータで、使用するQueue/Topicを指定する。実はJBossは、ここに書いた内容でキューなどを自動生成してくれる(なので上記のXML設定は不要)とのこと。まあいいや。

で、JMSメッセージをJRubyから送るのは、ごくシンプル。いや、もともと手間がかかるっていうとこはそのままなんですが。

require 'java'

include_class 'javax.naming.InitialContext'
ctx = InitialContext.new

qcf = ctx.lookup('QueueConnectionFactory')
conn = qcf.createQueueConnection()
sess = conn.createQueueSession(false, 0)
msg = sess.createTextMessage()
msg.text = 'This is a message from JRuby'

q = ctx.lookup(JNDIキュー名)
sender = sess.createSender(q)
sender.send(msg)