- PR -

jsp の におけるscopeについて

1
投稿者投稿内容
(株)ぽち
ぬし
会議室デビュー日: 2002/09/10
投稿数: 376
投稿日時: 2002-09-27 14:44
こんにちわ。

お知恵をお借りしたく投稿します。


現在以下のようなフローのシステムを作成しています。

1:ログイン画面(HTML)

↓postで送信

2:ログイン機能部(Servlet)
  ここでgetSession(true)により新規session生成

↓Dispatch

3:各種画面(JSP)
  ここで<jsp:useBean id="id" class="class" scope="session">と宣言

↓postで送信

4:各種機能部(Servlet)
  ここでgetSession(false)により既存session取得、nullであればエラー

↓Dispatch

5:各種結果画面(JSP)
  ここで<jsp:useBean id="id" class="class" scope="session">と宣言


上記のような作りの場合、期待する動きとして、
・セッションがタイムアウトしない限りは正常に機能する。
・セッションがタイムアウトすれば、あとの処理はすべて
 セッション切れのエラー画面表示

しかし下記のようにした場合、困った事象が発生します。

・A機能使用画面(JSP)に遷移
・A機能を使用し、セッションタイムアウトまで待つ。
・再度A機能を使う。
・セッションエラー発生
・エラー発生後、再度A機能使用画面に遷移
・再度A機能を使用
・セッションエラーではなく、NullPointerException発生

調査したところ

<jsp:useBean>が原因ではないかと思えてきました。

どうやら「・エラー発生後、再度A機能使用画面に遷移」の箇所で
sessionを新たに作ってしまっているみたいです。

NullPointerExceptionはServletの中でbeanのメソッドを叩く時に
発生していることがわかりました。

jspがコンパイルされたjavaファイルからソースを見てみたのですが
session = pageContext.getSession();
というな感じでsessionを取得しているみたいなんですが

これはsessionがなければ作ってしまうのでしょうか?
APIドキュメントにはそのへんのことは一切書いてありませんでした。

request#getSession(boolean)みたいな引数もないので
困っています。

それとも<jsp:useBean>の中に何か指定すれば良いのでしょうか?

よろしくお願いします。


ひろ
常連さん
会議室デビュー日: 2001/12/13
投稿数: 36
投稿日時: 2002-09-27 15:22
<%@ page session="false"%>

になってますか。

>session = pageContext.getSession();

もう一歩踏み込むとJspFactoryクラスのgetPageContext()メソッドによってpageContextが生成されています。
このメソッドにpageディレクティブのセッション属性の値が渡されているようです。
(株)ぽち
ぬし
会議室デビュー日: 2002/09/10
投稿数: 376
投稿日時: 2002-09-27 16:11
>ひろ様

回答ありがとうございます。

なるほど、僕の知識が薄かったようです。


そこで<%@ page session="false" %>について調べてみました。下記参考
http://www.atmarkit.co.jp/fjava/javafaq/jsp/jsp06.html

それでは機能を使用するJSP内でログイン時に生成したセッションの中身を
見てしまっている場合はどうすればいいのでしょうか?

例えば下記のような場合

1:ログイン
  session生成

2:登録画面(JSP)
  ここでログイン時に得たユーザ名を表示したい。

3:登録処理(Servlet)
  session存在チェック

4:登録結果画面(JSP)
  登録結果を表示


上記のような場合、1でsessionが新規で作られ、その後2,4
のいずれでもsessionを触っています。

<%@ page session="false"%>

を指定した場合、jsp内でsessionを触る処理があった場合に
コンパイルエラーになります。

よって2,4のjsp内では

<%@ page session="true"%>

という記述、もしくは省略する形が適当だと思ってるんですが
認識は合っているでしょうか?


そしてこの場合も、セッションタイムアウトでエラーになった後に
再度2から処理しようとするとsessionが新たに作られるため、
投稿した内容と同じ事象が発生すると思います。



僕の希望としてはServlet内における
request#getSession(boolean)みたいに
sessionがあればそれを使い、なければnull返す。ってのを
jspの中でもやってくれないのかなと・・。
ひろ
常連さん
会議室デビュー日: 2001/12/13
投稿数: 36
投稿日時: 2002-09-27 16:30
引用:

jspがコンパイルされたjavaファイルからソースを見てみたのですが
session = pageContext.getSession();
というな感じでsessionを取得しているみたいなんですが

