[JRuby][Warbler]Rubyで書いたソースからJARを作成する
はじめに
t.hondaです。Rubyでサクっと書いたスクリプトからJARを作成し、Javaが動く環境に配置して動かすことができたら便利だと思い、その方法を調べてみました。以下に、その実現方法とサンプルソースを書きたいと思います。
実行環境について
以下の実行環境にて開発、動作確認をしてみました。
- jruby 1.7.16.1
- java version "1.8.0_25"
またJARの作成には、WarblerというGemを使います。
以下、Gemのバージョンです。
- aws-sdk-core 2.0.11
- warbler 1.4.4
ソースと開発方法について
では、開発手順とソースについてです。先ほども書きましたが、流れとしては
- プロジェクトを作成する
- Warblerを使用し、JARを作成する
という感じとなります。
1.プロジェクトの構成について
プロジェクトの作成手順について書く前に、今回の構成について書いておきます。Warblerを使用してJARを作成するには、プロジェクトのフォルダを工夫する必要があるためです。
├── Gemfile ├── Gemfile.lock ├── WarblerSample.jar ・・・JAR作成時に出力される ├── app ・・・メインとなる処理を記述する │ ├── main.rb │ └── models │ └── sample.rb ├── bin │ └── init.rb ・・・起動時に実行する処理を記述する ├── config │ └── warble.rb └── vendor └── bundle └── jruby └── 1.9 ├── gems │ ├── aws-sdk-core-2.0.11 │ ├── builder-3.2.2 (・・・以下略・・・)
「bin」フォルダ内にアプリ起動時の処理を記述したinit.rbを作成しました。「bin」フォルダが存在しないと、WarblerにてJARを作成する際にwarble aborted! No executable script foundというエラーとなります。
「app」フォルダ内にアプリの主な処理を記述しました。上述したinit.rbから、このフォルダ内の処理を呼び出すようにしています。
「vendor/bundle」以下には、bundlerにてインストールしたgemが配置されています。
2.プロジェクト作成
以下の流れでプロジェクトを作成します。
以下のコマンドで、Gemfileの雛形を作成します。
$ bundle init
Gemfileが作成されるので、使用するgemを記述します。
# A sample Gemfile source "https://rubygems.org" gem 'warbler' gem 'aws-sdk-core' # gem "rails"
以下のコマンドでgemをインストールします。「--path〜」でプロジェクトのフォルダ内にgemをインストールしていることに注意してください。(このため後で工夫が必要になります。)
$ bundle install --path vendor/bundle
「config」フォルダをプロジェクトフォルダ内に作成します。
$ mkdir config
以下のコマンドでWarblerの定義ファイルの雛形を作成します。
$ bundle exec warble config
「warble.rb」というファイルがconfigフォルダ内に作成されるので、Warblerに読み込ませるフォルダを記述します。
Warbler::Config.new do |config| (中略) # Application directories to be included in the webapp. # config.dirs = %w(app config db lib log script vendor tmp) config.dirs = %w(bin config app) (中略) end
3.プログラム
今回書いたプログラムについてです。AWS SDK for Ruby を使い、S3にアクセスしてみました。先にも書きましたが、bin/init.rbにてアプリの起動処理を、appフォルダ内が主なロジックとなります。
bin/init.rb
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../")) Dir.glob(File.expand_path('vendor/bundle/jruby/*/gems/*/lib')).each{|path| $LOAD_PATH << path if !$LOAD_PATH.include?(path) } require 'app/main' main
1〜5行目で、JRuby、およびJARの作成に必要な実行パスを「$LOAD_PATH」に追加しています。1行目はアプリフォルダの絶対パスを、3〜5行目ではvendor/bundle以下のgemのパスを、それぞれ追加しています。gemのパスについては、これを追加しないとLoadエラーとなったのですが、Global領域にgemをインストールした場合は必要ないかもしれません。
7行目以降は、appフォルダ内のロジックを呼び出しています。
app/main.rb
require 'app/models/sample' def main Sample.new.start_method end
こちらは単純に、app/models/sample.rb内のメソッドを呼び出しています。
app/models/sample.rb
require 'aws-sdk-core' class Sample def start_method puts 'called Sample.start_method.' s3 = Aws::S3::Client.new(region: 'ap-northeast-1', profile: 'your-profile-name') resp = s3.list_objects(bucket: 'your-bucket-name') resp.contents.each do |object| puts object.key end end end
ここでaws-sdk-coreを使用し、S3にアクセスしています。今回はS3のバケットを指定し、中のオブジェクト名を出力してみました。
なお、AWSのアクセスキー、シークレットキーは~/.aws/credentialsに定義しておく必要があります。
JARの作成と実行
最後に、JARを作成して実行してみます。
以下のコマンドでJARを作成する。
$ bundle exec warble jar . #最後のピリオドを忘れずに!
作成したJARを実行する。
$ java -jar WarblerSample.jar
以下のように出力されました。
called Sample.start_method. lsyncd/ lsyncd/名称未設定.txt
AWS SDK for Rubyを使い、JVM上でS3にアクセスすることが出来ました!!
まとめ
別のRubyファイルをrequireした場合、JARだと読み込まれないのを解決するのに苦労しました。JRubyで開発する際に、何かの参考になれば幸いです。
参考サイト
Ahead-of-time compiling JRuby, packaging a Java Jar, creating a Gemspec, using Warbler
追記
もう少し細かいポイントについて続編を書きました。
[JRuby][Warbler]Rubyで書いたソースからJARを作成する - (2)定義ファイルの参照と、その他のポイント