Firefox の Web 系開発者用プラグイン

http://chrispederick.com/work/firefox/webdeveloper/
– Web Developer Extension (Mozilla/Firefox plugin)
Documentation -> Features に機能一覧がある。Web 周りの言語の構文チェックが豊富。
– ちなみに国際化もされていて、そっちをいれれば日本語で使えるので安心。
 
– 難点:
— ローカルファイル検証(HTML/CSS のみ対応)のときも validator.w3c.org にデータを送信するため、公開するとまずい系には使うべきではないこと。

JSP 基本文法

– <% 〜 %> で囲んだ部分は全体で1つのメソッドのように Java コードが書ける.

<body>
  <%
    out.println(“Hello, world!”);
  %>
</body>

– <%= 〜 %> で囲んだ部分は一つの式として評価され、戻り値をその部分に表示する( つまり void は不可)。複文になってはならないため、セミコロンは用いない。

Your name is <%= name %>

– <%! 〜 %> で囲んだ部分はクラス内の定義とみなす

  <%!
    private static final int FOO = 1;
    private void final doSomething(String value){ /* do something */ }
  %>

– <%@ 〜 %> で囲んだ部分は JSP の制御タグとする

  <%@ page contextType="text/html; charset=EUC-JP" %>
  <%@ page import="java.sql.*" %>
  <%@ page import="java.util.*" %>

– JSP のインクルード構文:
— <jsp:include page=”foo.jsp” /> – 対象のページを 別に実行して, 結果を動的に(コンパイル後に)インクルードする。ローカル変数, request パラメータはファイルごとに独立になる。

view.jsp:
  <body>
    Hi, <jsp:include page=”inc.jsp”/>.
  </body>
 
inc.jsp:
  <%= "John" %>

— <%@ include file = "foo.jsp" %> – 対象のページをそのまま読み込み、静的に(コンパイル時に)インクルードする。ローカル変数は共存になり、インクルード対象(exp. inc.jsp)のファイルが更新されてもインクルード元(ex. foo.jsp)は再コンパイルされないため、全てのインクルード元について明示的に更新してやらなければならない。

view.jsp:
 <body>
   <%@ include file = "inc.jsp" %>
   Hi, <%= name %>.
 </body>
  
inc.jsp:
  <% String name = "John"; %>

– 参考:
http://www.javaroad.jp/servletjsp/index.html
– Java の道: Servlet, JSP

Java で MD5

java.security.MessageDigest を使うと簡単。

MessageDigest md;
try {
    md = MessageDigest.getInstance(“MD5”);
} catch(NoSuchAlgorithmException e) {
    e.printStackTrace();
    return;
}
// digest を求めるバイト列設定
// update(“Hello, world!”.getBytes()) と同じ。
md.update(“Hello, “.getBytes());
md.update(“world!”.getBytes());
// 計算して求めるがそのままだとバイト列なので文字列化.
final byte[] digest = md.digest();
final String sHexDigest; {
final StringBuffer buf = new StringBuffer(“”);
    for(int i=0; i < digest.length; i++){
        final int n = digest[i] & 0xFF;
        if(n < 16) buf.append("0");
        buf.append(Integer.toString(n, 16));
    }
    sHexDigest = buf.toString();
}
 
System.out.println(sHexDigest);

ネットワークにつながっているプロセスを調べる

– CUI では fport, GUI では ActivePorts というのがある。
http://www.foundstone.com/index.htm?subnav=resources/navigation.htm&subcontent=/resources/proddesc/fport.htm
– fport
http://www.ntutility.com/
– ActivePorts
http://www.atmarkit.co.jp/fsecurity/rensai/securitytips/003fport.html
– @IT:Security Tips – 自マシンの開きポートとプロセスの関係を確認する

JDB を使う

– 昨日の一件のおかげで初めて Java のデバッガを使うことに。
– デバッグ対象の JVM のオプションに

-Xdebug -Xrunjdwp:transport=dt_socket,address=50000,server=y,suspend=n

を追加して実行(Resin の場合は httpd.sh の args=”…” を -J-Xdebug -J-Xrunjdwp:…のように -J を付与)しておけば次のようなデバッグができる。

$ jdb -attach 50000

threads

グループ tcp-server:
  (java.lang.Thread)0x3b0 tcp-accept-8080 実行中
  (java.lang.Thread)0x3b1 tcp-accept-8080 状況待機中
  (java.lang.Thread)0x3b2 tcpConnection-8080-0 状況待機中

thread 0x3b2

tcpConnection-8080-0[1] suspend
すべてのスレッドが中断されました。
tcpConnection-8080-0[1] where
  [1] java.lang.Object.wait (ネイティブ メソッド)
  [2] com.caucho.server.TcpServer.accept (TcpServer.java:648)
  [3] com.caucho.server.TcpConnection.accept (TcpConnection.java:211)
  [4] com.caucho.server.TcpConnection.run (TcpConnection.java:132)
  [5] java.lang.Thread.run (Thread.java:534)
tcpConnection-8080-0[1] resume
すべてのスレッドが再開されました。

quit

という感じでかなり便利。
http://java.sun.com/j2se/1.4/ja/docs/ja/tooldocs/win32/jdb.html#description
– Sun JDK ドキュメント: jdb – Java デバッガ

JDBC のログとりメモ

