Groovy + Spring Boot + SWT でクライアントアプリケーションをつくる

G* Advent Calendar 2015 9日目です!

昨日は saba1024 さん「[Groovy] MongoDBを簡単に扱えるイケてる言語Groovy -Groovyの応用編-」でした!


 

職場などで業務改善的なツールをつくりたくなる場合がありますが、案外みんなの PC にスクリプト言語を動かす環境がなかったりします。そんな時は Groovy ! Java の現場であればそのままつくった jar を渡せますし、そうでなくても launch4j などで JRE ごと渡すことができます。

今回は「Groovy + Spring Boot + SWT」という組み合わせで、手軽に高速に GUI Groovy アプリケーションをつくる骨格を紹介してみたいと思います。

珍しい組み合わせかと思いますが、Spring Boot のオートコンフィグレーションと、後述する spring-loaded によるホットデプロイ(GUI 再起動無しで処理を変更できる)と Groovy によるプログラミングの組み合わせは、かなり高速に開発を進めることができると思います。

プロジェクトの構成は以下のような感じになります。

groovy-swt-02

まずは、build.gradle で Spring Boot と SWT を定義してあげます。

build.gradle

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.springframework.boot:spring-boot-gradle-plugin:1.3.0.RELEASE'
    }
}

apply plugin: 'groovy'
apply plugin: 'spring-boot'

repositories {
    mavenCentral()
    maven { url 'http://maven-eclipse.github.io/maven' }
}

dependencies {
    compile 'org.codehaus.groovy:groovy-all:2.4.5'
    compile 'org.springframework.boot:spring-boot-starter'
    compile "org.eclipse.swt:org.eclipse.swt.win32.win32.x86:4.5.1"
}

springBoot {
    mainClass = 'sample.Application'
}

SWT は Windows x86 のものを選択していますが、他の環境の定義は次の通りです。

    // The Standard Widget Toolkit(SWT)
    // System.getProperty('os.name').toLowerCase().split()[0]
    // System.getProperty("os.arch")
    // 
    // Windows x86
    // compile "org.eclipse.swt:org.eclipse.swt.win32.win32.x86:4.5.1"
    // Windows x64
    // compile 'org.eclipse.swt:org.eclipse.swt.win32.win32.x86_64:4.5.1'
    // Linux GTK+ x86
    // compile 'org.eclipse.swt:org.eclipse.swt.gtk.linux.x86:4.5.1'
    // Linux GTK+ x64
    // compile 'org.eclipse.swt:org.eclipse.swt.gtk.linux.x86_64:4.5.1'
    // OS X Cocoa x64
    // compile 'org.eclipse.swt:org.eclipse.swt.cocoa.macosx.x86_64:4.5.1'

次に Spring Boot の規約に従って(必要なら)ロガー(logback-spring.xml)と Application.yml を定義します。

src/main/resources/logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/base.xml"/>
    <logger name="sample" level="DEBUG"/>
</configuration>

src/main/resources/Application.yml

setting:
    defaultPath: C:\Users

Application.yml は Spring Boot の設定も記述できますが、作成するアプリケーションで外だししたい設定なども書けます。これを読むための、ApplicationSetting は次のようになります。

src/main/groovy/ApplicationSetting.groovy

package sample;

import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.stereotype.Component

@Component
@ConfigurationProperties(prefix = "setting")
public class ApplicationSetting {
    String defaultPath
}

Java でかくと Setter/Getter が必要ですが、Groovy ならこれだけです。.yml のキーと変数名を合わせれば勝手に Spring Boot がバインドしてくれます。

プログラムの起動点となる Application は次のようになります。

src/main/groovy/Application.groovy

package sample

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.SpringApplication
import sample.gui.Controller

@SpringBootApplication
class Application {

    @Autowired
    Controller controller

    static void main(args) {
        SpringApplication.run(Application.class, args).withCloseable {
            it.getBean(Application.class).controller.start()
        }
    }
}

通常の Java アプリケーションと同様に main を起動してあげると、Spring Boot が main があるパッケージ配下のコンポーネントを自動でスキャンしてクラスロードしてくれます。 @Autowired で GUI の Controller をインジェクションして main から呼び出しました。

呼び出される gui.Controller は次のようなものです。

src/main/groovy/gui/Controller.groovy

package sample.gui

import org.slf4j.*
import org.eclipse.swt.*
import org.eclipse.swt.events.SelectionListener
import org.eclipse.swt.graphics.*
import org.eclipse.swt.layout.*
import org.eclipse.swt.widgets.*
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
import sample.ApplicationSetting
import sample.service.Convert

@Component
class Controller {

    static final logger = LoggerFactory.getLogger(Controller.class);

    @Autowired
    Convert convert

    @Autowired
    ApplicationSetting setting

    Display display
    Shell shell
    ToolItem open
    Table list

    def private init() {
        // Window Setting
        display = new Display()
        shell = new Shell(
            display, SWT.TITLE | SWT.RESIZE | SWT.MIN | SWT.MAX | SWT.CLOSE)
        shell.setSize(640, 480)
        shell.setText("Sample Application")
        shell.setLayout(new GridLayout())
        // Application Icon
        shell.setImage(new Image(display, this.getClass().getResourceAsStream(
            "/images/icon/calculator.32x32.png")))

        // Toolbar
        def toolbar = new ToolBar(shell, SWT.FLAT | SWT.RIGHT)
        // Open
        open = new ToolItem(toolbar, SWT.PUSH)
        open.setText('Open')
        open.setImage(new Image(display, this.getClass().getResourceAsStream(
            "/images/icon/start.32x32.png")))
        // Toolbar Size
        toolbar.pack()

        // List Table
        list = new Table(shell, SWT.FULL_SELECTION | SWT.BORDER)
        list.setHeaderVisible(true)
        list.setLayoutData(new GridData(GridData.FILL_BOTH))
        list.setFocus()

        // Event Listener
        open.addSelectionListener([
            widgetSelected : {  e ->
                def f = new FileDialog(shell, SWT.OPEN)
                f.setFilterPath(setting.defaultPath);
                f.setFilterExtensions(["*.csv"] as String[])
                def login = f.open()
                def message = convert.input(login);
                def box = new MessageBox(shell, SWT.OK | SWT.OK)
                box.setMessage(message)
                box.open()
            }
        ] as SelectionListener)
 
        shell.open()
    }

    public void loop() {
        while(!shell.isDisposed()) {
            if(!display.readAndDispatch()) {
                display.sleep();
            }
        }
        display.dispose()
    }

    def start() {
        try {
            init()
            loop()
        } catch(Exception e) {
            e.printStackTrace()
            def box = new MessageBox(shell, SWT.OK | SWT.ABORT)
            box.setMessage("例外が発生しました。\n" + e.message)
            box.open()
        }
    }
}

SWT の GUI 作成とメインイベントループがあります。

