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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

1回答

405閲覧

タイトル:Javaのフィールド変数について

pokemn

総合スコア16

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

1クリップ

投稿2019/02/23 17:49

編集2019/02/24 04:25

前提・実現したいこと

ここに質問の内容を詳しく書いてください。
いつもお世話になっております。
現在、Javaで開発を行っているのですが、下記問題が発生しています。
DbaccessクラスでUserinformationdtoクラスのフィールドに値を格納し、UserconfimationクラスでUserinformationdtoクラスの
フィールドをUserconfimationクラスの「System.out.println(this.userInfDto.getUser());」で確認しようとしたのですが、
そのタイミングで「nullpointerexception」が発生しました。
個人的には恐らくフィールドの初期化タイミングを理解していないことが原因だとは考えているのですが、調べてもいまいちピンと
来ませんでしたので今回質問させていただきました。
どなたかご存知の方がいましたらご教授お願い致します。
私自身Javaは現在勉強し始めたばかりなので今回の原因が初歩的なものだとしたら申し訳ありません。

発生している問題・エラーメッセージ

フィールド参照時にNullの為、「nullpointerexception」が発生

java.lang.NullPointerException at jp.co.controller.todo.Userconfirmation.doPost(Userconfirmation.java:39) at javax.servlet.http.HttpServlet.service(HttpServlet.java:650) at javax.servlet.http.HttpServlet.service(HttpServlet.java:731) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:110) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:962) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:445) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1115) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745)

該当のソースコード

Java

1package jp.co.controller.todo; 2 3import java.io.IOException; 4 5import javax.servlet.ServletException; 6import javax.servlet.http.HttpServlet; 7import javax.servlet.http.HttpServletRequest; 8import javax.servlet.http.HttpServletResponse; 9 10import org.apache.commons.lang3.StringUtils; 11 12import jp.co.model.todo.Dbaccess; 13import jp.co.model.todo.Userinformationdto; 14 15public class Userconfirmation extends HttpServlet{ 16 17 boolean bool; 18 Dbaccess dbaccess; 19 Userinformationdto userInfDto; 20 21 public void doPost(HttpServletRequest request, HttpServletResponse response) 22 throws IOException, ServletException{ 23 24 String user = null; 25 int psw = 0; 26 27 try { 28 user = request.getParameter("user"); 29 psw = Integer.parseInt(request.getParameter("psw")); 30 } catch (Exception e) { 31 32 } 33 34 dbaccess = new Dbaccess(); 35 36 bool = dbaccess.Confimation(user, psw); 37 try { 38 if (bool == true) { 39 System.out.println(this.userInfDto.getUser()); 40 System.out.println(this.userInfDto.getPsw()); 41 if (!StringUtils.isEmpty(this.userInfDto.getUser()) && this.userInfDto.getPsw() != 0) { 42 request.setAttribute("user", user); 43 request.setAttribute("psw", psw); 44 request.setAttribute("userinformationList", this.userInfDto.getUserInformationList()); 45 request.getRequestDispatcher("/Loginsuccess.jsp").forward(request, response); 46 } 47 } else { 48 request.getRequestDispatcher("/Login.jsp").forward(request, response); 49 } 50 } 51 catch (Exception e) { 52 e.printStackTrace(); 53 } 54 55 } 56 57}

該当のソースコード

Java

