はじめまして。
環境:
apache2.052 + jk2(2.04) + tomcat5.028
質問:
CSVファイルをアップロードして、DBに登録する業務があります。
CSVアップロード
↓
サーブレット:DB登録
↓
結果出力
DB登録の処理時間が20秒ほどかかるため、その間にブラウザを閉じたり、別のリンクをクリックされる場合があります(キャンセルの意を込めて?)。
そのような操作がされた場合、ユーザには登録の結果(エラーの有無等)を知る手段がないため、サーバ側のDB登録処理をキャンセル(ロールバック)させたいのですが、現状、ブラウザの状態にかかわらずDB登録処理は最後まで行われてしまいます。
なにかよい方法はございませんでしょうか。
また、一般的にはこのような処理は行わないものなのでしょうか。
よろしくお願いいたします。
No.4ベストアンサー
- 回答日時:
>処理メニューなど、フレーム分割されている場合を
>想定しておりました。
…orz
そうですね。(^^;A
まったく漏れてました。
申し訳ありませんでした。
前の現場ではフレームで共通に各ボタンに対するフラグを持ってて、レスポンスが返ってくるまでボタンが押されてもリクエストを飛ばさないように制御してましたね。
細かい部分でどうやって実現していたかは知りませんが…。
(ボタンがいっぱいあったのでフラグ設定ミスなどバグもそれなりにありましたが…他チームでよかったと思ってます。(笑))
No.3
- 回答日時:
>DB登録の処理時間が20秒ほどかかるため、その間にブラウザを閉じたり、
>別のリンクをクリックされる場合があります(キャンセルの意を込めて?)。
「閉じたり」はわかりますが、サーブレット1本でやった場合に、他のリンクをクリックできます?
あー、サーブレットでhtmlを直に吐いてれば、途中までは表示されるのかな…。わかんないけど…。
そうでなければ、ブラウザはずっと白い画面で「○○を開いてます。」って出ませんでしたっけ?
>キャンセルする場合、ユーザ(ブラウザ)の状態を判断するにはセションが切れるのを待つしかないため
セッションが切れるのはあくまでもセッションタイムアウトになった場合です。
セッションタイムアウトが起きたからといって、ブラウザが閉じられたとは限りません。ブラウザを開いたままでもセッションタイムアウトの設定値だけ放置しておけばセッションは切れます。
>セションが切れるとスレッドの状態がわからなくなる
確かにそのとおりですが、いちおうMETAタグで○秒おきにリクエストを飛ばすので大丈夫かなと。
ブラウザの「×」ボタンとかやられたら仕方ないですけど、そこはユーザーとの決め事で「やらないで下さい。」と言うしかないですね。
まぁそれでもやられた場合のことを考慮して、ログなど解析の元ネタはちゃんと出力しないといけませんね。
>今回のようなアップロード処理に限らず、サーブレット処理中にブラウザを閉じるとか、別のリンクをクリックするということは大いにありえますよね。
まぁそうなんですけど、でも、できることとできないことがあって、できることの中にも非常に面倒だったり、工数がかかることもあるので、そこは費用とかの兼ね合いでエンドユーザーさんには「やらないで下さい。」と決めないといけませんね。
(上でも述べましたが。)
それがダメということならクライアントにブラウザを使わないで、他のものを使うなり、クライアントも開発をするなりしないとだめですね。
あとはなるべく「×」ボタンを押したくならないように工夫することですかね。
例えば
--------------------------------------------------
登録スレッドクラス
・セッションからファイル名を取得
・登録結果「登録中:ファイル読み込み中」
・登録結果「登録中:ファイル読み込み完了」
・登録結果「登録中:DBに登録中」
・DBに登録
・登録結果「登録完了」
--------------------------------------------------
--------------------------------------------------
登録中画面
・METAタグを使って○秒おきにチェックするサーブレットに
要求を投げる
・登録中メッセージを表示
--------------------------------------------------
のようにして、
「動いてますよ!止まってませんよ!!」
ってことをアピールすれば「×」ボタンは押されにくくなるかもしれません。
>サーブレット処理はキャンセルされずに完走するのが通常ということなのでしょうか。
そうですね。
以上、長々と失礼しました。
ご回答ありがとうございす。
詳細に解説いただき、大変勉強になります。
>「閉じたり」はわかりますが、サーブレット1本でやった場合に、他のリンクをクリックできます?
処理メニューなど、フレーム分割されている場合を
想定しておりました。
>「動いてますよ!止まってませんよ!!」
>ってことをアピールすれば「×」ボタンは押されにくくなるかもしれません。
そうなんですよね。これは大事だと思います。
貴重な時間を割いていただき、ありがとうございました。
No.2
- 回答日時:
>ユーザには登録の結果(エラーの有無等)を知る手段がないため、サーバ側のDB登録処理をキャンセル(ロールバック)させたいのですが、
というのなら、キャンセルさせる方法ではなく、結果を知る手段を考えるべきでは?
そもそも、ブラウザの状態をWebサーバ側から知りたいという仕様が、Webシステムに向いていません。
キャンセルするにしろ、結果を取得するにしろ、サーブレットとは別にスレッドを起こして、そのスレッドを管理すればいいだけです。
しかし、キャンセルする場合、ユーザ(ブラウザ)の状態を判断するにはセションが切れるのを待つしかないため、DBにおいて長時間のロックが発生することになります。セションのタイムアウト時間を短くすれば別ですが、現実的ではありません。
私ならば、キャンセルする方法よりも、結果を取得できるような機構を実装することをお勧めします。
実装例については#1の方が書かれていますが、登録スレッドとセションを関連づけるのは良くありません(セションが切れるとスレッドの状態がわからなくなる)ので、もう少し考慮が必要です。
この回答への補足
pcbeginnerさん、Bonjinさんありがとうございます。
キャンセルするのは一般的ではないということなんですね。
私は、「ブラウザが閉じられた」ということは、サーブレットにとっては「出力先を失った」ということになって、(例えば以下のソースの)doGetメソッドのレスポンスを返すところでIOExceptionが発生して、それを契機にロールバック処理に移れるのでは?と考えていたのですが、どうやらブラウザを閉じてもIOExceptionは返らないようですね。
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html><body>Hello World!</body></html>");
out.close();
}
そこでさらに疑問なのですが、今回のようなアップロード処理に限らず、サーブレット処理中にブラウザを閉じるとか、別のリンクをクリックするということは大いにありえますよね。
その場合もやはりサーブレット処理はキャンセルされずに完走するのが通常ということなのでしょうか。
No.1
- 回答日時:
一般的かどうかは分かりませんが、
サーブレット
・受信したファイルをテンポラリディレクトリに保存
・セッションにファイル名などをセット
・セッションに登録結果を「登録中」でセット
・登録スレッドクラス.start()
・チェックするサーブレットにフォワード
登録スレッドクラス
・セッションからファイル名を取得
・DBに登録
・登録結果をセッションにセット
チェックするサーブレット
・セッションから登録結果を取得
・結果に応じて
登録中画面
正常終了画面
エラー画面
を表示
登録中画面
・METAタグを使って○秒おきにチェックするサーブレットに
要求を投げる
こんな感じでいかがでしょうか。
サーブレットの処理にキャンセルをかけるのは…
サーブレットも要求ごとに別スレッドになってるので…割り込み?掛ければできるのかもしれないけど、やったことありません…
Treadクラスにinterrupt()メソッドがありますね…。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- SQL Server DBのテーブルの設計ができず困っています。 2 2023/06/29 16:43
- 情報処理技術者・Microsoft認定資格 応用情報処理技術者試験のシステム利用率の計算について 2 2022/03/28 07:43
- PHP 重複を防ぐ記述について教えて下さい。 3 2023/04/03 14:35
- Excel(エクセル) Excel VBAについてです。 少しだけ知識はあるのですが、 うまくいかなかったので 質問させてい 3 2022/09/13 18:40
- IT・エンジニアリング ドメイン駆動設計の値オブジェクトについて質問 1 2023/05/13 02:50
- 弁護士・行政書士・司法書士・社会保険労務士 資格制度上の他資格の試験免除の撤廃について 4 2022/03/29 13:48
- MySQL SQLで日付別のIDを生成するには 3 2022/10/09 10:34
- その他(ニュース・時事問題) 「マイナポイント」の登録について 5 2022/12/12 22:36
- PHP PHP MySql 画像を取得 1 2022/06/04 14:05
- InternetExplorer(IE) PC Windows10 URL登録(お気に入り登録)が時々いつの間にかログインできない状態になる 1 2022/12/25 08:41
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VB.net(ASP.net)でアクセスカ...
-
セッションに格納する方法
-
リッチクライアントのセッション
-
setAttribute getAttribute 配...
-
グローバルIPアドレスの変更タ...
-
プログラミングで例えばゲーム...
-
腕時計の時報をならないように...
-
C言語で今まで表示していた画面...
-
画面を隠す・消す方法を教えて...
-
jspからjarを参照したいのですが
-
VBAでTIFF画像を読み込むには?
-
javaでクイズ(一問一答)作成...
-
VB.NET DataReaderが開かれている
-
URLはそのままで、リンクをクリ...
-
三菱GOTの画面切り替えについて
-
画面遷移を行わずに同一ページ...
-
このadidasの腕時計の時刻の設...
-
ボタンでパラメータを渡すには
-
3層クライアントサーバとMVCの関係
-
フォーム上で押されたボタンに...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
javascriptでセッションを取得
-
グローバルIPアドレスの変更タ...
-
javascriptでセッションの削除...
-
エラーページ遷移後に入力値を残す
-
JSPでsession変数が勝手に書き...
-
ASP Session変数名の取得
-
sessionスコープとapplication...
-
画面遷移でセッション切れにな...
-
ASP.NETのGlobal.asaxについて
-
セッションタイムアウト時にエ...
-
Tomcatでの同一セッション同時...
-
javascriptでのログアウトボタン
-
jsessionidの有効期限を延長す...
-
セッションタイムアウトの設定...
-
setAttribute getAttribute 配...
-
セッションIDの桁数
-
JSPでブラウザ終了時にPostgreS...
-
JSP + ラジオボタン
-
HttpSessionListenerクラスに関...
-
複数Webサーバーでのセッション...
おすすめ情報