spmiwdar1007
@spmiwdar1007

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

【Java】結合条件のsqlの値をjspに表示したいです。NullPointerExceptionエラーが修正できません。

解決したいこと

Javaでいいね機能は作ったので、お気に入り機能を作っています。
結合条件のsql文で選択した値をjspに表示させたいのですが、
データは間違いなくあるのに、エラーが出てしまいます。
解決方法を教えて下さい。

発生している問題・エラー

org.apache.jasper.JasperException: [/account/user.jsp] の処理中に行番号 [35] で例外が発生しました。

32: 		<th>タイトル</th>
33: 		<th>詳細</th>
34: 	</tr>
35: 	    <% for (FavoriteInfo f : favoriteList) { %>
36: 	        <tr>
37: 	            <td><%= f.getId() %></td>
38: 	            <td><%= f.getFavoriteBook() %></td>


Stacktrace:
	org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:599)
	org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:488)
	org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:380)
	org.apache.jasper.servlet.JspServlet.service(JspServlet.java:328)
	jakarta.servlet.http.HttpServlet.service(HttpServlet.java:814)
	org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
根本原因

java.lang.NullPointerException: Cannot invoke "java.util.List.iterator()" because "favoriteList" is null
	org.apache.jsp.account.user_jsp._jspService(user_jsp.java:171)
	org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
	jakarta.servlet.http.HttpServlet.service(HttpServlet.java:814)
	org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:456)
	org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:380)
	org.apache.jasper.servlet.JspServlet.service(JspServlet.java:328)
	jakarta.servlet.http.HttpServlet.service(HttpServlet.java:814)
	org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
注意 原因のすべてのスタックトレースは、サーバのログに記録されています。

該当するソースコード

【user.jsp】

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.List"%>
<%@ page import="java.util.ArrayList"%>
<%@ page import="pack.FavoriteInfo"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ユーザー情報</title>
</head>
<table>
	<tr>
		<th>投稿ID</th>
		<th>タイトル</th>
		<th>詳細</th>
	</tr>
	<% for (FavoriteInfo f : favoriteList) { %>
      <tr>
          <td><%=f.getId()%></td>
          <td><%=f.getFavoriteBook() %></td>
          <td><%=f.getDetail() %></td>
      </tr>
  <% } %>
</table>
</body>
</html>

【index.jsp】↓がuser_idのパラメータ部分です。

<% Integer userId = (Integer) request.getSession().getAttribute("id"); %>
<header>
  <a href="/test/account/user.jsp?user_id=<%= userId %>"><button type="button" >マイページへ</button></a>
</header>

【Favorite.java】

package pack;

import java.io.IOException;
import java.sql.SQLException;
import java.util.List;

import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
/**
 * Servlet implementation class Favorite
 */
@WebServlet("/Favorite")
public class Favorite extends HttpServlet {
	private static final long serialVersionUID = 1L;
    /**
     * @see HttpServlet#HttpServlet()
     */
    public Favorite() {
        super();
        // TODO Auto-generated constructor stub
    }
	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		// 受け取る文字設定
		request.setCharacterEncoding("utf-8");
		// 送る文字設定(html文字;文字コード)
		response.setContentType("text/html;charset=utf-8");
		try {
			Integer userId = Integer.parseInt(request.getParameter("user_id"));
			FavoriteDAO fDAO = new FavoriteDAO();
			fDAO.connect();
			List<FavoriteInfo> favoriteList = fDAO.favorite(userId);
			request.setAttribute("favoriteList", favoriteList);
			RequestDispatcher rd = request.getRequestDispatcher("/account/user.jsp");
			rd.forward(request, response);
		} catch (SQLException e) {
			e.printStackTrace();
			response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
		}
	}
	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}

【FavoriteDAO.java】

