のらぬこの日常を描く

ノージャンルのお役立ち情報やアニメとゲームの話、ソフトウェア開発に関する話などを中心としたブログです。

jetty + jndi(with c3p0)な環境から lightsleepを使って超簡単にDBに繋ぐ - デバッグができるようになるまで

どうも、のらぬこです。

この記事では、タイトルに記載の環境が eclipseデバッグ環境でも mvn jetty:run での環境でも正しく動作するところまでを記載します。

さて、最近、個人的に立ち上げてみたいWebサービスができまして、現在こっそり実装中です。

ただ、いかんせコード書き始めてまだ3日程度なので、使うフレームワークは今後変わるかもしれないし、そもそも途中で飽きるかもしれません。

が、今のところ、言語はJava、ApplicationServer には jetty、RDBpostgreSQL、Webフレームワークにはasta4dというフレームワークを選択しています。

O/R mapperとしてDomaを使おうかとも思ったのですが、最近見かけたlightsleepというO/R mapperを検証がてら使ってみることにしました。

下準備

開発環境

まずは開発環境として以下の環境を準備します。

  • Eclipse 4.5.2
    • すでにneon.2 まで出ていますが、そちらでも問題ないと思います。
  • run-jetty-run 1.3.5(Nightly)
    • Eclipse 内の market place からもダウンロードできますが、現在公開されているバージョンはjetty 9.0.0M3 までしか対応していません。
    • eclipseからデバッグ実行したとき、環境によっては(?)不具合が発生する可能性があるため、GitHub - xzer/run-jetty-run: Official successor of https://code.google.com/p/run-jetty-run/ を参考に、最新のnightly buildを使います。
      • market placeからダウンロードできる1.3.4を使用た場合、デバッガから起動した際に、使用するJettyのバージョンに関わらず、IndexOutOfRangeExceptionが大量発生する謎バグに遭遇することがあります。
    • なお、Eclipse market place を見ると、「Eclipse Jetty 3.9.0」 なるものもありますが、こちらのプラグインはjetty 起動時にc3p0を lib/ext としてjettyに食わせる手段がなさそうなので使えません。

とりあえずひな型WebAppの作成

これから開発を始めるという方は、まずはひな型Webプロジェクトを作成してください。

asta4dを利用する場合の手順は、GitHub - astamuse/asta4d: View first web application framework に手順が掛かれています。超簡単。

pomの設定を追加

下記のような形で書きます。とりあえず、今回追加が必要となる部分のみ抜き出しています。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>9.4.1212.jre7</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.2</version>
        </dependency>

        <dependency>
            <groupId>lightsleep</groupId>
            <artifactId>lightsleep</artifactId>
            <version>1.5.1</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/lib/lightsleep-1.5.1.jar</systemPath>
        </dependency>
    </dependencies>
</project>

なお、lightsleepは mvnrepository に登録されてなさそうなので、こちらを参考に、jarをダウンロードして pom.xml に systempath として追加しています。

jndiの設定を書く

jetty側

プロジェクトディレクトリに jetty ディレクトリを作成し、その中に jetty-local.xml という名前で jndiの設定(jetty側)を記載します。 jndi名、jdbc接続文字列等は各自適切に変更してください。

<!-- jetty/jetty-local.xml -->
<Configure id="noranuk0DB" class="org.eclipse.jetty.server.Server">
  <New id="noranuk0MasterDB" class="org.eclipse.jetty.plus.jndi.Resource">
    <Arg></Arg> <!-- score -->
    <Arg>jdbc/noranuk0DB</Arg> <!--  name -->
    <Arg> <!-- value -->
      <New class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <Set name="driverClass">org.postgresql.Driver</Set>
        <Set name="jdbcUrl">jdbc:postgresql://localhost:5432/kagure</Set>
        <Set name="user">admin</Set>
        <Set name="password">admin</Set>
      </New>
    </Arg>
  </New>
</Configure>

webapp側

src/main/webapp/WEB-INF/web.xml の web-app要素内に以下を追記します。res-ref-name は jetty-local.xml で指定した名前と同じものを設定してください。

<resource-ref>
    <res-ref-name>jdbc/noranuk0DB</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
</resource-ref>

lightsleepの設定

