« January 2009 | Main | March 2009 »

February 2009

2009.02.28

カスタムクエリ画面で作成日を条件に抽出したい

カスタムクエリ画面で更新日を条件に抽出したい
カスタムクエリ画面で更新日を条件に抽出したい(2)

 コメントにも記載されておりますが、初期のカスタマイズ版だと表示項目のところに「更新」が2つ表示されたりします。ということで、その対応やら、作成日での抽出(範囲指定可能)機能を追加したバージョンを公開しておきます(例によって、行番号は参考程度にお考えください。おそらく、そのままではパッチは適用できません)。

ダウンロードはこちらから ticket-r214.patch (5.6K)

#もしかすると、他の変更内容に関するパッチが中途半端に混じってしまっているかもしれません・・・。

| | Comments (0) | TrackBack (0)

2009.02.26

JOTMの2PCのコネクション

 JOTMを用いてTwo Phase Commit の続き(?)。

 JNDIを用いずに全て自前で処理を行うようにしていたのですが、どうもDBコネクションが残り続けるという現象が。当然のことながら、取得したjava.sql.Connectionはcloseしていることはソースで確認済み。

 ソースコードで追ってみると、org.enhydra.jdbc.standard.StandardXADataSource クラスから getXAConnection() をするところで、毎回コネクションを作成している模様。これが原因で解放されないコネクションが残り続けているようです。
 で、さらに調べてみると、XAConnectionからgetConnection()で取得したConnectionをcloseするのは当然ながら、XAConnectionに対しても明示的にcloseをする必要があるっぽいです。

 2PCに関しては(そうそう使う機会がないので)詳しくはないのですが、XAConnectionってそんなものなんでしょうかね? XAConnectionから取得したConnectionをcloseした場合、自動的にXAConnectionの方もcloseして欲しいような気もしつつ。

| | Comments (0) | TrackBack (0)

2009.02.23

Perf4J : org.perf4j.LoggingStopWatch

 多分、Perf4Jのライブラリを使うにあたって、もっとも基本的なクラスになるのではないかと(ライブラリ中でもっとも基本的なクラスは org.perf4j.StopWatch ですが、これだけだとログ出力等は行われないので)。

public void hoge() {
  long start = System.currentTimeMillis();
  // some task A
  System.err.println(System.currentTimeMillis() - start);
  start = System.currentTimeMillis();
  // some task B
  System.err.println(System.currentTimeMillis() - start);
  // some task
  start = System.currentTimeMillis();
  for (int i=0; i<10; i++) {
    // some task C
    System.err.println(System.currentTimeMillis() - start);
    start = System.currentTimeMillis();
  }  
}

ってな感じのソースが、

public void hoge() {
  StopWatch stopWatch = new LoggingStopWatch();
  // some task A
  stopWatch.lap("A");
  // some task B
  stopWatch.lap("B");
  // some task
  stopWatch.start();
  for (int i=0; i<10; i++) {
    // some task C
    stopWatch.lap("C");
  }
}

って感じで記述することができます。

Continue reading "Perf4J : org.perf4j.LoggingStopWatch"

| | Comments (0) | TrackBack (0)

2009.02.22

Perf4J

 Perf4J・・・Perf4J is to System.currentTimeMillis() as log4j is to System.out.println()(System.out.println()に対するlog4jのように、Perf4JはSystem.currentTimeMilles()に対するものである)。

 「ある範囲の処理に要した時間をログ等に出力するライブラリ」って感じですね。ログファイルへの出力の他に、JMX経由でデータを取得できるようにすることもできるようです(ログの内容を元に簡単な集計を行ってくれるクラスも提供されているようです)。

 ただ、処理時間の測定は常に必要となるわけではないため、動的に切り替えたいところではあります(処理時間の測定処理そのものも、実行回数が多くなってくると無視できない負荷になってきますし)。

 幸い、AspectJと組み合わせるとアノテーションで処理時間測定処理を埋め込むことができるようになるので、基本的にいろいろなところにアノテーションを付加した状態で、処理速度の情報を取得したい場合にweavingするように設定ファイルを書き換えることで、近いことができるような感じ? もっとも、weavingはクラスのロード時に行われるため、Webアプリケーションなどで稼働中に出力のオン/オフを切り替えることはできないと思いますが。
 あと、アノテーションを付加していないメソッドの処理時間を測定したくなることもあるかと思いますので、設定ファイルで後からAOPの対象メソッドを指定できた方がもっと便利かも、と思ったりも。