1package jp.co.model.todo; 2 3import java.sql.Connection; 4import java.sql.PreparedStatement; 5import java.sql.ResultSet; 6import java.sql.SQLException; 7import java.util.ArrayList; 8import java.util.List; 9 10import javax.naming.InitialContext; 11import javax.servlet.ServletException; 12import javax.sql.DataSource; 13 14public class Dbaccess extends Userinformationdto{ 15 16 DataSource ds; 17 Userinformationdto userInfDto; 18 19 public Dbaccess() throws ServletException { 20 try { 21 InitialContext ic = new InitialContext(); 22 ds = (DataSource)ic.lookup("java:/comp/env/jdbc/SQLServer"); 23 24 } catch(Exception e) { 25 26 } 27 } 28 29 public boolean Confimation(String user, int psw ) { 30 31 Connection con = null; 32 PreparedStatement pstmt = null; 33 ResultSet rset = null; 34 35 try { 36 con = ds.getConnection(); 37 if (user != null && psw != 0) { 38 39 StringBuffer sql = new StringBuffer(); 40 41 sql.append("select user_id, user_name, user_password from user_table where user_name='" + user +"'" + "and user_password=" + psw ); 42 43 // sql文実行準備 44 pstmt = con.prepareStatement(new String(sql)); 45 46 // sql文実行 47 pstmt.execute(); 48 49 // 実行結果を、ResultSetクラスに代入 50 rset = pstmt.executeQuery(); 51 if(rset.next()) { 52 setUser(rset.getString("user_name")); 53 setPsw(rset.getInt("user_password")); 54 System.out.println(getUser()); 55 System.out.println(getPsw()); 56 //StringBuilderの初期化を行います。 57 sql.delete(0, sql.length()); 58 sql.append("select task_number, task_title, task_start_date, task_end_date, task_status, task_description from user_table INNER JOIN user_task_table on user_table.user_id='" + rset.getString("user_id") + "'"); 59 System.out.println(sql); 60 // sql文実行準備 61 pstmt = con.prepareStatement(new String(sql)); 62 // sql文実行 63 pstmt.execute(); 64 //結果格納前に初期化を行います。 65 rset = null; 66 System.out.println(getUser()); 67 System.out.println(getPsw()); 68 // 実行結果を、ResultSetクラスに代入 69 rset = pstmt.executeQuery(); 70 ArrayList arrayList = new ArrayList(); 71 List<ArrayList> list = new ArrayList(); 72 while (rset.next()) { 73 arrayList.add(rset.getInt("task_number")); 74 arrayList.add(rset.getString("task_title")); 75 arrayList.add(rset.getDate("task_start_date")); 76 arrayList.add(rset.getDate("task_end_date")); 77 arrayList.add(rset.getInt("task_status")); 78 arrayList.add(rset.getString("task_description")); 79 list.add(arrayList); 80 } 81 setUserInformationList(list); 82 } 83 } else { 84 return false; 85 } 86 } catch (SQLException e) { 87 // TODO 自動生成された catch ブロック 88 e.printStackTrace(); 89 } finally { 90 try { 91 if (con != null) { 92 con.close(); 93 } 94 } catch (SQLException e) { 95 // TODO 自動生成された catch ブロック 96 e.printStackTrace(); 97 } 98 } 99 return true; 100 } 101 102} 103

該当のソースコード

Java

1package jp.co.model.todo; 2 3import java.util.ArrayList; 4import java.util.List; 5 6public class Userinformationdto { 7 8 private String user; 9 10 private int psw; 11 12 private List<ArrayList> userInformationList; 13 14 public String getUser() { 15 return user; 16 } 17 18 protected void setUser(String user) { 19 this.user = user; 20 } 21 22 public int getPsw() { 23 return psw; 24 } 25 26 protected void setPsw(int psw) { 27 this.psw = psw; 28 } 29 30 public List<ArrayList> getUserInformationList() { 31 return userInformationList; 32 } 33 34 protected void setUserInformationList(List<ArrayList> userInformationList) { 35 this.userInformationList = userInformationList; 36 } 37 38 39 40} 41

試したこと

ここに問題に対して試したことを記載してください。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/02/23 18:15

NullPointerExceptionのスタックトレースを追記してください。 おそらくuserInfDtoのインスタンスがnullだと思います。このインスタンスはいつ初期化するのでしょうか?
pokemn

2019/02/24 04:30

申し訳ありません。スタックトレースの追記を致しました。 おそらくuserInfDtoのインスタンスがnullだと思います。このインスタンスはいつ初期化するのでしょうか? →私の認識ですと、DbaccessクラスでDtoに値を格納したあとはUserconfirmationクラスの  フィールドuserInfDtoでgetすれば格納した値を参照できるという認識だった為、  インスタンス初期化を行うという認識はありませんでした。
退会済みユーザー

退会済みユーザー

2019/02/24 05:05

> 私の認識ですと、DbaccessクラスでDtoに値を格納したあとはUserconfirmationクラスの > フィールドuserInfDtoでgetすれば格納した値を参照できるという認識だった為、 おっしゃるとおりです。getすれば、NullPointerExceptionはなくなるでしょう。解決のためにコードを書いてみませんか。その他いろいろな問題がありそうですが、有識者の回答を待ちましょう。
guest

回答1

0

ベストアンサー

NullPointerExceptionの対処

doPost()のなかで使うthis.userInfDtoのインスタンスが生成されていないのでNullPointerExceptionが起きます。つまり、this.userInfDtoを使っているところは例外が発生します。

Java

1System.out.println(this.userInfDto.getUser()); 2System.out.println(this.userInfDto.getPsw()); 3if (!StringUtils.isEmpty(this.userInfDto.getUser()) && this.userInfDto.getPsw() != 0) { 4request.setAttribute("userinformationList", this.userInfDto.getUserInformationList());

これらのthis.userInfDto.xxxを、dbaccess.xxxに置き換えれば問題は起きません。たぶん回答はこれでいいのでしょうけれど、その他いろいろ問題がありますね。

技術的な問題点

  • スレッドセーフではない

サーブレットがシングルスレッドモデルを採用しない場合(ほとんどの場合)、サーブレットのインスタンス変数は保護されません。同様にDBAccessのインスタンス変数もマルチスレッドから保護されません。クラスのインスタンス変数は削除して、メソッドのローカル変数だけで処理してください。

  • List<ArrayList>の使い方がジェネリクスの利点を享受していない。

user_task_tableのDtoを用意してList<UserTaskDto>として使いましょう。

  • Dtoはセッションに格納することを考慮してSerializableを実装する。
  • JDBCのPreparedStatementの使い方に誤りがある。SQLインジェクションを避けるために値をバインドする。
  • SQLが二回発行されている(execute/executeQuery)。
  • AutoClosableなリソースにtry-with-resource構文を使ってもよい。できれば使ってほしい。

技術的な問題は必ず解決しましょう。本格的に学習することをおすすめします。学習内容はおよそ次のとおりです。

  • Java Servlet (+Threadの知識)
  • JDBC
  • Javaシリアライゼーション + Java Beans
  • アプリケーションアーキテクチャ設計パターン

クラス設計についての提言

一般的にはMVCパターンで考えるようですが、レイヤー(層) パターンで考えてみます。レイヤーにすることで、機能ごとに独立性を高めて、作りやすく、保守性をよくします。Webアプリケーションではレイヤーを三層または四層に分て考えます。

層 (レイヤー)担当機能クラスJava依存関係
プレゼンテーション層GUIを担当するServlet,JSPJava EE (Web)
ビジネスロジック層本質的なシナリオを実行する(提示されたソースにはありません)Java SE(+トランザクション管理?)
永続化層データベースなどの永続データを扱う層DAO(Data Access Object)JDBC
すべての層層をまたがって移動するデータDTO(Data Transfer Object)Java SE

レイヤーパターンには整合性を保つために規約が必要です。たとえば、各層は相互に依存してはならない(ビジネスロジック層はServletクラスに依存しない(importしない)など)。呼び出しは上位層から下位層へ。引数、戻り値として使用するオブジェクトを取り決める。下位層から上位層へ投げる例外を取り決める、トランザクションの扱いなど、多々あります。

レイヤーパターンから見た改善点

  • できればビジネスロジックに相当するクラスを用意してGUIから分離してください。

ログイン機能に本質的な、ユーザーの存在チェックを行う。ユーザーのタスク一覧を作成すること。

  • DbAccessがDTOの派生クラスになっていてレイヤー機能の分離ができていません。

永続化層にアクセスする機能(JDBC)がDtoを汚染しています。Dtoは軽量にしてください。

  • user_table, user_task_tableのアクセス機能が混在しています。

再利用性を考えると分離すべきです。そうすれば他のビジネスロジックからも利用できるようになります。

  • 同様に、user_table, user_task_tableのDtoを作成する。

上のアクセス機能ごとにDtoを作成するのが良いと思います。やはり再利用性のため。

以下のようなクラス分けにすることを提案します。

層 (レイヤー)クラス案
プレゼンテーション層Userconfirmation,Loginsuccess.jsp,Login.jsp
ビジネスロジック層LoginLogic
永続化層DBAccess(UserTableAccess,UsserTaskTableAccess),ConnectionManager
すべての層UserDto,UserTaskDto

投稿2019/02/24 12:29

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pokemn

2019/02/24 23:49

回答ありがとうございます。 無事解決致しました。 技術的な問題点とクラス設計の提言についてもご指摘の通り修正してみます。 またこれを機に一度上記で挙げられた4つの内容を本格的に学習致します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問