質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.48%

  • Tomcat

    570questions

  • Java EE

    376questions

    Java EE(Java Enterprise Edition)はJavaベースのテクノロジーとその相互運用の仕様をまとめたものです。サーバとクライアントのアーキテクチャを規定し、特定アプリケーションのクラス用に定義されたテクノロジー設定のプロファイルを使用します。

(Java)セッション取得ができない HttpSession

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 3,442

kyasubaru

score 15

いつもお世話になっております。
今回も皆様のお力を借りたくご質問させて頂きます。

以下動作環境
Java
エクリプス4.5Mars
動的WEBプロジェクト

WEBアプリを構築中ですが問題が不明な為投稿させて頂きます。
以下ソース

package util;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import model.SQL_RS_form;

public class QueryExcute {

    HttpServletRequest request;

    public void queryEX(ResultSet rs) {

        SQL_RS_form rsform = new SQL_RS_form();
        List<Object> list = new ArrayList<Object>();

        try {
            while (rs.next()) {
                rsform.setUser_mail(rs.getString("user_mail"));
                list.add(rsform.getUser_mail());
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        /* 問題発生個所 */
        HttpSession session = request.getSession();
        session.setAttribute("user_mail", list);
    }
}

/*MYSQL接続*/
package util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class JdbcDriver {

    final static String DRIVER = "com.mysql.jdbc.Driver";
final static String URL = "-------";
    final static String NAME = "-----";
    final static String PASS = "------";

    Connection con = null;
    public void Conect(String sql) throws SQLException {

        try {
            Class.forName(DRIVER).newInstance();
        } catch (InstantiationException e) {

            e.printStackTrace();
        } catch (IllegalAccessException e) {

            e.printStackTrace();
        } catch (ClassNotFoundException e) {

            e.printStackTrace();
        }

            con = DriverManager.getConnection(URL, NAME, PASS);
            Statement smt = con.createStatement();
            ResultSet rs = smt.executeQuery(sql);

            QueryExcute qe = new QueryExcute();
            qe.queryEX(rs);

            con.close();
    }

}

/* メールアドレスを全件検索 */
package dao;

import java.io.IOException;
import java.sql.SQLException;
import util.JdbcDriver;
import util.QueryLoader;

public class R001 {
    public void select() throws IOException, SQLException {

        String sql = QueryLoader.getQuery("R001", "SQL01");
        JdbcDriver jdbc = new JdbcDriver();
        jdbc.Conect(sql);

    }
}
package validate;

import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.Properties;
import javax.servlet.ServletRequest;
import common.MessageStream;
import dao.R001;

/*メールアドレス重複チェッククラス*/
public class S002 {
    ServletRequest session;
    public String validate(String mail) {

        MessageStream me = new MessageStream();
        Properties inMessage = null;
        try {
            inMessage = me.loadUtf8Properties("/Message.properties");
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            R001 r001 = new R001();
            r001.select();

@SuppressWarnings("unchecked")
            List<String> list = (List<String>) session.getAttribute("user_mail");

            for (String str : list) {
                if (mail.equals(str)) {
                    return inMessage.getProperty("M01");
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return "";
    }
}

デバッグにて動作確認をしていた所、上記指摘個所「HttpSession session = request.getSession();」にて問題がエラーが発生しています。それまでの動作には問題は御座いません。
以下エラー文
java.lang.NullPointerException
    util.QueryExcute.queryEX(QueryExcute.java:36)
    util.JdbcDriver.Query(JdbcDriver.java:42)
    dao.R001.select(R001.java:19)
    validate.S002.validate(S002.java:32)
    servlet.MMPC002.doPost(MMPC002.java:46)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:650)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

問題が発生しなければ、ここでDBから取得してきた値がlistへ格納されているので、それをセッションへ保持して他ロジックで取得可能にさせるといった流れで考えています。
みなさまのお力添えの程宜しくお願い致します。

追記
一連の処理(下から進行)を掲載いたしました。S002クラスがサーブレットから呼ばれます。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+1

requestのインスタンスを生成していないからですね。

request = //インスタンス生成文。

requestに何も代入していないので、requestは初期値であるnullのままです。

※参照型の変数では起こりうるnull pointer exceptionについて、まず理解された方がいいと思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/23 01:05

    ご回答ありがとうございます。
    御指摘頂いたとおり、クラス名下のフィールド宣言箇所で

    HttpServletRequest request = null;

    と修正しましたが解決出来ませんでした。
    また問題発生箇所の上でローカル変数として
    request = null;
    とも修正しましたが、解決しませんでした。

    キャンセル

  • 2016/03/23 01:22 編集

    nullではだめということです。
    nullは何も参照していないことを表してます。
    何も参照していないので、getSession()メソッドを呼び出すことができません。

    HttpServletRequest型のインスタンスを生成して、代入してください。

    他にHttpServletの実装などはありませんか?

    キャンセル

  • 2016/03/26 00:09 編集

    ご返信遅れまして申し訳ございません。
    はい実装は当クラスのみです。少々低いレベルのご質問かもしれませんが、

    「他にHttpServletの実装などはありませんか? 」

    とご指摘頂きました個所が解釈できかねております。
    他クラスで実装しているとするとどういった使い方があるのでしょうか?
    またHttpServletRequest request = new HttpServletRequest();としたところインスタンスを作成できませんと表示されましたがなぜなのでしょうか?
    お手すきの際にでもご回答お待ちしております。

    補足追加致しました。

    キャンセル

  • 2016/03/26 01:23

    HttpServletRequestは、クラスではなくインタフェースなので、インスタンスを生成できません。

    今の状態はどんな感じかというと、
    あなたはタクシーというサービスを受けようと思っている人とします。

    タクシーというサービスを受けるためには、「車」と「運転手」と「あなた」が必要です。

    今のあなたのソースコードは「車や車のハンドル、ブレーキ、アクセル(DBとDBへのアクセスの実装)」を作りこんでいるだけで、肝心の運転手(HttpServlet)が存在していません。

    あなたはブラウザなどを介して、運転手に「サービスを受けたい」とリクエスト(HttpServletRequest)をしようとしているわけですが、運転手が居ないタクシーにいくら語りかけても、タクシーはウンともスンとも言いません(;・∀・)

    したがって、HttpServletクラスを継承して、あなたのリクエストに答えてくれる運転手を作ってください。そうすれば、運転手はあなたが望むサービスをしてくれることでしょう。

    下記など参考になりませんか?
    http://www.wakhok.ac.jp/~tomoharu/web2004/text/index_c10.html

    キャンセル

  • 2016/03/27 19:09

    ご回答有難うございます。
    HttpServletRequestがインターフェースという認識がありませんでした。お恥ずかしい話です。ご親切に比喩表現ありがとうございます。

    キャンセル

checkベストアンサー

0

事象の原因としては「Odacchi」さまの回答の通りです。

質問のソースを確認したところ、サーブレットから呼び出すUtilクラスではないでしょうか?
それであれば、以下のように処理を変更することで改善できませんか?

  • QueryExcute#queryEX()メソッドの戻り値をvoidからList<Object>に変更
  • QueryExcute#queryEX()メソッドでは、listを返却
  • 呼び出し側サーブレットでQueryExcute#queryEX()メソッドの戻り値をsessionへセット

また、できればQueryExcute#queryEX()メソッド内のlistの型(List<Object>)はObjectではなく、型を指定したほうがよろしいかと思います。(String等)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/26 00:34

    ご回答ありがとうございます。ご質問させて頂いてよろしいでしょうか?
    ご指摘頂きました
    「質問のソースを確認したところ、サーブレットから呼び出すUtilクラスではないでしょうか?」
    上記の個所が解釈しかねております。

    また厚かましいご依頼で申し訳ございませんが、上記の追記ソースを踏まえたうえで、こうしたほうがいいなどご指導頂ければ幸いです。
    ぜひ宜しくお願い致します。

    キャンセル

  • 2016/03/26 12:51 編集

    > 上記の個所が解釈しかねております。

    下記をもとに勝手に判断しました。

    * パッケージ名が「util」であったこと
    * 機能がDBアクセスするクラスであったこと
    * HttpServletを継承していないこと


    追加で提示いただいたソースを拝読しました。
    手厳しいかもしれませんが、Servletに関する基礎的な部分の理解が足りてないと感じました。

    まず下記のような書籍を参考に、写経のようにサンプルソースの写しと動作検証を行い、少しずつ機能追加(カスタマイズ)してServletへの理解を深めるのが解決への近道では?と思います。

    * http://www.amazon.co.jp/10%E6%97%A5%E3%81%A7%E3%81%8A%E3%81%BC%E3%81%88%E3%82%8BJSP-%E3%82%B5%E3%83%BC%E3%83%96%E3%83%AC%E3%83%83%E3%83%88%E5%85%A5%E9%96%80%E6%95%99%E5%AE%A4-%E7%AC%AC4%E7%89%88-%E5%B1%B1%E7%94%B0-%E7%A5%A5%E5%AF%9B/dp/4798140341
    (Eclipseでの開発例ではないが、JSP, Servletの役割や仕組みの説明あり。立ち読みもよいかと思います)

    ---

    > また厚かましいご依頼で申し訳ございませんが、上記の追記ソースを踏まえたうえで、こうしたほうがいいなどご指導頂ければ幸いです。

    手厳しいことだけだと失礼だと思いますので、ソースに対する修正提案です。
    難しいことを言っているかもしれませんが、考え方として参考としてください。

    * 各クラスは機能が分かるようなクラス名にする
    * Exceptionが発生した際、後続の処理に影響する場合は適切なエラー処理を行う
    * ResultSetやConnectionは、エラー発生時にも必ずcloseされるよう実装する
    * Sessionを扱うのはServletだけにする
    * R001, JdbcDriver, QueryExcuteは1クラスにメソッドとして定義する
    - クラス:Users
    - public List<String> getMailAddresses()
    - 内部でR001, JdbcDriver, QueryExecuteと同様の処理を実装
    - 戻り値はDB検索で取得したメールアドレスのリスト

    ---

    書籍は安いものではないですが、Webでの参考情報に比べると知識体系がきちんと構成されており、理解しやすい構造になっているものが多いと個人的には感じています。
    「理解のしやすさ」には個人差があるので共有できる感覚ではないですが、立ち読みで試し読みし、自分の理解にあった説明がある書籍を手元に1冊準備しておくとよろしいかと思います。

    キャンセル

  • 2016/03/27 19:16

    ご親切にご回答ありがとうございます。
    セッション取得に関しましてはサーブレットで行う事により解決できました。本当にありがとうございます。
    作成ソースに対しての修正案有難うございます。まだ考え付いたことのみコーディングしているだけなので、ご指摘頂きましたことを拝見させて頂きますと技術力の低さを痛感しております。
    ますはご指摘頂いた点の修正を試みてみたいと考えています。
    また今後こちらのサイトで不明点などをご質問させていただくかと思いますので、お見掛けになりましたら、手厳しい事でも指摘頂けたらと幸いでございます。

    キャンセル

  • 2016/03/27 19:38

    解決に至ったようでよかったです。
    自分も過去には同じようにサーブレットの機能や役割への理解に苦労しました。
    クラスごとの「役割」を意識して設計、実装していくと良いかと思います。
    引き続きがんばってください。

    キャンセル

  • 2016/03/27 20:01

    takyafumin様
    ベストアンサー選定後ということで、マナー違反と存じ上げますが、宜しければ最後に2点ほどご質問宜しいでしょうか?

    ・1点目
    ご指摘頂きました1クラスにまとめるといった作業ですが、このご指摘意図としては個々の処理機能として1クラスにまとめた方が処理の流れがわかりやすくなる為。といった所でしょうか?
    当方のコーディング意図としては、知識不足ながらカプセル化としてバグ発生時のメンテナンスやソースの再利用化という観点でクラスを分けて作成をしておりました。

    ・2点目
    こちらは現在新規で迷っている問題です。
    チェッククラスにてエラーを検知後、そのエラーメッセージを元の入力したJSP画面へ表示させたいのです。サーブレットでの処理はできていますが、JSP画面の処理ロジックの想像がつきません。
    試しにエラー表示をしてみようとしたところ、その処理(エラーメッセージをセッションから取得)が初めから読み込まれてしまうので、正常に動きません。
    どのようにして元のJSP画面へ戻したら宜しいでしょうか?
    宜しくお願い致します。

    キャンセル

  • 2016/03/27 20:59

    今、時間がありますので問題ないです。

    >・1点目
    ご指摘頂きました1クラスにまとめるといった作業ですが、このご指摘意図としては個々の処理機能として1クラスにまとめた方が処理の流れがわかりやすくなる為。といった所でしょうか?

    「該当テーブルへのDB処理を担当するクラス」として1つにまとめ、機能ごとにメソッド(select, insert, update, delete, find等)を準備する方式を考えました。

    実際にシステムを構築する際にはもう少し踏み込んで、DB接続処理やクエリの実行部分は他のテーブルへのDB処理を担当するクラスと共通化する必要があるので、親クラスを作成してメソッドとして共有化する、なども考えられます。

    カプセル化・・・クラス内メンバへの外部からの直接アクセスを防ぎ、外部からの操作状態によってメソッドが意図しない動作をしないように設計することと理解しています。
    適切な識別子(public, protected, private)を付与することで実現します。

    ソースの再利用化・・・クラス化する以外にも親クラスとして再利用することも可能です。今回のケースでは、クラスを分けてもクラス間の依存性が強いのと、DB接続やクエリ実行はセットで利用するため、まとめたほうがシンプルだと思いました。
    ※まとめても、処理はメソッド単位で分けます。
    ただし、クラス設計としてはどちらも「アリ」かもしれません。いろいろ試して、後からどちらがよかったかを考えるのが経験としてよろしいかと思います。
    Javaのフレームワーク自体のソースを読むと、もっとすごいことをしています。(DI, コネクションぷーリングなど)少し難しいですが、徐々にフレームワークへ触れる機会を増やすと知識が増え、勉強になります。


    ---

    >・2点目
    こちらは現在新規で迷っている問題です。
    チェッククラスにてエラーを検知後、そのエラーメッセージを元の入力したJSP画面へ表示させたいのです。サーブレットでの処理はできていますが、JSP画面の処理ロジックの想像がつきません。

    よくある実装としては、以下のように実装するかと思います。

    1. サーブレットでエラーメッセージをセッションにセット
    2. JSP側でエラーメッセージがある場合のみエラーメッセージのHTML部分を表示させる

    エラーメッセージが複数ある場合は、エラーメッセージのリスト(List<String>)をセッションにセットし、JSP側でNullかlist.size()==0を判定するとよいかと。
    もう少し踏み込んでの説明となると、コメント欄だけでは厳しいので、ソース部分も記載して新たに質問されると良いかと思います。

    キャンセル

  • 2016/03/29 00:14

    お返事遅れまして申し訳ございません。
    1点目、2点目お目通しさせて頂きました。非常に参考になります。長文でのご説明本当に有難うございます。
    またお見掛け致しましたら、ご指導頂けますと幸いです。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.48%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Tomcat

    570questions

  • Java EE

    376questions

    Java EE(Java Enterprise Edition)はJavaベースのテクノロジーとその相互運用の仕様をまとめたものです。サーバとクライアントのアーキテクチャを規定し、特定アプリケーションのクラス用に定義されたテクノロジー設定のプロファイルを使用します。