| | Comments (0) | TrackBack (0)

2009.02.21

DB2の自動インストール

応答ファイルのキーワード(DB2 9.5)

応答ファイルを用いてインストールする場合、

setup.exe /m /u (応答ファイルのパス)

のような感じで実行。

もっとも、実際にはいきなり応答ファイルを作成するのではなく、setup.exeを通常(GUIモード)起動し、そこで応答ファイルを保存したものをベースに編集した方が楽だと思われます(ちょっとした修正をテキストエディタで行うような感じでしょうか)。

| | Comments (0) | TrackBack (0)

2009.02.19

SAStruts&Velocity

SAStruts + Velocity (1) SAStruts + Velocity (2)

 SAStrutsとVelocityも、やっぱり組み合わせて利用することができるんですね。しかも、


  • vmファイルはjspと同様にWEB-INFフォルダの下に配置することができるので、vmファイル直接呼び出しを防ぐことも簡単。

  • Velocityテンプレートで使用する値は、public fieldを利用可能。

1年ほど前に、SAStruts+Velocityは使えるのだろうか? ってことを考えたのですが、当時はTeedaを用いて開発中だったので(SAStrutsに関しては)無期限保留状態に。ただ、その後、その開発案件でいろいろとhtmlテンプレートに悩んだこともあり、次はSAStruts+Velocityという選択肢もありかも。Seasar2本体に関するノウハウはおそらくそれなりに共通して使えると思いますし。

| | Comments (0) | TrackBack (0)

2009.02.18

Seasarの環境の切替

以下の3つのフェーズ(環境)が存在することは、それなりによくあるのではないかと思います。

・各メンバーの開発環境⇒HOTdeployで
・テスト環境(テスト用サーバにデプロイ)⇒COOLdeployで
・本番環境(一般公開用サーバにデプロイ)⇒COOLdeployで

 テスト環境と本番環境はできるだけ揃えておくことが望ましいかと思いますが、必ずしもそれを準備できるわけでもなく(というか、完全に同一の環境を2つ準備できるようなケースはほとんどないのでは)。

 例えばコネクションプールの設定をテスト環境と本番環境とで切り替えたいような場合、env.txtファイル内の環境名を切り替えると同時に、定義ファイルの条件インクルードを組み合わせることで、実現できそうな感じ?

 デフォルトでは、環境名がct/ut以外の場合は全てCOOLdeployになりますので、

■開発環境:ct ⇒ jdbc_ct.diconを読み込ませるようにする
■テスト環境:test ⇒ jdbc_test.diconを読み込ませるようにする
■本番環境:product ⇒ jdbc.diconを読み込ませるようにする(jdbc_product.diconをあえて作らない)

といった感じでしょうか。あるいは、開発環境とテスト環境で使用するDBが同一(jdbc_ct.diconの内容とjdbc_test.diconの内容が完全に一致する場合)なのであれば、ct/testの時はjdbc.diconを読み込ませるようにして、本番環境用に別途jdbc_product.diconを定義するというのもありかもしれません(逆に、jdbc_ct.diconとjdbc_test.diconから共通の別diconファイルをincludeするというのもありかも)。

 ただ、いずれの場合もwarファイルのビルド時あるいはデプロイ時にenv.txtを差し替えるという処理を別途追加する必要はありますが。個人的には、test用とproduct用の2種類のwarファイルを作成するのはできれば避けたいところなので、本番環境にwarファイルをデプロイする際に、シェルスクリプトなどでenv.txtも書き換えてしまうという方法を採用しそうです。

#他にもっといい方法があるのかもしれませんが。

| | Comments (0) | TrackBack (0)

2009.02.17