これはsessionがなければ作ってしまうのでしょうか?
APIドキュメントにはそのへんのことは一切書いてありませんでした



すみません、この部分にのみ反応して書いてしまいました。問題の解決になっていませんでしたね。

正常にログインして作られたセッションにはユーザID等の認証済みの情報を
持っているのですよね。
それでしたら、セッションからその値を取得してみてそれがNullであれば
エラーとする。もしくはログインページにforwardするのはどうでしょうか。
(株)ぽち
ぬし
会議室デビュー日: 2002/09/10
投稿数: 376
投稿日時: 2002-09-27 16:54
>ひろ様

>正常にログインして作られたセッションにはユーザID等の認証済みの情報を
>持っているのですよね。
>それでしたら、セッションからその値を取得してみてそれがNullであれば
>エラーとする。もしくはログインページにforwardするのはどうでしょうか。


確かにそうですね。

そのユーザIDはBeanの内部パラメータであり、Beanはsessionに格納されている。

ルートによってはsessionが切れた後、sessionが切れたまま、新しく生成されている
、また内部のbeanまでもが生成されちゃってる時があるってのがServlet側で意識する
ことができないので、チェックとしては

if( session == null ) {
第一のセッショエラーチェック
}

bean = (bean)session.getAttribute("bean);

if( bean == null ) {
第二のセッションエラーチェック
}

if( bean.getPara() == null ) {
第三のセッションエラーチェック
}

3重にしなきゃいけないのかな・・。つら・・。


ちなみにjspの中で

<jssp:useBean id="id" class="class" scope="session"/>

と記述しているのですが

こうすると、session内のbeanまでが新規作成されるんですが
この記述をしないで

jsp内で
<%
Bean bean = (Bean)session.getAttribute("bean");
%>

という風にすればbeanの新規作成は僕にゆだねらるのでしょうかね?

そうすればsessionがタイムアウト後新規作成された場合、beanは
勝手に新規作成されないでnullが返ってくるのでbeanがnullかそうでないか
によってチェックできる気がするんですが。


ひろ
常連さん
会議室デビュー日: 2001/12/13
投稿数: 36
投稿日時: 2002-09-27 19:01
まず、セッションタイムアウト後にサーブレットを実行してエラーになった場合は、セッションを使用しているJSPページではなくてセッションを使用しないページに送ってあげてはどうでしょうか。

ブラウザのキャッシュを利用されたくないページには下記のタグも多少役に立つと思います。
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-Control" content="no-cache">
<meta http-equiv="Expires" content="0">

それでもキャッシュコントロールは完璧ではないので、JSP直接起動などのためにもロジック必要ですね。


引用:

jsp内で
<%
Bean bean = (Bean)session.getAttribute("bean");
%>

という風にすればbeanの新規作成は僕にゆだねらるのでしょうかね?




そうですが、<jsp:useBean>の記述より前ではまだ生成されていないはずです。

コード:
<%
  if (session.getAttribute("bean") == null) {
    session.inValidate();
    response.sendRedirect("XXXXXXXX");
  }
%>


ページの最初でこういったコードで判定してやってはどうでしょうか。
できれば別ファイルにしておいて、
<%@ include file="XXXXXXXXXX" %>
としてやるとすっきりすると思います。

(株)ぽち
ぬし
会議室デビュー日: 2002/09/10
投稿数: 376
投稿日時: 2002-09-30 09:53
>ひろ様

何度も回答ありがとうございます。


結局うまく行けるようになった感じがします。

あまりコードを変更するのもイヤだったので
僕が取った手段は以下のような感じです。


・sessionを使用しないJSPファイル内では
 すべて<%@ page session="false" %>を記述

・ログイン後sessionを生成するServlet内で
 session、およびBeanを生成する処理に加えて
 session.setAttribute("hoge", hoge)という
 感じで判定用のチェックオブジェクトを格納。
 (チェックオブジェクトは適当なStringです)

・sessionを使用するJSPおよびServlet内の頭で
 以下のチェックロジックを記述
 //セッションエラーチェック
 if( session == null ) {
  //エラー処理
  return;
 } else if( session.getAttribute( "hoge" ) == null ) {
  //エラー処理
  session.invalidate();
  return;
 }


こんな感じで、sessionがなければエラーとし、また不本意に作られて
いたとしても(Beanまでもが作られていても)チェックフラグ用のオブジェクト
がなければエラーとしました。

今のところ特に問題は出ていないのですが・・。

色々な助言ありがとうございました。
1

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