- - PR -
JSPで別クラスのpublic static finalフィールドを使用した場合のデプロイ作業について
投稿者 | 投稿内容 | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2004-09-21 14:08
お世話になっております。
環境:WebSphere Application Server V5.0でJSPのプリコンパイルをしないに設定。 発生した問題:別クラスのpublic static finalフィールドの値を修正、JSPでこのフィールドを使用しているかつJSPに修正を加えていない場合、JSPがリコンパイルされず、修正が反映されない。 現在開発を行っている環境では定数用のクラスを用意し、そこでpublic static finalフィールドのみの宣言を行っています。 public class TestConst{ public static final String CONST_TEST1 = "10"; public static final String CONST_TEST2 = "20"; 以下続く ここでCONST_TEST1の値を"01"に変える必要が出たとして public static final String CONST_TEST1 = "01"; に変えます。 すると、JSPでCONST_TEST1を使用していても、JSP自体が変更されていないとリコンパイルされないので、修正が反映されません。 そこで質問なのですが。 1.一般的にデプロイするときは画面を全て開いてJSPを全コンパイルするか、又はプリコンパイル機能を使用してJSPを全コンパイルするのどちらかなのでしょうか? 2.public static finalフィールドのみの宣言を行っているクラスのフィールドをJSPで使用するのに問題があるのでしょうか? 3.public static finalフィールドのみの宣言を行っているクラス自体存在してはいけないのでしょうか? 4.一度定義したpublic static finalフィールドに修正を加えること自体が間違っているのでしょうか?(ただ、このpublic static finalフィールドのみの宣言を行っているクラスの意図としては、ここで宣言したフィールドを他のクラスで使うことで、ここのフィールドさえ修正するば他を修正しなくてよいようにするという考えもあります。) 以上、よろしくお願いします。 | ||||||||||||||||
|
投稿日時: 2004-09-21 14:55
こんにちは、がちゃぴんです。
プリコンパイルしないで定数クラスの定数値のみの変更の場合、 キャッシュ、又はJSPのCLASSファイルを削除してはどうでしょう? 初回のアクセス時に少々時間がかかりますが・・・。 または、WASの場合、JSPのCLASSファイルを直接上書きすることも 可能だったと思いますが、これは裏技的というか正攻法ではないと思いますので・・・。
1. →プリコンパイル機能を使用してJSPを全コンパイルするかなー 2と3 →1でプリコンパイル機能を使用していれば、問題ないのでは? 4 →固定値定義クラスの値は、変わらないに越したことはないでしょうが、 固定値の内容によると思います。 システムの設定値等、変更の可能性のある値の定義は、外部に定義した内容(DBやプロパティファイル等)を 読み込むようにすればよいでしょう。DBの項目値の取りうる値のような コード定義的なものも、そのようにしても問題ないでしょうし。 それ以外のプログラム的な定数値は、固定値定義クラスにあってもよいと思いますが、 あとは極力、変更しないようにするだけだと思います。 | ||||||||||||||||
|
投稿日時: 2004-09-21 14:56
疑問ですが、
なぜ他クラスの定数を修正しただけなのに、JSPをリコンパイルする必要があるのでしょうか? 定数はCのマクロとは違い、インライン展開されるものではありません。 あくまでJSPとは別の領域に定数として値が保持されるのですから、JSPがリコンパイル される必要は無いのではないでしょうか? # 勘違いでしたらすみません。 | ||||||||||||||||
|
投稿日時: 2004-09-21 15:14
[public static final]な変数はインライン展開される事があるそうです。 (プリミティブ型とStringが対象になったような・・・) 解決方法としては
の様にすると良いです。 (インライン展開されないので) [参考] 「Effective Java」のSafeEnumパターンを調べて見ると良いと思います [ メッセージ編集済み 編集者: ぽん 編集日時 2004-09-21 15:17 ] | ||||||||||||||||
|
投稿日時: 2004-09-21 15:25
こんにちは、じゃばらです。
public static final なフィールドの値がリテラルで宣言されている場合、 それを参照しているクラスをコンパイルすると class ファイルにリテラル値が埋め込まれてしまいます。 値をリテラルで宣言できるのは int や double などの各種プリミティブ型と 文字列(String クラスのオブジェクト)ですね。 おそらくパフォーマンス上の理由でこうなっているのでしょうが、 かなりいやな仕様ですよね。 せっかくクラス単位で開発できるのに、public static final 定数の値を変えたら参照しているクラス全ての リコンパイルが必要になるとは・・・ # コンパイラにも依るのかもしれませんが。 # 私がこの現象を確認したのは Sun の JDK の javac です。 | ||||||||||||||||
|
投稿日時: 2004-09-21 15:27
かぶってしまいました。
すみません。 | ||||||||||||||||
|
投稿日時: 2004-09-21 15:56
じゃばらさん、ぽんさん、ありがとうございます。
私のコメントはどうも教科書的な発言でしたね ![]() コンパイラによってはインライン展開することがあるとは、知りませんでした。 そうなると、この場合はコンパイル済みのJSPファイルを破棄すれば良いわけですね。 正式にやって良いことかどうかは分からないですが、WebLogicの場合はコンパイル済みの JSPのクラスファイルを直接削除すると、このような問題はうまく行った経験があります。 WebSphereでも同じようなことができるのではないでしょうか? そこで、最初の投稿の質問にお答えすると、
本番環境にデプロイする場合は、アプリケーションサーバのJSPプリコンパイル機能を 使って全JSPをコンパイルしてしまうことが多いかと思います。 追記# WebLogicではappcというプリコンパイラをEARファイルに対して実行すると、 追記# 内部のJSPをプリコンパイルしてくれちゃいます。
今回の問題はたまたまコンパイラの挙動のせいであって、私は問題は無いのでは ないかと思います。ただ、このような定数を使うにはScriptletを記述しないと いけなくなると思いますので、Taglibを使うなり、JSPを呼び出すServletで定数を Request Scopeに入れるなりして、Scriptletの使用は回避しても良いかも、とは 思います。 追記# あ、でも、こうやっちゃうと定数の参照をコンパイル時にチェック出来なく 追記# なりますね・・・。どっちが良いんだろ。
そんなことはないと思いますよ。
間違っていないと思います。 総括すると、これはあくまでコンパイラの挙動の問題である様な気がします。 [ メッセージ編集済み 編集者: おばけ 編集日時 2004-09-21 16:10 ] | ||||||||||||||||
|
投稿日時: 2004-09-21 16:50
と、私も思っていたのですが、念のため調べてみるとそうではないようです。 「Java言語仕様第2版」の§13.4.8「finalフィールドと定数」によると、
とあります。つまり定数のインライン化は、コンパイラによる任意の最適化ではなく、言語仕様によって規定された動作のようです。 言語仕様には、「final定数は"本当に変わらない値"にだけ使うのが良い」なんてことも書いてあります。円周率とか光速とかですかね。 |