ソース先頭で、サービスクラスにあたる service.Convert と先ほど Application.yml を読むためにつくった ApplicationSetting を DI しています。

    @Autowired
    Convert convert

    @Autowired
    ApplicationSetting setting

ボタンを押したときのイベントでこれらを利用しています。

        // Event Listener
        open.addSelectionListener([
            widgetSelected : {  e ->
                def f = new FileDialog(shell, SWT.OPEN)
                f.setFilterPath(setting.defaultPath);
                f.setFilterExtensions(["*.csv"] as String[])
                def login = f.open()
                def message = convert.input(login);
                def box = new MessageBox(shell, SWT.OK | SWT.OK)
                box.setMessage(message)
                box.open()
            }
        ] as SelectionListener)

サービスクラスはとりあえず。

src/main/groovy/service/Convert.groovy

package sample.service;

import java.io.File;

import org.springframework.stereotype.Component;

@Component
public class Convert {
    def input(file) {
        return "converted!" 
    }
}

というわけで、Application.groovy を IDE から実行するか、./gradlew bootRun するとアプリケーションが起動します。

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.3.0.RELEASE)

2015-12-09 00:25:31.353  INFO 6560 --- [           main] sample.Application 

groovy-swt-01

さて、ここで大技です。 spring-loaded を実行時に javaagent で読み込むことで、実行中に修正したクラスをリロードできるようになります。 プロジェクトサイトから jar をダウンロードし、アプリケーション実行時の JVM 引数に以下を加えます。

-javaagent:${project_loc:template-springboot-swt}/lib/springloaded-1.2.5.RELEASE.jar -noverify

“${project_loc:template-springboot-swt}” は Eclipse 的なプロジェクトホームの指定ですので、適宜変更してください。

groovy-swt-04

なお、Eclipse で実行する場合は Application.groovy から Run してください。./gradle bootRun だとリロードされません。これは、Eclipse の場合、自動コンパイルの .class ファイルを置く先が bin/ ディレクトリ配下となり、bootRun した場合は build/ 配下の class ファイルで実行され、ファイルの更新がされないためです。

というわけで、spring-loaded ですが、やってみると異常に快適です。 GUI をつくる場合、対象の処理にたどり着くまでの操作が長くかかることがありますが、spring-loaded を入れておくとリトライが簡単で、なんだか世界が変わります。 🙂

その他、Spring Boot 上であると、H2 の組み込み DB や、JPA や GORM などの O/R マッパーも、gradle の定義だけでオートコンフィグレーションされてすぐ使えるようになりますので、非常に便利です。

今回のサンプルでは、サービスクラスで CSV を H2 に読んで GORM で抽出をかけたかったのですが、出張先にて機材トラブルにより間に合いませんでした。ごめんなさい。。

以上、あまり手間をかけず、ゆるいフレームワーク規約で自由気ままにツールなどの GUI をつくりたいなんて時に、良ければお試しください。

最後に、Apache Groovy おめでとうございます! 今年も Groovy にずいぶん助けてもらいました。 🙂

Keep on Groovy-ing!

Gradle と Brakets でお手軽 Sass 開発

Sass をやってみたいだけなのに、OS に node.js 入れたり grunt 入れたり Ruby 入れたりなかなか大変な思いをしている方が結構いるようですので、「Gradle」を使ったお手軽な導入方法を紹介してみたいと思います!

Gradle は、JVM(Java) の世界で広く用いられているビルド・タスクランナーツールです。node.js でいうところの grunt や glup と似たものだと思えばOKです。

Gradle の良いところのひとつは、Gradle 自体の導入も不要な gradlew というラッパーが用意されていること。また、Java の豊富な資産を活用したさまざまなタスクをポータブルに準備し、手軽に実行することができます。

おそらく Sass のファイルウォッチからのコンパイルできる環境が 15分くらいでできると思いますので、よければ試していただければ。この方法は OS 環境に依存しないので、他の人とプロジェクトを共有するのもとても楽です。(フォルダをそのまま相手に配布するだけでそのまま全部働きます)

Gradle 環境は、Windows、Mac OS X、Linux とも同じ方法で動作させることができます。ここでは Mac での操作を紹介してみます。

(のハズだったのですが、実行に使われる gradle-jruby に Windows で動かす場合の不具合があって 2015/3 月時点では動きません。。すでに修正がでているようなので、なおり次第記事をアップデートします)

Java の導入

環境の構築とビルドに使う Gradle というプロダクトが OS に依存するのは Java の JVM のみです。

ターミナルを起動して「java -version」を入力し以下のような結果がでれば導入済みなので何もする必要はありません。次の「Gradle テンプレートのダウンロード」に進みます。

gradle00

macbookpro:~ hiromasa$ java -version
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)

OS X で Java が未導入の場合、次のダイアログがでますので、詳しい情報を押下してダウンロードサイトにいきます。

gradle01

「JDK」から「jdk-8u25-macosx-x64.dmg」を探し、上部の「Accept License Agreement」ラジオボタンを選択し、リンククリックでファイルをダウンロードします。(jdk-8u25 の u25 はバージョン番号です。より新しいものがあればそちらを選択してください)

gradle02

.dmg をダブルクリックし、インストーラを起動して JDK を導入します。

gradle03

インストール後、一度ターミナルを開きなおして「java -version」して前述の表示がでれば準備完了です。

Gradle テンプレートのダウンロード

Gradle から Sass をコンパイルするための gradle-compass プラグインの定義ファイルと構成一式を以下からダウンロードします。(構成はぼくがそれなりにつくったものです)

https://github.com/h1romas4/gradle-template-web/archive/master.zip

.zip ファイルを任意の場所に展開して、自分の好みの名前をつけます。このフォルダがそのまま開発用の作業フォルダになります。

gradle10

ここでは「sample」にリネームしました。

gradle12

ターミナルのカレントディレクトリを「sample」に移します。(なお、この時パスに漢字などのマルチバイト文字が含まれるとビルドが不具合を起こすようですので、パスが半角英数字だけの場所にフォルダを配置します)

$ cd /Users/hiromasa/Desktop/sample

カレントディレクトリを移すには、ターミナルに cd スペースと入力したあとフォルダをドロップしてエンターを押すと確実です。

gradle13

できたら以下のコマンドを入力します。

$ ./gradlew compassWatch

gradle14

初回のみ、環境をインターネットからダウンロードするので時間がかかります。 5分ほどで終わりますのでのんびり待ちましょう。

gradle15

起動が無事完了すると、Sass ファイルのコンパイルウォッチ状態になります。これだけで環境構築は全て完了です。 😀

gradle16

作業をやめるときは Ctrl + C を押します。 後日再開する場合は、再び ./gradlew compassWatch してください。(今度はすぐ起動します)

Brakets からのファイル編集

「sample」フォルダ内の「www」フォルダの下に編集用の index.html と .scss ファイルのサンプルが用意してあります。 _sass/style.scss を編集するとウオッチが働いて css/style.css が生成される仕組みです。(ファイルは自由に追加できます)

