この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
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)定義ファイルの参照と、その他のポイント