こぶたのラッパ » 2009 年 2 月 26 日

Daily Archives: 2009 年 2 月 26 日

プログラミング

jsp:useBeanでジェネリックスを使う場合、classとtypeを両方指定する

Published by:

タイトルで言い切ってしまいましたが。

次のように書いたJSPコードをTomcat5.5で動かすと、「useBeanのクラス属性 java.util.ArrayList<ProductBean> の値が無効です」というエラーが出ました。

元コード
<jsp:useBean id="productList" class="java.util.ArrayList<ProductBean>" scope="request" />

ジェネリックスの型指定が気に入らないそうですが、そんな事言われてもあんたJava5でしょ?と言いたくなります。

ちなみにProductBeanクラスには引数なしのデフォルトコンストラクタが存在しますので、インスタンス化の失敗というわけではありません(引数なしのデフォルトコンストラクタのないクラスをclass属性でjsp:useBeanすると、同じようなエラーが出ます)。

そもそもインスタンスを作っているのはArrayListですので、 ProductBeanクラスに非はありません。
試しに「java.util.ArrayList<java.lang.String>」としても同じエラーが出ました。

対応策として、class属性の代わりにtype属性を指定するというものがあります。

対応策1
<jsp:useBean id="productList" type="java.util.ArrayList<ProductBean>" scope="request" />

これで上のエラーは出なくなりますが、これだとリクエストスコープに指定されたアトリビュートがセットされていない場合、「java.lang.InstantiationException: bean productList not found within scope」という別の例外になります。

必ず値がセットされているということであれば対応策1で良いのですが、そうではない場合対応策2になります。

対応策2
<jsp:useBean id="productList" class="java.util.ArrayList" type="java.util.ArrayList<ProductBean>" scope="request" />

「まさかなあ」という気持ちでこうしてみたら、これは動く。

JSPのバージョンのせいなのか、Tomcat5.5のバグなのか、はたまたこういう仕様なのか。
Tomcat6では未確認ですが、何ともおかしな振る舞いです。