HTML エディターである Adobe の Brakets でファイルを編集するとリアルタイムプレビューもできて便利です。

Brakets を導入し、「ファイル -> フォルダを開く」から「www」フォルダを選択します。

gradle20

フォルダ選択後、index.html を開き、画面右上の「雷アイコン」をクリックすると、リアルタイムプレビューモードでブラウザが起動します。

gradle21

_sass/style.scss を編集すると、ターミナルでウォッチが働き Sass のコンパイルが行われるとほぼ同時に、ブラウザがオートリロードし更新されます。

gradle22

なお、この状態でブラウザの開発者ツールを開くと、Brakets のリアルタイムプレビューの仕組みで改変された HTML が表示されてしまいます。

gradle23

開発者ツールのインスペクタなどを使いたい時は、Brakets の「雷アイコン」をもう一度押し、リアルタイムプレビューをきった状態にしてください。(プレビューがきれるだけで、ローカルで立ち上がった Web サーバはそのまま残るので、リロードなどの操作をしても問題ありません)

編集中の HTML や CSS がそのまま見えるようになります。 Gradle の Sass のコンパイル時に map ファイルを生成しているので、Firefox などでは対応した style.scss のソースを表示することができます。

gradle24

この制作環境を人に渡したい時は、フォルダごとぽいっとあげればOKです。相手方で同じように「./gradlew compassWatch」してもらえれば動きます。とてもポータブルで便利です。

さて最後に、Gradle でどんなことをやっているか気になったり、コンパイルオプションが気になった方は sample フォルダにある build.gradle を覗いてみてください。

/**
 * compass & sass build setting.
 * 
 * @see https://github.com/robfletcher/gradle-compass
 */
compass {
    cssDir = file("www/css")
    sassDir = file("www/_sass")
    // nested, expanded, compact, compressed
    outputStyle = "expanded"
    sourcemap = true
    noLineComments = true
    debugInfo = false 
}

Gradle はこの他にも Web 制作環境で役立つプラグインが沢山ありますので試してがってん!

(久しぶりのブログでオチが弱い上にどこかの記事とかぶってる…)

WireframeSketcher でワイヤーフレームドキュメント作成

以前、サイトを眺めてすごいなぁと思っていたものの、有料($99)だったため試さなかった、WireframeSketcher を本日購入してみました。

用意された部品や操作系を元に、アプリケーション開発時のワイヤーフレームやモックアップなどのドキュメント作成を支援するソフトウェアです。 SI の世界だと、エクセル方眼紙でやっちゃうような、外設の画面設計書をつくるの、で通じるでしょうか(笑)

WireframeSketcher

WireframeSketcher is a wireframing tool that helps designers, developers and product managers quickly create wireframes, mockups and prototypes for desktop, web and mobile applications. It’s a desktop app and a plug-in for any Eclipse IDE.

デザイナー、開発者、プロダクトマネージャさん向け。

Eclipse GEF/EMF ベースでつくられており、Windows、Mac、Linux 対応。ダウンロードしすぐ実行できるオールインワンのスタンドアローン版の他、Eclipse プラグイン版も用意されています。

130422-0007

下のような、描くのも変更するのも大変そうなイラストが、

wp_tree_f

次のテキスト入力だけで作成できてしまう。。

wp-content
-plugins
--otenki
---otenki.php
-themes
--[v] twentyeleven
--[v] twentytwelve

なんてことだ...

このことだけで、なんでもっと早く試さなかったのだろうと後悔です。。15日のお試し期間中の 1 日目で購入してしまいました。

以下、これまたどう考えても描くの面倒だろうJK、と言われそうな一覧表とフォームの組み合わせも、

130422-0019

こんな感じのテキストでサクッとつくることができます。

130422-0020

あっという間。。 🙂

試しに、このサイト hiromasa.another のモックアップを作成してみました。

130422-0011

出力を手書き風味にできるのがポイントで、(お客さんなどに)まだデザインとかはイメージですよ、というようなことを表現できるとのことです。

ちなみに Screen のプロパティーを Sketch から Clear に設定することで、びしっとすることもできます。

130422-0002

びし。まっすぐ。

130422-0010

WireframeSketcher の操作はパレットビューより部品を選択し、ぺたぺた貼り付け、それぞれの個別属性を指定していく感じです。

部品は PC 用、モバイル、Android、iOS、Web フォームなどなど沢山。 これらは一般的な .svg 形式で、フォーマットに従えば自分で描いた絵も部品に取り込むことができるようです。

130422-0021

ブログのコメントフォームを描いてみたの図。

130422-0022

ドローアプリとしての操作感は、利用開始当初、レイヤー機能がないため若干厳しい部分あるかなと思いましたが、アウトラインビューなどからのZオーダ設定、グルーピング系と、そのグループへの突入(?)、またプロパティーからの位置ロック操作をうまく使えば、問題なく描くことができると感じました。

130422-0023

画面上、オブジェクトの単一選択と矩形選択の切り替えの UI がぱっと分かりませんが、(Fn + ) F3/F4 でそれぞれに切り替わります。クリック to ドラッグの範囲選択において、カーソル位置のオブジェクトを引っ張りたくないケースでは F4 を押すといいと思います。

さて、WireframeSketcher の良いところのひとつは保存形式に XML のテキスト形式が用いられていることで、さらに画像となる .svg ベクターデータと、骨組みとなる .screen データは完全に分離されています。

このため、骨組みの .screen の変更履歴をみると、どの部分が修正されたかが分かります。

130422-0016

スクリーンショットは新旧ファイル差分を出した図。–File Three が増えてその下のアイテムの y 座標が増えたことが分かります。

このように、WireframeSketcher はテキストファイルベースのデータ形式を採っているため、ローカルヒストリーの利用や Subversion、Git などバージョン管理との統合も得意です。

Eclipse マーケットから EGit や Subclipse などを追加することで Git や SVN が使えるようになるハズです。(スタンドアローン版 は Eclipse Juno ベース。自分は Eclipse Juno for JavaEE に WireframeSketcher をプラグインの形で入れました)

さて、ぼくは普段からドキュメントの作成に Eclipse Mylyn の .textile サポートを使っていましたので、今回ワイヤーフレーム作成に WireframeSketche という心強い見方が統合されたことになります。

ワイヤーフレームはもちろん、ちょっと億劫だなと思っていた図形の描画もできるようになってとても嬉しいです。 🙂

130422-0018

ブログ”徹底解析”シリーズを Eclipse で書いているの図。

日本に一人しかいないんじゃないかと思うくらいの Eclipse の利用法ですが、ソースコード見ながら記事を書くことが多いので、この使い方はすごく便利です。(ちなみに 300ページの原稿に耐えてます)

上記スクリーンショット下部は、PlantUML。これもテキストベース図形描画 & Eclipse プラグインあり。 UML を描くツールですが、これがまた色々な用途に使えるのです。