– close() するのは PreparedStatement#close() でなく ResultSet#close() でもなく、絶対に Connection でなければならない。
– ログ情報には PreparedStatement#toString() がよさげ(少なくとも com.mysql.jdbc では)。
理由は、ログのための利便性から。SQLException がどのクエリでエラーになったかを残してくれないので、 PreparedStatement インスタンスがクエリ周りの情報をきっちり保持してくれていれば、toString() でログにどのクエリ文を実行したかが残せる。しかし、PreparedStatement#close() は DB 接続を閉じる仕様とは限らないため、Connection#close() を呼ぶ必要がある。PreparedStatement#close() だけにしたらプールがあふれ、思わぬ場所で DB 接続が開くのをずっと待ち続けることになってしまった。
– 例:

boolean isExist(int id){
    PreparedStatement ps = null;
    try{
        final Connection con = getConnection();
        try{
            ps = con.prepareStatement(“SELECT id FROM list WHERE id = ? LIMIT 1”);
            ps.setInt(1, id);
            return ps.executeQuery().next();
        }finally{
            con.close();
        }
    }catch(SQLException e){
        log(“Query error [“+ps+”]”, e); // void log(String, Throwable); とする
        return false;
    }
}

Bug Pattern というか今日のミス

– 事前に気づいたけど相当焦ったもの。

SELECT * FROM foo WHERE …;

な、ただレコードの有無を調べる(要素は取り出さない)クエリのパフォーマンスを意識して SQL クエリのみ書き換えたときに、うっかり次のようにしまった。

SELECT COUNT(*) FROM foo WHERE …;

常に 1 レコード返るようになり、レコード数 0 のときも毎回処理が行われることに… リリース前に自分で気づいたけれど反省。

委譲とコンポジション(Effective Java の間違い)

Effective Java には、自身を参照にして渡さないと委譲とは呼べない、とあるが、これは間違い。Effective Java にも挙げられている [GoF P32] には次のようにある。

委譲では、1 つの要求を 2 つのオブジェクトが扱う。要求を受け取ったオブジェクトは委譲者へオペレーションを委譲する。これは、サブクラスが親クラスに要求を渡すことと同様である。

Effective Java にある自身の参照渡しはどこからでてきたのかというと、多分次の文の誤解から。

しかし継承の場合は、継承されたオペレーションは、C++ ならば this メンバ関数、Smalltalk ならば self を用いて、要求を受け取ったオブジェクトを参照できる。委譲でこれと同じ効果を実現するには、要求を受け取ったオブジェクトが自身を委譲者に渡す。そうすれば、委譲したオペレーションが受け手のオブジェクトを参照できるようになる。

その他参考:
<http://www.ogis-ri.co.jp/otc/otc2/oosquare-ml/Archive/200005.month/767.html>
– オージス総研 ML

MySQL で ENUM を使うべきではない

– ENUM 型のカラムには、リストにない任意の文字列をエラーなしで指定できてしまうため、不具合の温床になりうる。例えば次のテーブルを考える。

CREATE TABLE `foo` ( `number` ENUM(‘zero’,’one’,’two’) NOT NULL DEFAULT ‘zero’);

これに zero, one, two 以外の値が入ることは望ましくないが、リストにない文字列をいれることで空文字が入ってしまう。

mysql> INSERT INTO `foo` VALUES (‘six’);
Query OK, 1 row affected, 1 warning (0.03 sec)
 
mysql> select * from foo;
 +——–+
 | number
 +——–+
 |
 +——–+
1 row in set (0.02 sec)

これは typo でも発生してしまうため、TINYINT などを使って、マジックナンバーは各言語の const 変数でラップしたほうがエラーを捕捉できていいかなと。

Servlet の基本

– 基本は通常のクラスと同じだが、条件として javax.servlet.http.HttpServletを親クラスとする必要がある。
– protected void do*(HttpServletRequest, HttpServletResponse)
doGet, doPost, doDelete, doHead, doOptions, doPut, doTrace があり、それぞれ対応するリクエストのときに呼び出される。
– protected void service(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException
別のオーバーロードされた service メソッドから処理を受け、配分するのが役目なので protected。
parent.service(req,res) を呼び出した時点で do*(req,res) の処理が行われるので、その前後の共通動作を定義するのに便利。
– 日本語(マルチバイト文字)を引数にとる
— getParametervalues,getParameterを使い、化けた状態の文字を取得したあと

new String(string.getBytes(“ISO_8859_1”), “Shift_JIS”);

のようにする。(HTTPプロトコルの文字コードが ISO-8859-1 のため)
— HttpServletRequestクラスのsetCharacterEncodingで、パラメータを取得する前にエンコードを指定しておく。
— HttpServletRequest#setCharacterEncoding(String enc) の挙動の違いの問題に注意!
Tomcat 4.1.29 以降の 4.1.*/5.0.16以降の 5.0.*、では、Getメソッドではエンコードされなくなった。GETの引数はURIに含まれるので、URIはエンコードされるべきではないという見解による仕様変更とのこと。
– スレッドセーフということ。
サーバサイドでは1つのインスタンスを使いまわしてマルチスレッドで動作するので、スレッド同士の不要な干渉をなくさなければならない。
“staticではない”フィールド(インスタンス変数)もスレッド間では共有されている事に注意!
–> ページ閲覧者固有の変数を持ちたい場合、メソッド内で定義した変数を使わなければならない。
データアクセスなど同期を取らないといけない場合は、(デッドロックにくれぐれも注意しつつ)適宜 synchronized にする。