Home > Seasar

Seasar Archive

Seasar Project用のHudsonテスト環境

Seasar Project用のHudsonテスト環境を用意しました。コミッタの皆さんいろいろな設定のジョブを登録してみてください。

サンプルで1個登録してありますが、Hudsonの使い方が良く判っていないのでもっと良い方法があると思います。追加されたジョブ設定を見て、良い使い方をWikiに用意したHudsonのページに集めていきます。

Pluginは適当に次のを入れてあります。他にオススメのものがあれば是非教えてください。

  • Disk Usage Plugin
  • JIRA Plugin
  • Task Scanner
  • Checkstyle Plugin
  • FindBugs Plugin
  • PMD Plugin
  • Warnings Plugin

Hudson導入に関して、開発者であるid:kkawa?さんとid:cactusmanさんからご協力のお申し出をいただいております。何か困ったことが起きてもこれで大丈夫です!ありがとうございます。

また、紹介してくださったid:skirnir?さんとid:j5ik2oさんありがとうございます。

完成、開発環境紹介

最後のフェーズまで実装して完成。あとは考慮漏れがないことを祈るだけ。開発期間は認証周りなどは以前作ったものを流用してたので1週間ちょい。今回使ったものは次のとおり。

  • 開発環境
    • Jiemamy: テーブル設計 (今回はERダイアグラムエディタとテストデータ管理としてしか使っていない)
    • H2 Database: 初期開発環境でのデータベース、初回リリース後は本番環境のPostgreSQLを使用して開発
    • S2JDBC-Gen: DDL -> Entity, Names, Service
    • Maven: ライブラリ管理、S2JDBC-Gen実行、warファイル生成
  • 作成した Web アプリケーションの環境
    • S2Container: DI x AOPコンテナ
    • Cubby: Web アプリケーションフレームワーク
    • Mayaa: Web テンプレートエンジン
    • S2JDBC: O/R Mapper (初期開発時: H2 Database, 初回リリース後: PostgreSQL)
    • S2Directory: O/D Mapper (開発環境: OpenDS?, 本番環境: OpenLDAP)
  • 本番サーバ環境
    • Apache: 2.2.x系なのでmod_proxy_ajp使用
    • Tomcat: アプリケーションサーバ
    • PostgreSQL: 本番環境データベース

S2JDBC-Genは最初Mavenと別にライブラリ管理するのに戸惑って使うつもりなかったもののid:j5ik2oさんのとこでMavenと連携させる例があって取り入れました。結果これが良くて、さらに途中で新バージョンも出ちゃったりして、既に作ってたServiceを移植してすべてタイプセーフに流れるようなインターフェース使うようになりました。第1フェーズ終えた後に、既にデータ入ってたテーブルを直さないと後のフェーズで処理が面倒になる箇所があって直したけど、タイプセーフだったおかげですぐに直すべきコード中の箇所も判り、かなり助かりました。

今回ほとんどS2JDBCの話題しか日記には書いてなかったけど、Jiemamyはじめ毎度ですがS2ContainerのHOT deploy、Cubby、Mayaaも超役立ってて、これらどれが欠けてても期間的にやばかった。

それぞれについて多少何か書くネタが出来たので気が向いたら日記に書いていくかも(^^)。

第1フェーズ完了

突貫工事だった割にエラー出ることなく第1フェーズ無事完了したようです。残りはフェーズ的には3つ。最後のフェーズでの動作機能はまだ完成していない。

1つ判ったのは、データベースでデータの依存関係を表せてないテーブル設計は後々プログラムでとても面倒な処理をしなければならないことになる。単に期間を表すテーブルだけでなく、その前後の繋がりや階層表現もデータベースの中で表現した方が良さそう。

今回それぞれのフェーズに対応する期間を表すテーブルはあったものの、前後関係をデータベースに持たせていなかったので面倒な判定処理が増えてしまった。フェーズというのはワークフローなので、escafeFlow使うと楽できそうなものの、サンプル動かしてもイマイチ判らず時間もなかったのでまた次回に。

間一髪・・・