PlantUML についてはプログラマーズ雑記帳さんが非常に参考になります。(とても助かりました!)

PlantUML の使い方 | プログラマーズ雑記帳

テキストから UML を生成する PlantUML についての解説記事を書いてみました。

PlantUML の Eclipse プラグインについては、そのうちまた。 🙂

MacBook Pro 購入

CSS Nite などにいくと、OS のシェアが逆転したんじゃないかと錯覚するほど MacBook を使われている方が多いことに気がつきます。WordPress ハンズオンなどでも MacBook を持ってこられる方が多く、貸してもらって操作をするたびに Mac OS X におびえているのです(笑)

WordPress入門ハンズオン1巻にてハムさん。:)

てなわけで、そろそろ覚えておかないといかんのじゃないの?ということで、買いましたぞ MacBook Pro。:)

15インチの安い方に、非光沢 1680×1050 解像度のパネルに替えて 16万なにがしでした。(ぼくは圧倒的にソースコードみる時間が長いので液晶は非光沢にしているのです)

とりあえず、アプリは Eclipse さえ入っていればなんとかなるので一番最初にインストール。 cocoa-swt もきれいに動きますね。:)

Mac で便利なのは control キーの存在。ぼくは Linux とかも CapsLock に CTRL あてていますが、これはあくまで CTRL キー。 control として別キーにアサインできるのが良い感じです。 というわけで、Eclipse にも emacs キーアサインできるです。いつも忘れるので書いておきます。

Previous Column ^B
Next Column ^F
Line Up ^P
Line Start ^A
Line End ^E
Line Down ^N
Delete Previous ^H

ほかにもたくさんありますが、とりあえず。:)

Firefox は何もしなくてもこのキーアサインききました。Adobe さんのアプリはきかなかったような?

Eclipse は先日でました最新版 4.2 な Juno を使っています。 せっかくなので入れているプラグインのアップデートサイトも書いておきましょう。

Groovy Update Site – http://dist.springsource.org/release/GRECLIPSE/e4.2/
https://svn.codespot.com/a/eclipselabs.org/jsdt-jquery/updatesite
org.eclipse.php.repository – http://download.eclipse.org/tools/pdt/updates/3.1.1/nightly
Subclipse 1.8.x Update Site – http://subclipse.tigris.org/update_1.8.x

PHP Developer Tool のバージョンが Juno の標準リポジトリでは 3.0  のままになっています。SP1 あたりで 3.1 が入りそうな雰囲気ですが、とりあえず nightly をいれています。まだちょっとバグっぽい動作するようですがなんとか。

Java 系で、cocoa な SWT と LWJGL で OpenGL を動作させたの図。

いい感じに動きます!

ただ、ぼくの MacBook Pro では OpenGL 動かしたり、でかいプログラムコンパイルしたりするとあっという間にパームトップが熱くなってしまうのがいたい。長時間の開発は厳しいくらい熱せられるので、外部キーボード使うか、マシンの下にすのこたんとかファンをおくとかしないといけなそうです。ここは継続調査で。

てなかんじで、届いたのは水曜日くらいで Mac の操作をちょっと覚えましたら、土曜日の WordPress ハンズオンで早速役立ってくれました。よかった 🙂

8/25 のWordPress入門ハンズオン2巻もがんばりますので、よろしくお願いいたします!

Redmine 1.2.1 on JRuby/Tomcat

少し前に VPS の Tomcat7 にデプロイしようとして失敗していました、Redmine 1.2.1 さんですが本日また再挑戦してみました。 前回の失敗は JRuby のバージョンを間違っていたという寒いオチなことが分かりましたので、今回は割とすんなりいきました。。 🙂

Rednime は Ruby 1.8 系で動作なのですね、見落としていました。

Redmineのインストール | Redmine.JP

RedmineはたいていのUNIX, Linux, Mac, Windowsシステム等、Rubyが利用可能なシステムで実行できます。

Redmineの各バージョンで必要となるRailsのバージョンは以下の通りです。

というわけで、対応する JRuby は 1.5 系。 前回は 1.6 系つまり Ruby 1.9 でやってしまっていたのでした。 とほほ。

ちなみに JRuby を使うとこういう時に便利で、たとえば OS の Ruby パッケージとか気にしなくても依存関係なくポータブルにインストールすることができます。

というわけで、環境は以下の感じです。

[root@capibara redmine-1.2.1]# java -version
java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
Java HotSpot(TM) 64-Bit Server VM (build 20.1-b02, mixed mode)
 
[root@capibara bin]# /opt/apache-tomcat-7.0/bin/version.sh 
Using CATALINA_BASE:   /opt/apache-tomcat-7.0
Using CATALINA_HOME:   /opt/apache-tomcat-7.0
Using CATALINA_TMPDIR: /opt/apache-tomcat-7.0/temp
Using JRE_HOME:        /usr
Using CLASSPATH:       /opt/apache-tomcat-7.0/bin/bootstrap.jar:/opt/apache-tomcat-7.0/bin/tomcat-juli.jar
Server version: Apache Tomcat/7.0.19
Server built:   Jul 13 2011 11:32:28
Server number:  7.0.19.0
OS Name:        Linux
OS Version:     2.6.18-274.3.1.el5
Architecture:   amd64
JVM Version:    1.6.0_26-b03
JVM Vendor:     Sun Microsystems Inc.
 
[root@capibara redmine-1.2.1]# jruby -v
jruby 1.5.6 (ruby 1.8.7 patchlevel 249) (2010-12-03 9cf97c3) (Java HotSpot(TM) 64-Bit Server VM 1.6.0_26) [amd64-java]

適当に JRuby 1.5 を展開してパスを通して Redmine に必要な gem を追加。

# jruby -S gem install rack -v=1.1.1 --no-rdoc --no-ri
# jruby -S gem install rake -v=0.8.7 --no-rdoc --no-ri
# jruby -S gem install i18n -v=0.4.2 --no-rdoc --no-ri
# jruby -S gem install activerecord-jdbcpostgresql-adapter -v=0.9.7  
# jruby -S gem install warbler

ポスグレで動作させるために、activerecord-jdbcpostgresql-adapter を入れていますが、最新バージョンであるとプロジェクト操作時に以下のエラーで落ちてしまうため、0.9.7 に落としています。

   1: ActiveRecord::StatementInvalid (ActiveRecord::JDBCError: ERROR: column "issues.id" must appear in the GROUP BY clause or be used in an aggregate function: SELECT COUNT(*) AS count_all, tracker_id AS tracker_id FROM (SELECT DISTINCT "issues".id FROM "issues"  LEFT OUTER JOIN "projects" ON "projects".id = "issues".project_id  LEFT OUTER JOIN "issue_statuses" ON "issue_statuses".id = "issues".status_id  LEFT OUTER JOIN "trackers" ON "trackers".id = "issues".tracker_id WHERE (((projects.id = 1 OR (projects.lft > 1 AND projects.rgt < 2))) AND issue_statuses.is_closed='f') AND (projects.status=1 AND projects.id IN (SELECT em.project_id FROM enabled_modules em WHERE em.name='issue_tracking'))  GROUP BY tracker_id ) count_all_subquery):

