- PR -

JSPで別クラスのpublic static finalフィールドを使用した場合のデプロイ作業について

投稿者投稿内容
torakiyojp
常連さん
会議室デビュー日: 2004/08/04
投稿数: 23
投稿日時: 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フィールドのみの宣言を行っているクラスの意図としては、ここで宣言したフィールドを他のクラスで使うことで、ここのフィールドさえ修正するば他を修正しなくてよいようにするという考えもあります。)

以上、よろしくお願いします。
がちゃぴん
会議室デビュー日: 2002/02/06
投稿数: 19
お住まい・勤務地: 東京都・いろいろ
投稿日時: 2004-09-21 14:55
こんにちは、がちゃぴんです。

引用:

torakiyojpさんの書き込み (2004-09-21 14:08) より:
環境:WebSphere Application Server V5.0でJSPのプリコンパイルをしないに設定。

発生した問題:別クラスのpublic static finalフィールドの値を修正、JSPでこのフィールドを使用しているかつJSPに修正を加えていない場合、JSPがリコンパイルされず、修正が反映されない。



プリコンパイルしないで定数クラスの定数値のみの変更の場合、
キャッシュ、又はJSPのCLASSファイルを削除してはどうでしょう?
初回のアクセス時に少々時間がかかりますが・・・。
または、WASの場合、JSPのCLASSファイルを直接上書きすることも
可能だったと思いますが、これは裏技的というか正攻法ではないと思いますので・・・。


引用:

1.一般的にデプロイするときは画面を全て開いてJSPを全コンパイルするか、又はプリコンパイル機能を使用してJSPを全コンパイルするのどちらかなのでしょうか?

2.public static finalフィールドのみの宣言を行っているクラスのフィールドをJSPで使用するのに問題があるのでしょうか?

3.public static finalフィールドのみの宣言を行っているクラス自体存在してはいけないのでしょうか?

4.一度定義したpublic static finalフィールドに修正を加えること自体が間違っているのでしょうか?(ただ、このpublic static finalフィールドのみの宣言を行っているクラスの意図としては、ここで宣言したフィールドを他のクラスで使うことで、ここのフィールドさえ修正するば他を修正しなくてよいようにするという考えもあります。)

以上、よろしくお願いします。



1.
 →プリコンパイル機能を使用してJSPを全コンパイルするかなー

2と3 
 →1でプリコンパイル機能を使用していれば、問題ないのでは?


 →固定値定義クラスの値は、変わらないに越したことはないでしょうが、
  固定値の内容によると思います。
  システムの設定値等、変更の可能性のある値の定義は、外部に定義した内容(DBやプロパティファイル等)を
  読み込むようにすればよいでしょう。DBの項目値の取りうる値のような
  コード定義的なものも、そのようにしても問題ないでしょうし。
  それ以外のプログラム的な定数値は、固定値定義クラスにあってもよいと思いますが、
  あとは極力、変更しないようにするだけだと思います。
おばけ
ぬし
会議室デビュー日: 2002/11/14
投稿数: 609
お住まい・勤務地: 東京都江東区
投稿日時: 2004-09-21 14:56
疑問ですが、
引用:

現在開発を行っている環境では定数用のクラスを用意し、そこでpublic static finalフィールドのみの宣言を行っています。
(中略)
すると、JSPでCONST_TEST1を使用していても、JSP自体が変更されていないとリコンパイルされないので、修正が反映されません。


なぜ他クラスの定数を修正しただけなのに、JSPをリコンパイルする必要があるのでしょうか?
定数はCのマクロとは違い、インライン展開されるものではありません。
あくまでJSPとは別の領域に定数として値が保持されるのですから、JSPがリコンパイル
される必要は無いのではないでしょうか?

# 勘違いでしたらすみません。
ぽん
大ベテラン
会議室デビュー日: 2003/05/13
投稿数: 157
投稿日時: 2004-09-21 15:14
引用:

おばけさんの書き込み (2004-09-21 14:56) より:

疑問ですが、
なぜ他クラスの定数を修正しただけなのに、JSPをリコンパイルする必要があるのでしょうか?
定数はCのマクロとは違い、インライン展開されるものではありません。
あくまでJSPとは別の領域に定数として値が保持されるのですから、JSPがリコンパイル
される必要は無いのではないでしょうか?


[public static final]な変数はインライン展開される事があるそうです。
(プリミティブ型とStringが対象になったような・・・)

解決方法としては
コード:

private static final String AAA = "aaa";

public static String getAaa() {
return AAA;
}


の様にすると良いです。
(インライン展開されないので)

[参考]
「Effective Java」のSafeEnumパターンを調べて見ると良いと思います