あやうく予告してあったURLにPDFファイルを置いといて、「これを印刷して手で書いて出してください」っとなるとこだった。。ここ3日間必死になって作ってたWEBアプリの第1フェーズが完成し、利用開始3時間前にリリースという危ない橋を渡った(汗。次また3日間で全部完成予定。

最後の最後、利用開始6時間前ぐらいにH2 Database相手にしかテストしてなかったアプリを本番DBであるPostgreSQLにして突撃したらエラーが出てもうダメかと思った。。

エラーはPostgreSQLで text 型を使っているフィールドに対応するEntityクラスのフィールドに @Lob があったのがいけなかったらしい。それで、今あらためて検索してみたらkoichikさんが関連してる回答をされていた

  • 例外
org.seasar.framework.exception.SQLRuntimeException: [ESSR0072]SQLで例外(SQL=[], Message=[Bad value for type int : user1], ErrorCode=0, SQLState=22003)が発生しました
    at org.seasar.extension.jdbc.query.AbstractQuery.handleResultSet(AbstractQuery.java:443)
    at org.seasar.extension.jdbc.query.AbstractSelect$6.handle(AbstractSelect.java:413)
    at org.seasar.extension.jdbc.query.AbstractSelect$6.handle(AbstractSelect.java:410)
    at org.seasar.extension.jdbc.query.AbstractSelect$1.handle(AbstractSelect.java:283)
    at org.seasar.extension.jdbc.query.AbstractSelect$1.handle(AbstractSelect.java:281)
    at org.seasar.extension.jdbc.manager.JdbcContextImpl.usingPreparedStatement(JdbcContextImpl.java:144)
    at org.seasar.extension.jdbc.query.AbstractSelect.processPreparedStatement(AbstractSelect.java:278)
    at org.seasar.extension.jdbc.query.AbstractSelect.processResultSet(AbstractSelect.java:407)
    at org.seasar.extension.jdbc.query.AbstractSelect.getSingleResultInternal(AbstractSelect.java:232)
    at org.seasar.extension.jdbc.query.AbstractSelect.getSingleResult(AbstractSelect.java:177)
    at org.example.hoge.entity.AdminUserTest.testFindById(AdminUserTest.java:32)
    ...
  • 対応するEntityのフィールド
/** uidプロパティ */
@Lob
@Column(length = 2147483647, nullable = false, unique = true)
public String uid;

このEntityはS2JDBC-Genで生成したものですが、ソース見てみたら、org.seasar.extension.jdbc.gen.internal.dialect.PostgreGenDialectの225行目でtext型の時はlobをtrueにしているようです。

private static PostgreColumnType TEXT = new PostgreColumnType("text",
               String.class, true);

これをfalseにすれば良いんだろうけど、そうすると、EntityからDBスキーマを生成する時に影響してしまうのかな?

また、そうしたらそうしたらで、H2 DatabaseのCLOB使ってる属性に対応するEntityには@Lobが付くことになるのに、それをそのままPostgreSQLで使えば結局エラーが出るので、そもそも異なるDBサーバをいったりきたりして開発するのが間違いなのかもしれない。

とりあえず仮眠してからまた考えよう。

  • [追記 11:46]
  • DBスキーマ
CREATE TABLE admin_user (
  id BIGSERIAL NOT NULL PRIMARY KEY,
  uid TEXT NOT NULL UNIQUE
);
  • レコード例
INSERT INTO admin_user (id, uid) VALUES (1, 'user1');
  • Entity全体
@Entity
public class AdminUser {

    /** idプロパティ */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(precision = 19, nullable = false, unique = true)
    public Long id;

    /** uidプロパティ */
    @Lob
    @Column(length = 2147483647, nullable = false, unique = true)
    public String uid;
}
  • 例外が発生するテストケース例
    • uidの@Lob外すと例外出ずに正常に実行されるようになります。
public void testFindById() throws Exception {
    jdbcManager.from(AdminUser.class).id(1L).getSingleResult();
}
  • 実行されたSQL
select T1_.ID as C1_, T1_.UID as C2_ from ADMIN_USER T1_ where T1_.ID = 1

[追記 10/14 11:45]

本件、id:taediumさんとこのPostgreSQLのTEXT型はCLOBか否か?に続きがあり、PostgreSQLのTEXT型では@Lobを付けてはいけないということになりました。修正ありがとうございました。

コメントが付けられなかった件、tDiaryの「ツッコミ中でURLを表す文字の占める割合が70%より高いものはspamとみなす」という設定に引っかかってしまったのではないかと思います、すいません。数値を30%に変えておきました。

[追記 10/29 0:39]

すこし時間空いてしまいましたが、id:taedumさんとこのPostgreSQLのTEXT型はCLOBか否か? その2より、@LobつきStringをOID型ではなくTEXT型にマッピングすることになったそうです。

S2JDBCで複雑なSQLもタイプセーフに流れるようなインターフェースで書いた方が良いと思う理由

昨日書いたS2JDBCを使った複雑な↓のクエリ

public ThesisProfUser findByUidAndYear(String userId, int year) {
    return select()
        .leftOuterJoin(year())
        .leftOuterJoin(profUser())
        .leftOuterJoin(thesisAssignmentList())
        .leftOuterJoin(thesisAssignmentList().thesisStudentUser())
        .leftOuterJoin(
            thesisAssignmentList().thesisStudentUser().studentUser())
        .leftOuterJoin(thesisAssignmentList().assignmentVoteList())
        .where(
            new ThesisProfUserCondition().profUser().uid.eq(userId).and(
                new ThesisProfUserCondition().year().year.eq(year)))
        .getSingleResult();
}

これだけ見たらSQL生で書いたり、外だしSQLファイルで書いた方が良いと思う方もいると思います。てなわけで、複雑なSQLも↑のようにタイプセーフに流れるようなインターフェースで書いた方が良いと思う理由を書いときます。とても簡単な理由です。

  • DBスキーマを変更してEntityやNamesをS2JDBC-Genで生成し直すと、DBスキーマの変更に応じてコード中のどこを変更すべきかをコンパイラ(Eclipseなど)が「エラーとして教えてくる」

これです。属性名が1つ変わっただけでもコード中から参照している箇所を全部自力で探し出すのはツライですよね。1からコードを書く時に流れるように次々とEclipseが補完してくれるという大きなメリットもありますが、もっと重要だと思うのが↑です。

このことに関しては、S2JDBC-Gen開発者のtaediumさんがプッシュされているS2JDBC-Genのコンセプト機能?であるEntityからDBスキーマを生成する機能ではさらに一歩先をいっていると思います。スキーマから生成して後からエラー箇所を直すより、先にEclipseのRefactorでEntityを修正させてしまえば、1発でコード中のほとんどの箇所を直せてしまいます(JSPやMayaaなどのビュー部分で参照している箇所も一緒にRefactorされればさらに良い。。)。ただ、単純な修正ならこっちの方が確実で早いですが、テーブル構造的に大きく変えるとなると、リレーション部分をグラフィカルなERダイアグラムで直した方が全体が見通せて考えやすいかなとも思います(てなわけで、EntityをグラフィカルなERダイアグラムとして表示して編集できるPluginがあれば、EntityからDBスキーマを生成する機能が爆発的に使われるかも?)。

ちょっと脱線しましたが以上のような理由で、手元にあるコードではすべてのクエリをS2JDBCを使ったタイプセーフに流れるようなインターフェースで書いています。もしSQLファイルを使う例外があるとしたら、ぱっと思いつく中では次の2ケースぐらいでしょうか。

  • DBに定義してある特殊なストアドプロシージャを使いたい
  • DBが持つ独自関数を使いたい

でも、S2JDBCでいくらDBを簡単に扱えるようになってもまだまだ開発上で解決しない問題があります。それは、S2JDBC関係なく、根本的にDBスキーマの設計がダメダメなら欲しいデータをDBから取得するのはコストが掛かるし、コンパイラがエラー箇所を教えてくれるとはいえ構造的に大きく変更になればロジック部分も考え直さないといけなく、変更コストはやっぱし甚大。

というわけで、今使っているDBスキーマも修行が足りないとひしひし感じているので、もっと知識を集めて良くしたい。

Namesにjoinクエリ用文字列 -> Seasar2.4.30とS2JDBC-Gen 0.9.2で解決

whereはConditionで辿れるけど、そのConditionが使うjoinが辿れないので、S2JDBC-Genで生成されるNamesにそのテーブルから繋がっているテーブルすべてを網羅するjoinクエリ用文字列があれば便利かも。

"table1List"
"table1List.table2List"
"table1List.table2List.table3List"
  • [追記: 19:53]

ひがさんがコメントくださったように、書いた直後に新しくリリースされたSeasar2.4.30とS2JDBC-Gen 0.9.2で解決しました。しかも、流れるように書けるというもっといい感じに解決。

  • 利用例
    • leftOuterJoinの中は、static importsされたものでS2JDBC-Gen 0.9.2が生成するNames(例ではThesisStudentUserNames)に定義されている
    • whereのConditionもS2JDBC-Gen 0.9.2が生成している
    • orderByの中のdesc()は、org.seasar.extension.jdbc.operation.Operationsが持っている
public ThesisStudentUser findByUidOrderByYear(String uid) {
    return select()
        .leftOuterJoin(year())
        .leftOuterJoin(studentUser())
        .leftOuterJoin(thesisAssignmentList())
        .where(new ThesisStudentUserCondition().studentUser().uid.eq(uid))
        .orderBy(desc(year().year()))
        .getSingleResult();
}

すごい綺麗になった気がします。ただ次のようにConditionをandでつなぐケースだけはちょっと複雑になってしまうかもしれない感じ(何か別の書き方があるのかもしれない)。別の書き方をkoichikさんに教えていただきました、↓の方に追記あります。

public ThesisProfUser findByUidAndYear(String userId, int year) {
    return select()
        .leftOuterJoin(year())
        .leftOuterJoin(profUser())
        .leftOuterJoin(thesisAssignmentList())
        .leftOuterJoin(thesisAssignmentList().thesisStudentUser())
        .leftOuterJoin(
            thesisAssignmentList().thesisStudentUser().studentUser())
        .leftOuterJoin(thesisAssignmentList().assignmentVoteList())
        .where(
            new ThesisProfUserCondition().profUser().uid.eq(userId).and(
                new ThesisProfUserCondition().year().year.eq(year)))
        .getSingleResult();
}

何にせよS2JDBC-Gen使うとS2JDBCが異次元的に強力になりヤバいです。たぶん羽生さんのらくらくERDレッスンで勉強して組んだテーブルとの相性の良さは僕が知っているO/Rマッパーの中で一番高いと思う(残念ながらERDレッスンを未だに読み終えてないので似非テーブル設計しかできてないけど・・・)。

  • [追記: 21:30]

さらにkoichikさんがコメントくださったように、Conditionの部分も流れるように書けました!

public ThesisProfUser findByUidAndYear(String userId, int year) {
    return select()
        .leftOuterJoin(year())
        .leftOuterJoin(profUser())
        .leftOuterJoin(thesisAssignmentList())
        .leftOuterJoin(thesisAssignmentList().thesisStudentUser())
        .leftOuterJoin(
            thesisAssignmentList().thesisStudentUser().studentUser())
        .leftOuterJoin(thesisAssignmentList().assignmentVoteList())
        .where(eq(profUser().uid(), userId), eq(year().year(), year))
        .getSingleResult();
}

これは素晴らしい。。。XxxConditionいらないですね。

S2JDBC-Gen便利

S2JDBC-Genを初めて触ったけど良いですね。エンティティに@OneToMayや@ManyToOneも生成してくれたり、エンティティ以外にも対応するCondition、Names、Serviceも生成してくれていたせりつくせり。ConditionとNamesは使ったことなかったけど、今回生成されたのを使ってみたら、今までS2JDBC使った時に曖昧だったwhere内の "id = ?" などの部分がきっちりし、スキーマ変えてもエラー箇所が追随できるようになり全部ConditionとNames使うように変えました。

JIRA 3.13に上げたら日本語化された

見た目が変わってかなり違和感があるので以下の設定で今まで通りに。

  • General Configuration -> Default language: 英語 (UK)

Seasar Conference 2008 Autumnのお知らせ

Seasarだけでなく、いろいろなOSSプロダクトの話が聴けます!今週土曜と開催まで日はないですが、無料のイベントですので思い立ったらそのまま奮ってご参加ください。

以下、転載。

Seasarファウンデーションからイベントのお知らせです。

ご連絡が大変遅れましたが、今週末の土曜日に、法政大学市谷キャンパス外濠校舎3Fにて「Seasar Conference 2008 Autumn」を開催いたします。

開催日:2008年 9月 6日(土) 12:30 – 17:30 (12:00開場)

会場:法政大学市ケ谷キャンパス 外濠校舎3F

主催:特定非営利活動法人Seasarファウンデーション

後援:法政大学情報科学部

参加費用:無料

詳細:http://event.seasarfoundation.org/sc2008autumn/

Seasarファウンデーションでは、現在、春のSeasar Conferenceにて発表しました「OSS開発基金」改め、「Seasar基金」に対して取り組んでおり、Seasarファウンデーション傘下のOSS開発コミュニティだけではなく、国内のOSS開発コミュニティを支援していこうと模索中です。

その取り組みの一環として、今回の「Seasar Conference」では、OSS開発関係者各位に参加していただくため、スピーカーの公募を行いました。

結果、多くの方に賛同いただき、たくさんのスピーカーの方々に参加いただけました。

(セッション:http://event.seasarfoundation.org/sc2008autumn/Session

12:30から始まる理事会活動報告から、17:30に終わるLTまで、6レーン4セッション、合計26セッションです。

国内のOSS開発コミュニティを代表する方々のセッションで、国内OSSの普及を促進するとともに、東京工業大学教授の千葉先生や、早稲田大学客員教授の丸山先生のセッションで、これからのOSSのための「発見」や「気づき」などを得ることができればと思っております。

大変、ご連絡が遅くなりましたが、ぜひ、ご参加ください。申込みは、以下のURLからよろしくお願いいたします。

http://event.seasarfoundation.org/sc2008autumn/

ネットワーク不調 -> 停電

IIJの先でネットワーク障害がおきてるっぽいです。自宅のCATV経由だと繋がらず、別回線のASAHIネット経由だと繋がっているので、経路によってはまったくアクセスできない状況になっていると思われます。

おそらく上流の問題なので回復するまでしばしお待ちください。関係各位、ご迷惑をお掛けいたします。

[8/6 0:59追記] 上流以外にも建物ごと2回停電したようです。2台リモートで復旧でいない状況になっており、朝になって現地に行くまで復旧できないかもれいません。対象: ml.seasar.orgで動いているML、escafe.org

[8/6 10:24追記] サーバ全部復旧しました。でも他の施設がまだ停電したまま。実験機器とか壊れてないと良いね。

ホーム > Seasar

検索
フィード
メタ情報

Return to page top