Rails の O/R が生成している SQL が不正してしまっているように見えますね。 とりあえず、古いバージョンならうまく動くようです。

次にポスグレに DB を作成。

# su - postgres
-bash-3.2$ createuser -P redmine
Enter password for new role: 
Enter it again: 
Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) y
Shall the new role be allowed to create more new roles? (y/n) n
CREATE ROLE
-bash-3.2$  createdb redmine -O redmine
CREATE DATABASE
-bash-3.2$ psql -l
        List of databases
   Name    |  Owner   | Encoding  
-----------+----------+-----------
 postgres  | postgres | SQL_ASCII
 redmine   | redmine  | SQL_ASCII
 template0 | postgres | SQL_ASCII
 template1 | postgres | SQL_ASCII
(4 rows)

Redmine の database.yml を作成。

[root@capibara redmine-1.2.1]# pwd
/root/install/redmine-1.2.1
[root@capibara redmine-1.2.1]# cat config/database.yml
# MySQL (default setup).
 
production:
  adapter: jdbcpostgresql 
  driver: org.postgresql.Driver
  database: redmine
  host: localhost
  username: redmine 
  password: 
  encoding: utf8

この状態で Rails の DB マイグレートを実行。

# jruby -S rake generate_session_store
# jruby -S rake db:migrate RAILS_ENV="production"

Tomcat にインストールしたいので warble。 まずは config 作成その後に war 作成。

# jruby -S warble config
# cat config/warble.rb 
# 下の方に追加
config.dirs = %w(app config lib log vendor tmp lang)
config.gems << "activerecord-jdbcpostgresql-adapter" 
config.gems << "i18n" 
config.gem_dependencies = true
config.webxml.rails.env = 'production'
config.gems["rack"] = "1.1.1" 
config.gems["rake"] = "0.8.7"
config.gems["activerecord-jdbcpostgresql-adapter"] = "0.9.7" 
# jruby -S warble

あとはできた war を Tomcat7 にデプロイしてあげれば動作します。

添付ファイル格納域が WEB-INF/files になってしまいますので、シンボリックリンクで消えないところに飛ばしてあげています。(これは config で設定できたような気もします)

といわけで、

redmine51

無事動きました。 🙂

さて全然関係ないですが、以上 VPS に SSH つないで操作していますが、実は今までさぼってターミナルマルチプレクサ系を入れていませんでした。 yum update 中に回線切れたら、がびーんということで、併せて本日インストール。

tmux です。 CentOS 5.7 にはパッケージないっぽかったので、ソースからインストール。 以下のライブラリに依存するようでしたので、devel を入れています。

# yum install libevent-devel ncurses-devel

あとは、普通に ./configure && make && make install でいけると思います。 😀

redmine50

らいらい。と。

さくらの VPS と Apache Tomcat7

突然ですが、さくらの VPS を借りてみることにしました。 🙂

当初はこの VPS に家から VPN でつなぎっぱなしにして、うちのローカルサーバの一部の機能を外に出す使い方を考えていたのですが、まぁ実際そこまでする要件もなさそうなので断念(一応、Android からの接続もできたのですが)。

というわけで、Groovy とか Rails とか PHP 以外のアプリケーションが動作するお遊びサーバとしてスタートです。

最近だとたまにこのサイトでもでてきます、Cloud Bees とか dotCloud とか無料の PaaS つかってもその手のアプリは割と簡単に動かすことができるのですが、無料だとドメインマッピングに制限があったり、ちょっと不自由。 お金を払うとなると VPS と同じくらいかもっと高い料金になりますので、自由度の高いほうに転んだ感じです。

あ、ちなみにここ .another はそのままコアサバです(笑)

というわけで、アプリケーションサーバ選択。 OS はさくら標準の CentOS 5.5 のままです。

Jetty にしようか Tomcat6 、いやいや Tomcat7 でしょ、とか、ここで GlashFish とか。。 しばし考えて、あまり根拠もなく Tomcat7 が選択される。 7 は初めて触りますが、勝手知ったるなんとかでなんとなかるでしょう? 😀

Java6 は Oracle 提供の .rpm を、Apache httpd と PostgreSQL は CentOS のパッケージのものを。 Tomcat7、Groovy は それぞれからの提供のものを /opt に展開インストール。

そういえばバーチャルホストでトム設定するの初めてだったので微妙にてこずりました。。

Groovy のパス設定。(ファイルつくる)

[root@capibara ~]# cat /etc/profile.d/groovy.sh 
# groovy
PATH=/opt/groovy-1.8/bin:${PATH}

ポスグレの表領域位置指定。(標準で /home にパーティションきられているので表領域を /home/postgres に移動。 サービス起動前に前に以下のファイルつくる)

[root@capibara postgres]# cat /etc/sysconfig/pgsql/postgresql 
PGDATA=/home/postgres
[root@capibara postgres]# chkconfig postgresql on
[root@capibara postgres]# service postgresql start

ポスグレ initdb 等。(たとえばユーザつくって redmine の DB 作成の図)

[root@capibara home]# su - postgres
-bash-3.2$ 
-bash-3.2$ initdb -D /home/postgres/
-bash-3.2$ createuser -P redmine
Enter password for new role: 
Enter it again: 
Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) y
Shall the new role be allowed to create more new roles? (y/n) n
CREATE ROLE
-bash-3.2$ createdb redmine -O redmine
CREATE DATABASE

Tomcat7 バーチャルホスト設定。 $CATALINA_HOME/conf/server.xml の Engine に追加。

<Engine name="Catalina" defaultHost="localhost">
  <Host name="apps.maple4ever.net"
     appBase="apps.maple4ever.net"
     unpackWARs="true"
     autoDeploy="true" />
</Engine>

$CATALINA_HOME/apps.maple4ever.net のディレクトリを作成。 ちなみに adduser tomcat して、$CATALINA_HOME 配下を tomcat 権限に、また Tomcat は同ユーザで commons-deamon 起動しています。クラスパスの jar が 6 と違うので要注意。

このディレクトリに .war 入れるとファイル名をコンテキストパスとしてデプロイされます。

Apache のバーチャルホスト及び mod_proxy_ajp 設定。 指定のコンテキストパスを Tomcat になげます。 /etc/hosts や /etc/sysconfig/network なども設定のこと。

[root@capibara www]# cat /etc/httpd/conf.d/proxy_ajp.conf 
 
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
 
NameVirtualHost *:80
 
<VirtualHost *:80>
   ServerName unknown 
   <Location />
      Order deny,allow
      deny from all
   </Location>
</VirtualHost>
 