src/main/resources/lightsleep.property を新規作成し、以下のような感じで設定します。Databaseの欄は環境に合わせて適宜変更してください。

# for PostgreSQL
Logger             = Std$Out$Info
Database           = PostgreSQL
ConnectionSupplier = Jndi
dataSource         = jdbc/noranuk0DB

各環境ごとの設定例などは、Lightsleep/Manual_ja.md at master · MasatoKokubo/Lightsleep · GitHub を参照してください。

run-jetty-runの設定

  • $HOME/.m2/repository/ 以下から下記3つの jarを探してきて、プロジェクトディレクトリ内の適当な場所(jetty/lib/ext 等)にコピーします。
    • c3p0-0.9.5.2.jar
    • mchange-commons-java-0.2.1.jar
    • postgresql-9.4.1212.jre7.jar
      • JDBCドライバは、接続先DBによって適切なものに読み替えてください
  • Eclipse から [Run] - [Debug configurations…] を選択します。
  • 左サイドペインから [Jetty WEbApp]を選択します。
  • Jettyタブを開きます。
    • Jettyのバージョンは 9.3系(もしくは一番新しいバージョン)を選択します。
      • 9.2未満のバージョンを選択した場合、謎バグを踏むという不幸が訪れる可能性があります。
    • 一番下にある、[Show advanced option] を選択します。
    • JNDI support のチェックを入れます
    • Additional Jetty.xml の欄に 上で作成した jetty-local.xml のパスを指定します。
  • Jetty classpath タブを開きます
    • リストを一番下までスクロールさせると[Custom Jetty Classpath]という項目があるのでそれを選択します。
    • 最初にコピーした3つの jar を追加します。

ここまでの作業をしたうえで、デバッグを開始すれば、おそらく正常に実行されるはずです。

DBアクセスのテスト

URLがたたかれた時に動作するコードに、こんな感じのコード埋め込んであげると確認できるかと思います。

Transaction.execute(connection -> {
            Optional<Item> contactOpt = new Sql<>(Item.class)
                .where("id={}", 1)
                .select(connection);
            // 取得したレコード出力するなりなんなり
});

mvn jetty:run 向け pom.xml の設定

そろそろ書くのに疲れてきたので、jetty-maven-pluginの設定部分のみ貼っておきます。

こっち側は、jetty + jndi(with c3p0) が正しく動作するように設定を記載するだけです。

dependencies に c3p0 と jdbc drive を追加してあげないと、jettyが起動時にjndiの設定を行う際、c3p0などが認識できずエラーになってしまうので、ちゃんと書かないとだめです。

<project>
    <build>
        <plugins>
            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>9.4.0.v20161208</version>
                <configuration>
                    <webApp>
                        <contextPath>/</contextPath>
                    </webApp>
                    <httpConnector>
                        <port>8080</port>
                    </httpConnector>
                    <daemon>true</daemon>
                    <jettyXml>${project.basedir}/jetty/jetty-local.xml</jettyXml>
                </configuration>
                <executions>
                    <execution>
                        <id>start-jetty</id>
                        <phase>pre-integration-test</phase>
                        <goals>
                            <goal>start</goal>
                        </goals>
                        <configuration>
                            <scanIntervalSeconds>0</scanIntervalSeconds>
                        </configuration>
                    </execution>
                    <execution>
                        <id>stop-jetty</id>
                        <phase>post-integration-test</phase>
                        <goals>
                            <goal>stop</goal>
                        </goals>
                    </execution>
                </executions>

                <dependencies>
                    <dependency>
                        <groupId>org.eclipse.jetty</groupId>
                        <artifactId>jetty-io</artifactId>
                        <version>9.4.0.v20161208</version>
                    </dependency>

                    <!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
                    <dependency>
                        <groupId>org.postgresql</groupId>
                        <artifactId>postgresql</artifactId>
                        <version>9.4.1212.jre7</version>
                    </dependency>

                    <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
                    <dependency>
                        <groupId>com.mchange</groupId>
                        <artifactId>c3p0</artifactId>
                        <version>0.9.5.2</version>
                    </dependency>
                </dependencies>
            </plugin>

            <!-- -->
        </plugins>
    </build>
</project>

今回の話は以上となります。

lightsleep の使用感など、何かネタが出てくればそちらも記事にしたいと思います。

お読みいただいてありがとうございました。