TeedaでマルチマスタDBの更新を行う

 複数台のサーバでPostgreSQLを稼働させている場合、pgpoolなどを用いることでマルチマスタDBの環境を構築することができますが、pgpoolなどを使用せずにSeasar2 + TeedaでマルチマスタDBを更新する方法のメモ。ただし、実際にこのような方式でいいのかどうか、および記述している内容が本当に正しいのかどうかは不明です(^^; (もっと楽な方法があるのかもしれません)

  • Seasar2 + Teedaの環境の場合、基本的にdoXxxやinitialize/prerenderはJTAを利用したトランザクションになっているので、(JDBCドライバが対応していれば)特に意識することなくTwo Phase Commitで処理されるため、DBの内容の一貫性は保てる(もちろん、2PCも万能ではないため、100%という保証はできませんが・・・)。
  • s2container.findAllComponents(ConnectionPool.class) で、コンテナに登録されているConnectionPoolオブジェクトを全て取得することができる。戻り値はConnectionPoolの配列になるので、ループで処理することが可能(戻り値がObject[]なのでキャストは必要となりますが)。
  • コネクションプールからのコネクションの取得は、ConnectionPool#checkOut()で行う。戻り値はConnectionWrapperで、StatementやPreparedStatementは、このWrapperから取得する(getPhysicalConnection()などでさらに内側のコネクションを取得する必要はなし)。
  • デフォルトの状態だとdoXxxの終了時に自動的にcommit(例外が発生した場合はrollback)が行われるので、明示的にcommit等をしなくても可。
  • コネクションの解放はConnectionWrapper#close()で行う。内部的に、ConnectionPool#checkIn(ConnectionWrapper)などが実行される。

 データの更新処理を行うところ全てでコネクションの取得処理を行うとなると面倒なので、現実的にはHelperクラスかLogicクラスなどで処理を行うことにするといい感じかも?

 なお、S2Dao等でカバーできる範囲であれば、こんな面倒なことをしなくてもOKのはずです。S2Daoの場合、1つの接続先に対して1つのインタフェースを定義しなければいけない(と思う)ので、接続先が増えてきた場合に管理が面倒になってきそうな感じなので、S2Daoを使わずに済む方法の模索、ということで(もちろん、接続先が増えた場合、最低限jdbc.diconの追加は必要となりますが)。

 ちなみに、複数のスキーマを使い分けるような場合においても、直接Connectionを取得した方が楽なケースも出てくるのではないかと(search_pathの指定である程度はカバーできますが)。

| | Comments (0) | TrackBack (0)

2009.02.16

SingletonS2Containerでキャストなしのコンポーネント取得

 多くの場合はコンポーネントはS2コンテナに任せている(DIでバインドしている)のですが、そうはいっても手動でコンポーネントを取得する必要が出てくるケースも。

 機能リファレンス - コンポーネントの取得によると、

Java5でS2Tigerを利用している場合、SingletonS2Containerを使うことでキャストを不要にできます。

とのこと。もっと早くに知っていれば・・・(^^;

 ちなみに、

Hoge hoge = SingletonS2Container.getComponent(Hoge.class);

のように、クラスを指定して取得する方法も、
Hoge hoge = SingletonS2Container.getComponent("hoge");

のように、コンポーネント名を指定して取得する方法も、両方サポートされているようです。

| | Comments (0) | TrackBack (0)

2009.02.15

byteaデータの書き込み

 PostgreSQLでbytea型のデータを書き込む処理のメモ。

1.PreparedStatementでSQLを構築する。
2.PreparedStatement#setBinaryStream(int, InputStream, int)でデータをセットする。なお、書き込むデータが既にbyte[]になっている場合は、setBytes(byte[])でも可(わざわざByteArrayInputStream()を作成しなくてもOK)。

 注意点としては、setBinaryStream(int, InputStream)や、setBinaryStream(int, InputStream, long)の場合は、is not yet implemented. ということでエラーになってしまうようです(postgresql-8.3-604.jdbc4のドライバで検証)。

 なお、bytea型のデータを読み込む場合は、ResultSet#getBinaryStream(int)を使用するか、あるいはbyte[]の状態のまま次の処理を行うのであればResultSet#getBytes(int)で取得してもOKのようです。

| | Comments (0) | TrackBack (0)

2009.02.14

暗号化してから圧縮するか、圧縮してから暗号化するか

 Javaにおいては、圧縮用のストリーム(ZipOutputStream/GZIPOutputStream)も、暗号化用のストリーム(CipherOutputStream)も両方とも標準で提供されています。いずれも、コンストラクタでOutputStreamを指定することができるので、「暗号化してから圧縮」も「圧縮してから暗号化」も簡単に切り替えることができます。

【暗号化してから圧縮】

new CiperOutputStream(new GZIPOutputStream(new ByteArrayOutputStream()), Cipher)

【圧縮してから暗号化】

new GZIPOutputStream(new CipherOutputStream(new ByteArrayOutputStream(), Cipher))

 外側にあるストリームから順番に処理されていくこととなります。ちなみに、暗号化することによりかなりランダムなバイト配列になってしまうため、前者の方だとほとんど圧縮が効かなくなってしまうというケースが多いかもしれません。実際、手元にある約6KBのテキストファイルで試したところ(暗号化はAES)、前者だとファイルサイズは数バイト大きくなりました(後者は約1/2のサイズに)。

 当然ながら、復号化する場合も順番を考慮しなければなりません。圧縮してから暗号化したデータを読み取る(=復号化してから展開する)場合は、

new GZIPInputStream(new CipherInputStream(new ByteArrayInputStream(byte[]), Cipher))

のような感じになります(入力の場合は、内側のストリームから順番に処理されます)。

| | Comments (0) | TrackBack (0)

2009.02.12

BacthModifyPluginが機能しなくなる

 チケットにアラート表示のカスタマイズの影響で、BatchModifyPluginが上手く機能しなくなってしまっていました。

 調べてみると、TicketIDのリクエストパラメータを構築する部分に、不要な文字列が紛れ込むようになってしまっていたことが原因っぽい。
 とりあえず、BatchModifyPluginの template/batchmod.html ファイル内の、

$("input[@name=selectedTicket]:checked").each( function(){ selectedTix.push(this.value);} );

の部分を、
$("input[@name=selectedTicket]:checked").each( function(){
  var v = this.value;
  var pos = v.indexOf('\n');
  if (pos != -1) v = v.substr(0, pos);
  selectedTix.push(v.replace(/[ \r\n]/g,""));
});

のような感じで書けば動くようになりました。結構無理矢理な対応ではありますが(^^;

| | Comments (0) | TrackBack (0)

2009.02.11

copyでNULL値の読込

 PostgreSQLのCOPY を使うと、大量のデータを(SQLで処理する場合と比較し)高速に読み込ませることができます。

 ドキュメントによると、NULL値も取り込めるとのことですが、いくらやっても失敗してしまう・・・。と思ったら、何のことはない、テキスト中のNULL値が、\N(NULL値)ではなく\n(改行コード)になっていたことが原因でした・・・。

#ちなみに、psqlのセッションにおいて、

\pset null *NULL*

のような感じのコマンドを投げる(「*NULL*」の部分は表示させたい任意の文字列)と、selectした結果のNULL値の出力を切り替えることができます。

| | Comments (0) | TrackBack (0)

2009.02.08

JOTMを用いてTwo Phase Commit

 久しぶりにTwo Phase Commitが必要となるアプリケーションの開発を行うことに。前回の開発時はIBM WebSphere Appication Serverの環境下だったので、普通に(?)lookupで処理を行うことができました。しかしながら、今回はJavaアプリケーションにおいてもTwo Phase Commitが必要になってくるので、J2EEコンテナが必要というような方法は使用できず。

 S2JTAという選択肢も考えたのですが、諸事情により今回は見送り(S2JTAは「Java EEアプリケーション・サーバーに依存しない実装」も提供されているとのことですが、これはスタンドアローンアプリでも使用できるってことなんでしょうかね??)。

 Samples for Connection Pooling and Distributed TransactionsXA with Two-Phase Commit Operation--XA4.javaのような感じで、XAResourceなどを使用して自前で処理を記述するという方法もありますが、ソースの記述量が若干増えてしまうのが難点。

Continue reading "JOTMを用いてTwo Phase Commit"

| | Comments (0) | TrackBack (0)

2009.02.06

ATOK2009届いた

 注文しておいたATOK2009が無事に届きました。バージョンとしては、ATOK22に相当するようで(ちなみに、僕が使ったことのある一番古いバージョンはATOK5・・・小学生の頃なので、20年以上前のことですねぇ)。
 とりあえず無事にインストールが完了しましたが、ATOK2009の使い勝手そのものは・・・まぁ、これからってところですか(笑

 ちなみに、使用許諾契約書によると、旧バージョンに関しても、「同一の個人が使用する」「同一のコンピュータにインストールする」「管理者を同じくする別々のPCにインストールする」のいずれかに当てはまる場合は継続して利用できるとのことです(ちなみに、「同一人物が利用する場合で、かつ同時に使用しない」のであれば、同じバージョンを別々のPCにインストールして利用(例えば自宅と職場)してもOKということも記載されています)。

 このことからすると、旧バージョンにおいてセット版として購入したジーニアスや広辞苑等に関しても、引き続き利用しても問題ないという解釈になるんですかね??

| | Comments (0) | TrackBack (0)

2009.02.03

再帰的にプロパティセット(Windows)

 例えば、Excelファイルに対してサブフォルダ内のものも含めて再帰的にneeds-lockプロパティをセットする場合。コマンドプロンプトから、

for /R . %I IN (*.xls) DO svn propset svn:needs-lock "*" %I

を実行。カレントフォルダ以下の全てのフォルダのExcelファイルに対してプロパティがセットされますので、後はこの結果をコミットすればOK。

 注意点は、*の部分をダブルクォーテーションで囲っておかないと、ワイルドカードとして認識されてしまうってことでしょうか。

| | Comments (0) | TrackBack (0)

2009.02.02

ServerSocketのbacklog

ServerSocket serversocket = new ServerSocket(8888, 1);

ServerSocketを初期化する際に、backlogのパラメータを指定すると、キューのサイズを指定することができるとのこと。JavaDocによると、

キューが埋まっているときに接続要求があると、接続は拒否されます。

と記載されています。

 試しに、ServerSocketでリクエストの受信~返却に時間がかかるような処理を記述(といっても、Thread.sleep(5000) で強制的にウェイトをかけているだけですが)して、クライアントから複数リクエストをスレッドで投げた場合・・・3つ目のリクエスト以降、

java.net.ConnectException: Connection refused: connect

の例外が発生。1つ目の処理を実行中、2つ目のリクエストがキューに入り、その時点でキューが埋まったので3つ目以降のリクエストに対して「接続を拒否」したってことですね。

#ちなみに、0 を指定した場合は、初期値(50)が設定されるようですので、キューの数は最低1以上ってことになります。

| | Comments (0) | TrackBack (0)

2009.02.01

UnfuddleのインフラがAmazonEC2ベースに

Infrastructure Upgrades and Amazon EC2

ざっくり、以下のような感じ?(かなりの意訳あり・・・誤訳もあるかも)

・現在、Unfuddleは全体がAmazonEC2で動いている。
・膨大なUnfuddleのコード(Unfuddleのリポジトリに登録されているコードではなく、Unfuddleのサービスを構築しているコード?)を、スケーラブルなように回収した。
・パフォーマンスが大幅に改善された。
・各種ソフトウェアの更新も行ったが、その中で特筆すべきなのは、Subversionを1.5.xに変更したことである。それにより、SubversionのマージTrackingなどの機能を利用できるようになった。
・AmazonEC2のインフラを利用するようにしたことで、当面はインフラの増強をすることなくUnfuddleの強化(機能追加等)に力を注ぐことができる。

確かに、全体的にレスポンスが向上しているような気がします(特にSubversionリポジトリの過去のリビジョンに対してアクセスが発生するような操作を行った場合)。

#そういえば、サーバ側で動作しているSubversionのバージョンをクライアント側から知ることってできるんですかね??

| | Comments (0) | TrackBack (0)

« January 2009 | Main | March 2009 »