<VirtualHost *:80>
   ServerName apps.maple4ever.net 
   <Location /captcha-grails>
      ProxyPass ajp://apps.maple4ever.net:8009/captcha-grails
   </Location>
   <Location /click-examples>
      ProxyPass ajp://apps.maple4ever.net:8009/click-examples
   </Location>
</VirtualHost>

Location でおしり / なしにすると、スラつけなくてもいい感じに飛ばしてくれるようです。

てなかんじで、端折っているのであんまりメモにもなっていませんが(笑) 実際には、iptables の設定なども加わるでしょう。

Groovy + Grails のサンプルアプリ。(そのうち消えます)

sakura2011072402

Apache Click のサンプルアプリ。(そのうち消えます)

sakura2011072403

やぁ、動いた!

さすがに JVM だけあってさくさく動きますね。

sakura2011072401

さくら VPS はメモリ 1G のサーバにしていますが、これで残りメモリ 400M ほど。 ポスグレがフル稼働していないのでなんともですが、アプリが 1つか 2つは動きそうな感じです。

さて、何して遊びましょう。 🙂

Apache Tomcat 6.0.32 インストールメモ

すいません、完全に自分用のメモです(笑)。。

Redmine さんを家で動かす(JRuby on Rails 動作)ようになってからローカルサーバで Apache Tomcat が常時起動になりましたが、 そのバージョンが 6.0.32 に上がっていましたのでアップデートしてみました。 CentOS 5.5 でデーモン起動しています。

こういうの Redmine の wiki に書いておいているのですが、Tomcat アップデート中は Redmine みれないのでこちらに。。(笑)

IMG_0097

まずは動作環境。

$ uname -a
Linux localhost.localdomain 2.6.18-194.32.1.el5 #1 SMP Wed Jan 5 17:53:09 EST 2011 i686 i686 i386 GNU/Linux
$ java -version
java version "1.6.0_21"
Java(TM) SE Runtime Environment (build 1.6.0_21-b06)
Java HotSpot(TM) Server VM (build 17.0-b16, mixed mode)

いままで全然気が付かなかったのですが、Linux 版の Java はデフォルト Server VM モードであがるんですね。 Windows は Client VM がデフォルトであがるので、Linux でも Server VM 使うように昔から引数設定していましたが、、実は不要だったようです。

てなわけで Tomcat ダウンロードしてデーモン起動する jsvc をつくって入れるまで。 /opt/tomcat6 にいれています。 tomcat ユーザは作成のこと。

$ sudo /etc/init.d/tomcat6 stop
$ cd /opt
$ sudo wget http://ftp.jaist.ac.jp/pub/apache/tomcat/tomcat-6/v6.0.32/bin/apache-tomcat-6.0.32.tar.gz
$ sudo tar zxvf apache-tomcat-6.0.32.tar.gz
$ sudo mv apache-tomcat-6.0.32/ tomcat6/
$ sudo chown -R tomcat:tomcat tomcat6/
$ sudo cp /opt/tomcat6/bin/commons-daemon-native.tar.gz /root
$ sudo su - root
# cd
# tar zxvf commons-daemon-native.tar.gz
# cd commons-daemon-1.0.5-native-src/
# ./configure --with-java=/usr/java/default/
# make
# cp jsvc /opt/tomcat6/bin/
# chown tomcat:tomcat /opt/tomcat6/bin/jsvc
# /etc/init.d/tomcat6 start
# /etc/init.d/tomcat6 stop
# cd /opt/tomcat6/conf/Catalina/localhost/
# vi redmine.xml
# cp redmine.xml redmine.xml.org
# chown tomcat:tomcat *
# chmod 644 *
# /etc/init.d/tomcat6 start

ちなみに、redmine.xml はコンテキストルートと .war のパス設定のみ。

$ cat /opt/tomcat6/conf/Catalina/localhost/redmine.xml
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/redmine" docBase="/home/apache/redmine/redmine.war" />

デーモン起動用の init.d シェル。

$ cat /etc/init.d/tomcat6
#!/bin/sh
#
# chkconfig: - 80 20
# description: jsvc

# Source function library.
. /etc/init.d/functions

JAVA_HOME=/usr/java/default
CATALINA_HOME=/opt/tomcat6
TOMCAT_USER=tomcat
TMP_DIR=/tmp
CATALINA_OPTS=
CLASSPATH=\
$JAVA_HOME/lib/tools.jar:\
$CATALINA_HOME/bin/commons-daemon.jar:\
$CATALINA_HOME/bin/bootstrap.jar
PIDFILE=/var/run/tomcat.pid
LOCKFILE=/var/lock/subsys/tomcat
DAEMON=$CATALINA_HOME/bin/jsvc

start(){
    #
    # Start Tomcat
    #

    echo -n "Starting tomcat6: "
    $DAEMON \
    -pidfile $PIDFILE \
    -user $TOMCAT_USER \
    -home $JAVA_HOME \
    -Dcatalina.home=$CATALINA_HOME \
    -Djava.io.tmpdir=$TMP_DIR \
    -outfile $CATALINA_HOME/logs/catalina.out \
    -errfile '&1' \
    $CATALINA_OPTS \
    -cp $CLASSPATH \
    org.apache.catalina.startup.Bootstrap

    #
    # To get a verbose JVM
    #-verbose \
    # To get a debug of jsvc.
    #-debug \
    RETVAL=$?
    if [ $RETVAL = 0 ]; then
        echo_success
        touch $LOCKFILE
    else
        echo_failure
    fi
    echo
}

stop(){
    #
    # Stop Tomcat
    #
    echo -n "Shutting down tomcat6: "
    $DAEMON \
    -stop \
    -pidfile $PIDFILE \
    org.apache.catalina.startup.Bootstrap
    RETVAL=$?
    if [ $RETVAL = 0 ]; then
        echo_success
        rm -f $PIDFILE $LOCKFILE
    else
        echo_failure
    fi
    echo
}

case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        start
        ;;
    status)
        status $DAEMON
        RETVAL=$?
        ;;
    *)
        echo $"Usage: jsvc {start|stop|restart|status}"
        exit 1
        ;;
esac

Apache httpd と Apache Tomcat をつなぐ proxy_ajp.conf。

$ cat /etc/httpd/conf.d/proxy_ajp.conf

LoadModule proxy_ajp_module modules/mod_proxy_ajp.so

#
# When loaded, the mod_proxy_ajp module adds support for
# proxying to an AJP/1.3 backend server (such as Tomcat).
# To proxy to an AJP backend, use the "ajp://" URI scheme;
# Tomcat is configured to listen on port 8009 for AJP requests
# by default.
#

#
# Uncomment the following lines to serve the ROOT webapp
# under the /tomcat/ location, and the jsp-examples webapp
# under the /examples/ location.
#
#ProxyPass /tomcat/ ajp://localhost:8009/
#ProxyPass /examples/ ajp://localhost:8009/jsp-examples/