package pack;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class FavoriteDAO {
	private String URL = "jdbc:mysql://localhost:xxxxxx";
	private String USER = "xxxxxxx";
	private String PASS = "xxxxxxx";
	PreparedStatement pstmt = null;
	ResultSet rs = null;
	Connection con = null;
	
	public void connect() {
		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
			con = DriverManager.getConnection(URL, USER, PASS);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public List<FavoriteInfo> favorite(int userId) throws SQLException {
		List<FavoriteInfo> favoriteList = new ArrayList<>();
		String sql = "select books.id, books.favorite_book, books.detail from books inner join likes on books.id = likes.books_id where likes.user_id = ?";
		try {
			connect();
			pstmt = con.prepareStatement(sql);
			pstmt.setInt(1, userId);
			rs = pstmt.executeQuery();
			while (rs.next()) {
				FavoriteInfo fi = new FavoriteInfo();
				fi.setId(rs.getInt("id"));
				fi.setFavoriteBook(rs.getString("favorite_book"));
				fi.setDetail(rs.getString("detail"));
				favoriteList.add(fi);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (pstmt != null)
	                pstmt.close();
	            if (rs != null)
	                rs.close();
	            if (con != null)
	                con.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return favoriteList;
	}
}

※"select books.id, books.favorite_book, books.detail from books inner join likes on books.id = likes.books_id where likes.user_id = ?" で値が取得できるのは、コマンドプロンプトで?に値を入れて確認済みです。

ackage pack;

import java.io.Serializable;

public class FavoriteInfo implements Serializable {
	
	private int id;
	private int user_id;
	private String favorite_book;
	private String detail;
	
	public int getId() {
		return this.id;
	}
	public void setId(int id) {
		this.id = id;
	}
	
	public int getUserId() {
		return this.user_id;
	}
	public void setUserId(int user_id) {
		this.user_id = user_id;
	}

	public String getFavoriteBook() {
		return this.favorite_book;
	}
	public void setFavoriteBook(String favorite_book) {
		this.favorite_book = favorite_book;
	}

	public String getDetail() {
		return this.detail;
	}
	public void setDetail(String detail) {
		this.detail = detail;
	}

}

自分で試したこと

原因はfavoriteListに値が入っていないことだと分かるのですが、
何故値が入らないのか分かりません。
自分なりには何度も確認をしたのですが修正できませんでした。
どなたか助けてください。。。

0

1Answer

JSPのコンパイルエラーは、

favoriteList cannot be resolved to a variable

favoriteList変数が解決できない」(変数が見つからない)というエラーでは?

1Like

Comments

  1. @spmiwdar1007

    Questioner

    @nak435
    回答ありがとうございます!
    変数を追加してみましたが、NullPointerExceptionエラーが出てしまいます。
    元々favoriteListの変数は入れていたのですが、修正途中で消えてしまっていました。。
    ご指摘ありがとうございます!

    org.apache.jasper.JasperException: [/account/user.jsp] の処理中に行番号 [35] で例外が発生しました。
    
    32: 		<th>タイトル</th>
    33: 		<th>詳細</th>
    34: 	</tr>
    35: 	    <% for (FavoriteInfo f : favoriteList) { %>
    36: 	        <tr>
    37: 	            <td><%= f.getId() %></td>
    38: 	            <td><%= f.getFavoriteBook() %></td>
    
    
    Stacktrace:
    	org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:599)
    	org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:488)
    	org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:380)
    	org.apache.jasper.servlet.JspServlet.service(JspServlet.java:328)
    	jakarta.servlet.http.HttpServlet.service(HttpServlet.java:814)
    	org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    根本原因
    
    java.lang.NullPointerException: Cannot invoke "java.util.List.iterator()" because "favoriteList" is null
    	org.apache.jsp.account.user_jsp._jspService(user_jsp.java:171)
    	org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    	jakarta.servlet.http.HttpServlet.service(HttpServlet.java:814)
    	org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:456)
    	org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:380)
    	org.apache.jasper.servlet.JspServlet.service(JspServlet.java:328)
    	jakarta.servlet.http.HttpServlet.service(HttpServlet.java:814)
    	org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    注意 原因のすべてのスタックトレースは、サーバのログに記録されています。
    
    <!-- ↓追加 -->
    <% List<FavoriteInfo> favoriteList = (List<FavoriteInfo>) request.getAttribute("favoriteList"); %>
    <table>
    	<tr>
    		<th>投稿ID</th>
    		<th>タイトル</th>
    		<th>詳細</th>
    	</tr>
    	    <% for (FavoriteInfo f : favoriteList) { %>
    	        <tr>
    	            <td><%= f.getId() %></td>
    	            <td><%= f.getFavoriteBook() %></td>
    	            <td><%= f.getDetail() %></td>
    	        </tr>
    	    <% } %>
    </table>
    
  2. 例えば、DBを検索してヒットせず0件だった場合でも、空のリストが返りませんか?
    nullが返ったということは、検索自体が失敗しているように思います。

    正しいクエリーが出ていることを、どこで確認されたのでしょうか? そのエビデンスを貼ってください。

  3. @spmiwdar1007

    Questioner

    @nak435
    コマンドプロンプトで実際にsql文を貼って確認しました。
    ↓の画像は、【FavoriteDAO.java】のsql文をコピーして「?」を2に変えたものです。
    見る感じ値はあるので、処理のコードを間違えているのでしょうか。。。
    sql.png

  4. 文字列も貼って欲しかったですが、そこで見えているselect文(の文字列)は、どこで得たものですか?
    上のプログラムが生成した文字列ですか? そこのエビデンスです。

    (ご自身が加工したものは意味がないです)

  5. @spmiwdar1007

    Questioner

    @nak435
    申し訳ないです。
    select文(の文字列)は、どこで得たものですか?
    上のプログラムが生成した文字列ですか?
    →自分の理解力でここの回答が求めている回答になるかわかりませんが、
    【index.jsp】※以降のセッションユーザーのIDは2です。

    <a href="/test/account/user.jsp?user_id=<%= userId %>"><button type="button" >マイページへ</button></a>
    

    これの結果が↓のURLです。
    url.png

    user_idが2であるパラメータを、【Favorite.java】の

    Integer userId = Integer.parseInt(request.getParameter("user_id"));
    

    で取得し【FavoriteDAO.java】の↓の処理でsql文から値を選択。

    public List<FavoriteInfo> favorite(int userId) throws SQLException {
    		List<FavoriteInfo> favoriteList = new ArrayList<>();
    		String sql = "select books.id, books.favorite_book, books.detail from books inner join likes on books.id = likes.books_id where likes.user_id = ?";
    		try {
    			connect();
    			pstmt = con.prepareStatement(sql);
    			pstmt.setInt(1, userId);
    			rs = pstmt.executeQuery();
    			while (rs.next()) {
    				FavoriteInfo fi = new FavoriteInfo();
    				fi.setId(rs.getInt("id"));
    				fi.setFavoriteBook(rs.getString("favorite_book"));
    				fi.setDetail(rs.getString("detail"));
    				favoriteList.add(fi);
    			}
    		} catch (Exception e) {
            // 省略
            }
    

    【Favorite.java】の↓の処理でfavoriteListに値を追加する。

    FavoriteDAO fDAO = new FavoriteDAO();
    fDAO.connect();
    List<FavoriteInfo> favoriteList = fDAO.favorite(userId);
    request.setAttribute("favoriteList", favoriteList);
    

    という認識です。

  6. @spmiwdar1007

    Questioner

    @nak435
    文字列の生成は、投稿したものはbooksテーブルに入り
    いいねを押したらlikesテーブルに入り
    books.idとlikes.books_idを結合して生成しています。
    books.png
    likes.png

  7. DBの内容に間違いはないことは事実そうですね。
    その前の確認内容は、想定通り正しく動いている前提ですね。

    今回はNullPointerException という想定外のことが起きているので、どこまでは想定通りに動いて、どこで想定と違う動きになっているのか、場所を特定し、原因を特定する、という作業が必要です。

    スクリーンショット 2023-06-07 15.58.27.png

    上から順にでも、下から順にでも、確認がし易いどちらかの方法で、大きく5つぐらいのステップがあるようなので、デバック情報を出力するなり、ブラウザのコンソールに出力するなりしながら、「そのステップは正しく実行した」というエビデンス(スクショ)を集めてください。

    「思った通りに動いていない、作った通りに動いている」という、プログラマあるあるが起きているだけです。(断定してごめんさない。原因が判明すれば真実かどうかが分かります)

  8. @spmiwdar1007

    Questioner

    @nak435
    ご親切にありがとうございます!!
    一度コンソールに出力してエビデンス集めてみます!!

  9. 本当にFavoriteDAO.favorite()が呼ばれていますか?
    呼ばれているなら、この中で例外が起きている可能性が高いと思います。
    呼ばれていないなら、それが問題です。

    エビデンスに期待します。

  10. @spmiwdar1007

    Questioner

    @nak435
    コンソールに表示して確認してたら、Integer.parseInt()メソッドが整数に変換できない値を処理していたのが原因でした。
    ここを修正したら無事に表示できました!!
    先日はご丁寧に教えて頂きありがとうございました!!

  11. 原因が判明してよかったです☺️

Your answer might help someone💌