[ メッセージ編集済み 編集者: ぽん 編集日時 2004-09-21 15:17 ]
じゃばら
会議室デビュー日: 2004/05/24
投稿数: 10
お住まい・勤務地: 福岡
投稿日時: 2004-09-21 15:25
こんにちは、じゃばらです。

引用:

おばけさんの書き込み (2004-09-21 14:56) より:
定数はCのマクロとは違い、インライン展開されるものではありません。



public static final なフィールドの値がリテラルで宣言されている場合、
それを参照しているクラスをコンパイルすると
class ファイルにリテラル値が埋め込まれてしまいます。

値をリテラルで宣言できるのは int や double などの各種プリミティブ型と
文字列(String クラスのオブジェクト)ですね。

おそらくパフォーマンス上の理由でこうなっているのでしょうが、
かなりいやな仕様ですよね。
せっかくクラス単位で開発できるのに、public static final 定数の値を変えたら参照しているクラス全ての
リコンパイルが必要になるとは・・・

# コンパイラにも依るのかもしれませんが。
# 私がこの現象を確認したのは Sun の JDK の javac です。
じゃばら
会議室デビュー日: 2004/05/24
投稿数: 10
お住まい・勤務地: 福岡
投稿日時: 2004-09-21 15:27
かぶってしまいました。
すみません。
おばけ
ぬし
会議室デビュー日: 2002/11/14
投稿数: 609
お住まい・勤務地: 東京都江東区
投稿日時: 2004-09-21 15:56
じゃばらさん、ぽんさん、ありがとうございます。
私のコメントはどうも教科書的な発言でしたね
コンパイラによってはインライン展開することがあるとは、知りませんでした。

そうなると、この場合はコンパイル済みのJSPファイルを破棄すれば良いわけですね。
正式にやって良いことかどうかは分からないですが、WebLogicの場合はコンパイル済みの
JSPのクラスファイルを直接削除すると、このような問題はうまく行った経験があります。
WebSphereでも同じようなことができるのではないでしょうか?

そこで、最初の投稿の質問にお答えすると、
引用:

1.一般的にデプロイするときは画面を全て開いてJSPを全コンパイル
するか、又はプリコンパイル機能を使用してJSPを全コンパイルする
のどちらかなのでしょうか?


本番環境にデプロイする場合は、アプリケーションサーバのJSPプリコンパイル機能を
使って全JSPをコンパイルしてしまうことが多いかと思います。

追記# WebLogicではappcというプリコンパイラをEARファイルに対して実行すると、
追記# 内部のJSPをプリコンパイルしてくれちゃいます。

引用:

2.public static finalフィールドのみの宣言を行っているクラスの
フィールドをJSPで使用するのに問題があるのでしょうか?


今回の問題はたまたまコンパイラの挙動のせいであって、私は問題は無いのでは
ないかと思います。ただ、このような定数を使うにはScriptletを記述しないと
いけなくなると思いますので、Taglibを使うなり、JSPを呼び出すServletで定数を
Request Scopeに入れるなりして、Scriptletの使用は回避しても良いかも、とは
思います。

追記# あ、でも、こうやっちゃうと定数の参照をコンパイル時にチェック出来なく
追記# なりますね・・・。どっちが良いんだろ。

引用:

3.public static finalフィールドのみの宣言を行っているクラス
自体存在してはいけないのでしょうか?


そんなことはないと思いますよ。

引用:

4.一度定義したpublic static finalフィールドに修正を加える
こと自体が間違っているのでしょうか?


間違っていないと思います。

総括すると、これはあくまでコンパイラの挙動の問題である様な気がします。


[ メッセージ編集済み 編集者: おばけ 編集日時 2004-09-21 16:10 ]
佐々木
大ベテラン
会議室デビュー日: 2003/03/30
投稿数: 121
投稿日時: 2004-09-21 16:50
引用:

総括すると、これはあくまでコンパイラの挙動の問題である様な気がします。



と、私も思っていたのですが、念のため調べてみるとそうではないようです。
「Java言語仕様第2版」の§13.4.8「finalフィールドと定数」によると、

引用:

フィールドがコンパイル時の定数である場合、finalキーワードの削除、あるいはその値を変更することによって既存バイナリの互換性が損なわれ、実行できなくなるようなことはないが、再コンパイルを行わない限りその定数の新たな値を取得することはできない。

…中略…

この結果は、§14.20の最後で考察している条件コンパイルのサポートを行うための決定から発生した副作用である


とあります。つまり定数のインライン化は、コンパイラによる任意の最適化ではなく、言語仕様によって規定された動作のようです。

言語仕様には、「final定数は"本当に変わらない値"にだけ使うのが良い」なんてことも書いてあります。円周率とか光速とかですかね。

スキルアップ/キャリアアップ(JOB@IT)