ProxyPass /redmine ajp://localhost:8009/redmine

Tomcat と全然関係ないですが、fastladder を動かしている passenger.conf。

$ cat /etc/httpd/conf.d/passenger.conf
LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-2.2.15/ext/apache2/mod_passenger.so
PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-2.2.15
PassengerRuby /usr/bin/ruby

<VirtualHost *:8081>
   ServerName localhost.localdomain
   DocumentRoot /opt/fastladder/public
   <Directory /opt/fastladder/public>
      AllowOverride all
      Options -MultiViews
   </Directory>
</VirtualHost>

さらに関係ないですが、Redmine とつないでいる subversion.conf。

$ cat /etc/httpd/conf.d/subversion.conf

LoadModule dav_svn_module     modules/mod_dav_svn.so
LoadModule authz_svn_module   modules/mod_authz_svn.so

#
# Example configuration to enable HTTP access for a directory
# containing Subversion repositories, "/var/www/svn".  Each repository
# must be readable and writable by the 'apache' user.  Note that if
# SELinux is enabled, the repositories must be labelled with a context
# which httpd can write to; this will happen by default for
# directories created in /var/www.  Use "restorecon -R /var/www/svn"
# to label the repositories if upgrading from a previous release.
#

#
# To create a new repository "http://localhost/repos/stuff" using
# this configuration, run as root:
#
#   # cd /var/www/svn
#   # svnadmin create stuff
#   # chown -R apache.apache stuff
#

<VirtualHost *:8082>
   <Location />
      DAV svn
      SVNParentPath /home/apache/svn
      SVNListParentPath on
      DavDepthInfinity on
      Order deny,allow
      Deny from all
      Allow from 127.0.0.1
      Allow from 192.168.0.0/24
      AuthType Basic
      AuthName "Authorization Realm"
      AuthUserFile /home/apache/passwd/.htpasswd
      Require valid-user
   </Location>
</VirtualHost>

以上。

すいません、すいません。。

Redmine 1.0.5 + JRuby + Tomcat6 デプロイ

最近、主にローカル Wiki として活躍してくれている Redmine が 1.0.5 にアップデートされましたので追従してみます。 セキュリティーフィックスも含まれるとのことです。

1.0.5 より i18n で必須 gem が追加になっていますので、JRuby + Tomcat デプロイ時は設定が1つ変わりますのでメモがてら。 🙂

Redmine 1.0.5 bug/security fix リリース | Redmine.JP

12月23日(日本時間)、Redmine 1.0.5がリリースされました。

Redmine 1.0.4に対して11個の修正・3個の脆弱性対策が行われています。

Redmine 1.0.5には脆弱性の修正も含まれているため、Redmineオフィシャルサイトでは全てのRedmineユーザーに対して最新版へのアップグレードを呼びかけています。

gem 追加について。

インストール・アップグレード時の注意

Redmine 1.0.5より、Rubyの国際化ライブラリi18nのバージョン0.4.2が実行時に必要です。インストール・アップグレードに先立ちサーバ上で以下のコマンドを実行してi18n 0.4.2をインストールしてください。

gem install i18n -v=0.4.2

というわけで、 JRuby で動かしている場合は、

$ sudo jruby -S gem install i18n –v=0.4.2

こういう感じで gem を追加です。

でもって、warble の config に依存 i18n を追加します。

# config を redmine 用に修正(一番したに追加)
sudo vi config/warble.rb 
config.dirs = %w(app config lib log vendor tmp lang)
config.gems << "activerecord-jdbcpostgresql-adapter" 
config.gems << "i18n" 
config.gem_dependencies = true
config.webxml.rails.env = 'production'
config.gems["rack"] = "1.0.1" 

これで、 sudo jruby -S warble でできた war を Tomcat とかにデプロイすれば動作するハズです。 🙂

redmine20 

参考、リンク。

hiromasa.another » Blog Archive » Redmine を Tomcat6 にデプロイ

hiromasa.another :o)» Blog Archive » 年末のデータバックアップ

 

がってん、がってん。

Redmine を Tomcat6 にデプロイ

先日インストールしましたプロジェクト管理ツールの Redmine ですが、1.0.1 として 1系の正式版がでました!

というわけで、先日は mod_rails で動作させていましたが、せっかくなので今度は JRuby を使って Tomcat6 上にデプロイしてみたいと思います。

なにか利点があるかって話ですが、1パッケージにして JavaVM で動作させておけば、OS にのっている Ruby 実行環境に依存しなくて済むのがいいところ。 gem のバージョン依存とか考えなくていいし、Servlet の実行環境さえあればどこにでも乗せられるのでなかなか便利かもしれません。

とりあえず、.war 玉をつくる作業した環境は以下の通りです。

[hiromasa@localhost ~]$ java -version
java version "1.6.0_21"
Java(TM) SE Runtime Environment (build 1.6.0_21-b06)
Java HotSpot(TM) Server VM (build 17.0-b16, mixed mode)
[hiromasa@localhost ~]$ jruby -v
jruby 1.5.2 (ruby 1.8.7 patchlevel 249) (2010-08-20 1c5e29d) (Java HotSpot(TM) Client VM 1.6.0_21) [i386-java]
[hiromasa@localhost ~]$ sudo /opt/tomcat6/bin/version.sh 
[sudo] password for hiromasa: 
Using CATALINA_BASE:   /opt/tomcat6
Using CATALINA_HOME:   /opt/tomcat6
Using CATALINA_TMPDIR: /opt/tomcat6/temp
Using JRE_HOME:        /usr
Using CLASSPATH:       /opt/tomcat6/bin/bootstrap.jar
Server version: Apache Tomcat/6.0.29
Server built:   July 19 2010 1458
Server number:  6.0.0.29
OS Name:        Linux
OS Version:     2.6.18-194.11.1.el5
Architecture:   i386
JVM Version:    1.6.0_21-b06
JVM Vendor:     Sun Microsystems Inc.

まずは、JRuby のインストールから。

$ sudo wget http://jruby.org.s3.amazonaws.com/downloads/1.5.2/jruby-bin-1.5.2.tar.gz
$ sudo tar zxvf jruby-bin-1.5.2.tar.g
$ cat /etc/profile
export JRUBY_HOME=/opt/jruby-1.5.2
export PATH=$PATH:$JRUBY_HOME/bin

でもって、必要な gems を入れていきます。 ぼくは PostgreSQL で動作させているため、jdbc はポスグレのになります。

$ sudo jruby -S gem install rail
$ sudo jruby -S gem install activerecord-jdbcpostgresql-adapter
$ sudo jruby -S gem install warbler
$ sudo jruby -S gem install rack --version '~> 1.0.1

warbler というのが、Rails のアプリを .war 玉にしてくれるありがたいものです。 あと、rack が 1.0.1 じゃないと後で Redmine を動かしたときに Exception するので入れておきます。

