- PR -

servlet内のオブジェクト変更

1
投稿者投稿内容
team_ura
会議室デビュー日: 2005/01/20
投稿数: 4
投稿日時: 2005-01-20 21:57
初めての書込みになります。
team_uraと申します。よろしくお願いします。

環境 :WindowsNT Server
JDK :jdk1.3.1
tomcat:4.1

現在servlet-JSPにてWebアプリケーションを作成しています。
そこで、サーバマシンでバッチがキックされた際にservlet共通領域applicationに
setAttributeでセットしたものを変更したいのですが、良い方法が浮かびません。
※ちなみに、セットしたいものはSerializableをimplementsできません。

servlet開始時に、threadを開始させ指定したフォルダにファイルが作成されたら
threadからgetServletContext()でセットしようとしましたが、ダメでした。
何かほかに良い方法がありますでしょうか?
知恵を貸してください。お願いします。

※参考までにソースを載せます。

// 初期化処理
public void init(ServletConfig config) throws ServletException {

super.init(config);
System.out.println("初期化処理です。");

getServletContext().setAttribute("Ver1","初期です!");

ControlThread bs = new ControlThread();
Thread b = new Thread(bs);
b.start();

}

public class ControlThread extends HttpServlet implements Runnable,Serializable {

/* (非 Javadoc)
* @see java.lang.Runnable#run()
*/
public void run() {
// TODO 自動生成されたメソッド・スタブ
File bf = new File("d:\\home\\break.txt");
File sf = new File("d:\\home\\start.txt");

while (true) {
System.out.println("状態監視中・・・");
if (bf.exists()) {
System.out.println("終了存在確認!");
getServletContext().setAttribute("Ver1","停止!");
}
if (sf.exists()) {
System.out.println("開始存在確認!");
getServletContext().setAttribute("Ver1","開始!");
}


try {
Thread.sleep(6000);
} catch (InterruptedException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
}
}


}
pascal
常連さん
会議室デビュー日: 2004/04/29
投稿数: 29
お住まい・勤務地: 神奈川県
投稿日時: 2005-01-20 22:26
こんにちは。

#Runnableなサーブレットを初めて見たので、少し面食らってしまいました。。

それはさておき。

ControlThread#runで取得しているServletContextは、その上のinitが書かれているServletContextとは別物では無いでしょうか。
いくら設定しても駄目な気がしますが。

思いつきで書いたのですが、こんなのはどうですか?

コード:

public void init(ServletConfig config) throws ServletException {

super.init(config);
System.out.println("初期化処理です。");

getServletContext().setAttribute("Ver1","初期です!");

ControlThread bs = new ControlThread(getServletContext());
Thread b = new Thread(bs);
b.start();

}

public class ControlThread implements Runnable,Serializable {


private ServletContext _context;
public ControlThread(ServletContext aContext) {
_context = aContext;
}


public void run() {
File bf = new File("d:\\home\\break.txt");
File sf = new File("d:\\home\\start.txt");

while (true) {
System.out.println("状態監視中・・・");
if (bf.exists()) {
System.out.println("終了存在確認!");
_context.setAttribute("Ver1","停止!");
}
if (sf.exists()) {
System.out.println("開始存在確認!");
_context.setAttribute("Ver1","開始!");
}


try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}


}





[ メッセージ編集済み 編集者: pascal 編集日時 2005-01-20 22:28 ]

[ メッセージ編集済み 編集者: pascal 編集日時 2005-01-20 22:34 ]
team_ura
会議室デビュー日: 2005/01/20
投稿数: 4
投稿日時: 2005-01-21 11:37
pascal様
返答ありがとうございました。

早速頂いたコードで試したところ、予期した通りの動きをしました。
非常に助かりました。
※ThreadクラスにServletContextを参照渡しをするわけですね。

ここで作成されたスレッドは、servletのdestroyメソッド内で
終了を定義する必要があるのでしょうか?

pascal
常連さん
会議室デビュー日: 2004/04/29
投稿数: 29
お住まい・勤務地: 神奈川県
投稿日時: 2005-01-22 15:03
こんちには。

サーブレットのサービス終了時に停止する必要があるでしょうね。
もし、Threadをあまり使ったことが無いのでしたら、Threadの停止については、まず以下をご覧下さい。
http://java.sun.com/j2se/1.4/ja/docs/ja/api/java/lang/Thread.html
http://java.sun.com/j2se/1.4/ja/docs/ja/guide/misc/threadPrimitiveDeprecation.html

team_ura
会議室デビュー日: 2005/01/20
投稿数: 4
投稿日時: 2005-01-24 15:30
上の2サイトを読ませてもらい、
参考にしてdestroyメソッドにスレッドの終了処理を追加しました。

さらに質問なのですが、格納したServletContextを別セッションで取得する
場合には、getServletContext()でInit時に作成したオブジェクトを
取得できるのでしょうか?

※初期化処理側で呼ばれたgetServletContext()と、スレッド側で呼ばれた
getServletContext()では異なるServletContextが取得されるのであれば、
別セッションでgetServletContext()を読んだ場合にも、異なるServletContext
が取得されるのでは?

別セッションで同じServletContextを取得するにはどうすればよいのでしょうか?
pascal
常連さん
会議室デビュー日: 2004/04/29
投稿数: 29
お住まい・勤務地: 神奈川県
投稿日時: 2005-01-24 21:55
こんにちは。

意図を正確に伝えることが出来ずに申し訳ありませんでした。

改めて整理すると、最初の例のinit()メソッドが定義されているサーブレットを、AnotherServletと呼ぶことにします。
すると、最初の例は、以下のように書けます。

コード:

public class AnotherServlet extends HttpServlet {
public void init(ServletConfig config) throws ServletException {
super.init(config);
System.out.println("初期化処理です。");
getServletContext().setAttribute("Ver1","初期です!");
//以下省略
}
}
public class ControlThread
extends HttpServlet
implements Runnable,Serializable {
public void run() {
// TODO 自動生成されたメソッド・スタブ
File bf = new File("d:\\home\\break.txt");
File sf = new File("d:\\home\\start.txt");

while (true) {
System.out.println("状態監視中・・・");
if (bf.exists()) {
System.out.println("終了存在確認!");
getServletContext().setAttribute("Ver1","停止!");
}
if (sf.exists()) {
System.out.println("開始存在確認!");
getServletContext().setAttribute("Ver1","開始!");
}
//以下省略
}
}
}



AnothorServletとControlThreadは、別のサーブレットです。
(というか、ですよね?)
つまり、サーブレットコンテナからみれば、別のアプリケーションです。
それぞれでgetServletContextとしても、別のContextが取れるわけです。
(正確には言い方がちょっと違うのですが、ここでは敢えて書きません)
私が、「いくらやっても取れない」と書いたのは、そういう理由からです。

また、ServletContextは、アプリケーションに一つです。
同じサーブレットに関連づけられたリクエスト(言葉足らずで申し訳ありませんが、私にはこの言い方しか思いつきません)であれば、どこからも参照できます。
「別セッションから」の意味が不確か、というか、文脈に沿いませんが、心配しなくてもやりたいことは出来ると思います。

#実を言うと、Contextを使うのであれば、あるファイルを監視するのに、わざわざThreadを使う必要は無いと思います。


意図が通じたでしょうか。
色々書くとかえって誤解をまねきそうなので、この辺にしておきます。
以下もご覧下さい。
http://java.sun.com/j2ee/sdk_1.3/ja/techdocs/api/javax/servlet/ServletContext.html


[ メッセージ編集済み 編集者: pascal 編集日時 2005-01-24 22:00 ]
team_ura
会議室デビュー日: 2005/01/20
投稿数: 4
投稿日時: 2005-01-25 01:22
pascal様、返答ありがとうございます。

Servletの仕組みをもっと勉強する必要がありそうです。
※ページ数の少ない参考書には、そこら辺の説明が抜けているため
 学習を怠っていました。

ここらで意を決してServletの分厚い本を買ってじっくり読みたいとおもいます。
ありがとうございました。
1

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