でもって、Redmine をダウンロードしてきて、普通に config を設定していきます。 config/database.xml については以下のように。

[hiromasa@localhost redmine-1.0.1]$ cat config/database.yml
# MySQL (default setup).
 
production:
  adapter: jdbcpostgresql
  driver: org.postgresql.Driver
  database: [dbname]
  host: localhost
  username: [username]
  password: [password]
  encoding: utf8
  scheme_search_path: public

以下、Redmine のファイルを置いた直下のディレクトリにて。

これで DB のマイグレーションができるハズです。(ここでは .war をつくるのと同じ環境に入れてます)

$ sudo jruby -S rake db:migrate RAILS_ENV="production"

でもって、いよいよ warbler で .war をつくります。 まずは config をつくってもらいます。

$ sudo jruby -S warble config

ほいでもって、できた config を編集。

config/warble.rb

config.dirs = %w(app config lib log vendor tmp lang)
config.gems << "activerecord-jdbcpostgresql-adapter"
config.gem_dependencies = true
config.webxml.rails.env = 'production'
config.gems["rack"] = "1.0.1"

最後の rack のバージョン指定をしないと依存関係でおちるようです。(新しい方が使われてしまう)

できたら、いよいよ。

   1: $ sudo jruby -S warble

 

[root@localhost redmine-1.0.1]# ls -laF redmine-1.0.1.war 
-rw-rw-rw- 1 root root 17230199  8月 28 16:01 redmine-1.0.1.war

 

キター!

こころを込めて配置します。 ここでは、war つくった環境と同じなのでそのまま…

$ sudo /etc/init.d/tomcat6 stop
$ sudo cp redmine-1.0.1.war /opt/tomcat6/webapps/redmine.war
$ sudo /etc/init.d/tomcat6 start

無事デプロイ成功。 起動しました。 🙂

redmine20

でもって、添付ファイルについてが気になって調べてみたのですが、どうやら WEB-INF/files に置かれる模様。 こんなところに置いてたらちょっとしたことで消えちゃういますのでシンボリックリンクで対応。

$ sudo ln -s /home/apache/redmine/files/ files

デプロイするたびにですが、しょうがないですね。 設定とか実はあるのかもしれませんがとりあえず。 あとは必要なら mod_ajp でつなぐなど。

というわけで、できあがった redmine.jar と Tomcat さえあればどこでも動くようになりました。 とりあえず事務所に持って行きます。。(笑)

DB マイグレーションは、 .war 作成でつかった JRuby 自体もただコピーするだけで他に持って行けると思うので、それでマイグレーション動かするのが良さそうですね。

エクスポートインポートでいければ Stax Networks とかにもデプロイできるかもしれません。(ただしファイルがかけないため、添付ファイルはだめだと思われる)

さて気になる .war ファイルですがほどいてみると以下のようになっていました。

redmine21

画像が小さくて見にくいですが、WEB-INF/gems/gems に依存する gems が格納されるようです。 あとは、ひとつの filter から jruby を起動して .rb を動的コンパイルしつつ動作という感じでしょうか。

動きはきびきびして、いい感じです。 先ほど入れて一通り動作見たばかりなので、もうちょっと動作させてみたいと思います。

以上、デプロイ田中でした。 ざっ。

Java + LWJGL + OpenGL で 2D ゲーム

先日、事務所の先輩と話をいたしておりまして、ゲームつくりますか、やろうやろう、みたいな進行に 🙂

ということでとりだしてきました、 OpenGL の Java ラッパー LWJGL。 OpenGL で古き良き 2D 描画をなんとか再現してやろうかと奮闘中であります。

Web で 3D を描く WebGL とかも同じような感じですし、iPhone/touch も Android も OpenGL ですし最近あちこちに OpenGL があふれていますね。

てなわけで、LWJGL というのは、Java 向けにかかれたゲームライブラリで、基本的には OpenGL (や音声、入力部)への薄いラッパです。

lwjgl.org – Home of the Lightweight Java Game Library

LWJGL provides developers access to high performance crossplatform libraries such as OpenGL (Open Graphics Library) and OpenAL (Open Audio Library) allowing for state of the art 3D games and 3D sound. Additionally LWJGL provides access to controllers such as Gamepads, Steering wheel and Joysticks. All in a simple and straight forward API.

OpenGL のコマンドを native に変換してくれる static メソッドがいっぱいある感じで、Linux、Windows、Mac、Solaris と各 native jni が用意されているので、Java と組み合わせることでいろんな環境でゲームなどのプログラムを動作させることができます。

これが速いし、みなさんに twitter で試していただいたところ、Windows、Linux、Mac の各 32/64bit でちゃんと動作したりしてなかなかよくできているようです!

Ubuntu 10.04 / 64bit での動作。

sprite01

Windows 7 / 32bit での動作。

sprite02 

すばらしいっ。

で中身の方なんですが、ぼくはゲームのプログラムというと CPU のクロックが 4MHz とか 8MHz だった時代(間違えのようなクロックですが本当です)でしかやったことがなかったので、どうしていいのやら(笑)

なんとなくイメージ的に 2D でも 3D の機能をつかって、四角いポリゴンをつくってそこにテクスチャーをはってスプライトや背景を実装するというのは知っていたので、あちらこちらのソースを参考につくってみました。

  • キャラクタスプライト。 小さな GL_QUADS をたくさん表示させて実装。 RGBA の透過と、1テクスチャに複数のアニメパターンを描いて切り替えて表示するのも実装。
  • マップ型 BG面。 配列をよんでチップを選択してテクスチャからタイルパターンを FBO(Frame Buffer Object)に描画して 1枚絵にしてから貼り付けて実装。
  • 1枚絵の BG面。 ただでっかいテクスチャを貼り付けただけ。 だとつまらなかったので、ピクセル(フラグメント)シェーダを登録してライト的な効果をつけてみた。

こういうやり方があっているのかどうか、まったく分かりません。 むしり取った衣笠と併せて超手探りです(笑)

ソースとかまだめっちゃくちゃで試している状態ですが、もし気になる方がいらっしゃいましたら実際に動かしてみてください。 Java Web Start を使っていますので、以下をクリックして「プログラムで開く」してもらえれば、大抵の環境でそれとなく動くと思います。

jws 

(Ubuntu の方は sun-java6 じゃないとだめかもです。 OpenJDK は未確認)

リソースとかまだ借り物ですごめんなさい。 作成中のものがおいてありますので、ここで書かれているものより機能が追加されているかもしれません。

てなわけで、環境によっては 1000フレームを超えるとのことで、恐るべき時代ですね。 (よしともさんいつもありがとうございます!)

昔は処理速度稼ぐために「描かなくていいところは描かない」ことが基本でしたが、いまなんかフルフレームで全描換えですもんねぇ。 8bit 時代は画面クリアするだけでどれほどかかったことか(笑)

などと遠い目をしつつもうちょっとがんばってみたいと思います。 🙂