0

I am practicing Java-based web development using Tomcat as the application server and following MVC pattern without any framework. I want to send a few fields from the database and display it in a JSP form. For this, I am creating an array list of the data in a java class and then sending it to a controller, which then sends it to the JSP file where it will be shown in a table.

However, the array list is fine in the controller (used .size() method on the ArrayList to confirm equal no. of database records), but the data is apparently null when reaching the JSP page. I have tried going through many links, but most do not apply to my situation (not maven) and the only one that does do not provide a solution. Appreciating any help!

menu_model.java

package Created;

public class menu_model {
    private String menuid;
    private String menuscr;
    private String menuprnt;
    
    public void setmid(String menuid) {
        this.menuid = menuid;
    }

    public void setmscr(String menuscr) {
        this.menuscr = menuscr;
    }
    
    public void setmprnt(String menuprnt) {
        this.menuprnt = menuprnt;
    }
    
    public String getmid() {
        return menuid;
    }

    public String getmscr() {
        return menuscr;
    }

    public String getmprnt() {
        return menuprnt;
    }    
}

menu_DAO.java

package Created;

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

public class menu_DAO {
        public static String cond = "jdbc:oracle:thin:@localhost:1535:DATABASE";
        public static String usnm = "username";
        public static String pwrd = "password";
        
        public static ArrayList<menu_model> menu_rtrv(){
        try {
        PreparedStatement pst = null; 
        
        menu_model po;
        
        Class.forName("oracle.jdbc.OracleDriver");
        Connection conn = DriverManager.getConnection(cond,usnm,pwrd);
        pst = conn.prepareStatement("select m_id,m_scrnm,m_prnt from menu_menus where m_id in "
                + "(select um_id from um_menus where user_id=? and umenu_enable=?)");
        pst.setString(1,"TEST");
        pst.setString(2, "YES");
        ResultSet rs=pst.executeQuery();
        
        ArrayList<menu_model> rsarr = new ArrayList<>();
                while (rs.next())
                {
                    po = new menu_model();
                    po.setmid(rs.getString("m_id"));
                    po.setmscr(rs.getString("m_scrnm"));
                    po.setmprnt(rs.getString("m_prnt"));
                    rsarr.add(po);
                }
                conn.close();
                return rsarr;
            }
        
        catch (ClassNotFoundException | SQLException e)
        {
            e.getMessage();
        }
            return null;
}
}

menu_cntrlr.java (Controller)

package Created;

import jakarta.servlet.RequestDispatcher;
import java.io.IOException;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.*;
import java.util.ArrayList;

@WebServlet (name = "menu_cntrlr", urlPatterns = {"/mctrl"})
public class menu_cntrlr extends HttpServlet {

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        ArrayList alist = menu_items.menu_rtrv();
        request.setAttribute("list", alist);
        RequestDispatcher dispatcher = request.getRequestDispatcher("m_menu.jsp");
        dispatcher.forward(request, response);
        }

@Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

@Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
}

m_menu.jsp

<%@page import="java.util.*,Created.menu_model"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
   <head>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
    <link rel="stylesheet" href="static/vendor/fontawesome/all.min.css" />
    <link rel="stylesheet" href="bs_ovrd.css" />
    <title>Main menu</title>
   </head>
    <body>
        <table border=2>
    <tr>
        <th>Menu ID</th>
        <th>Menu Scr Name</th>
        <th>Menu Parent</th>
    </tr>
        <%
        ArrayList<menu_model> dlist=(ArrayList)request.getAttribute("list");
        Iterator it=dlist.iterator();
        while(it.hasNext())
        {
            menu_model m=(menu_model)it.next();  
        %>
    <tr>
        <td><%=m.getmid() %></td>
        <td><%=m.getmscr() %></td>
        <td><%=m.getmprnt() %></td>
    </tr>
    <%
        }
    %>
    </table>
    </body>
</html>

HTTP Status 500 – Internal Server Error (upon loading http://localhost:8080/WebApplication1/m_menu.jsp)

Type Exception Report

Message An exception occurred processing [/m_menu.jsp] at line [30]

Description The server encountered an unexpected condition that prevented it from fulfilling the request.

Exception

org.apache.jasper.JasperException: An exception occurred processing [/m_menu.jsp] at line [30]

28:     
29:         
30:         Iterator it=dlist.iterator();
31:         while(it.hasNext())
32:         {
33:             menu_model m=(menu_model)it.next();


Stacktrace:
    org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:610)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:499)
    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:792)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
Root Cause

java.lang.NullPointerException: Cannot invoke "java.util.ArrayList.iterator()" because "dlist" is null
    org.apache.jsp.m_005fmenu_jsp._jspService(m_005fmenu_jsp.java:148)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    jakarta.servlet.http.HttpServlet.service(HttpServlet.java:792)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:466)
    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:792)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
Note The full stack trace of the root cause is available in the server logs.

Tried using JSTL and the JSP page loads but the if condition returns and no list:

<c:if test="${empty list}">
            it is null
            </c:if>
        <c:forEach var="mitem" items="${list}">   
         <td><c:out value="${mitem.menuid}"/></td>
       <td><c:out value="${mitem.menuscr}"/></td>
       <td><c:out value="${mitem.menuprnt}"/></td>
     </c:forEach>

EDIT: I tried passing an integer declared in the controller to the JSP, and found the following error which I think is linked to the previous one:

Exception Report

Message An exception occurred processing [m_menu.jsp] at line [21]

Description The server encountered an unexpected condition that prevented it from fulfilling the request.

Exception

org.apache.jasper.JasperException: An exception occurred processing [m_menu.jsp] at line [21]

18:    </head>
19:     <body>
20:      <%//ArrayList<menu_model> dlist=(ArrayList)request.getAttribute("list");
21:         int sc = (int) request.getAttribute("list");
22:         out.print(sc);%>
23:         <table border=2>
24:     <tr>


Stacktrace:
    org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:610)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:499)
    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:792)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
Root Cause

java.lang.NullPointerException: Cannot invoke "java.lang.Integer.intValue()" because the return value of "jakarta.servlet.http.HttpServletRequest.getAttribute(String)" is null
    org.apache.jsp.m_005fmenu_jsp._jspService(m_005fmenu_jsp.java:145)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    jakarta.servlet.http.HttpServlet.service(HttpServlet.java:792)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:466)
    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:792)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)

The below is the code that I had added:

//in the Controller
int c=2;
        request.setAttribute("list", c);

//in the JSP
<%  int sc = (int) request.getAttribute("list");
    out.print(sc);
%>
Tim Moore
  • 8,958
  • 2
  • 23
  • 34
jinoJ
  • 3
  • 3
  • Just to be sure, what URL are you loading that triggers the error? Are you sure the controller is being invoked? – Tim Moore Jan 29 '23 at 22:29
  • I'm loading the JSP @http://localhost:8080/WebApplication1/m_menu.jsp as the controller has a redirect to this JSP. I tried adding a button to receive a String I declared in the controller and it displays. The issue seems to be with the request not accepting the ArrayList I guess, might I be missing an imports? – jinoJ Jan 30 '23 at 07:23
  • If you're visiting m_menu.jsp directly, that would explain it. In that case, the servlet is never invoked, it is bypassed and the JSP loads directly. You'd need to visit the servlet URL http://localhost:8080/WebApplication1/mctrl – Tim Moore Jan 30 '23 at 08:26
  • When using the MVC pattern with the Java servlet API, it's common to put the JSP files into the WEB-INF folder to prevent them from being accessed directly, which avoids this problem. See https://stackoverflow.com/a/6825956/29470 – Tim Moore Jan 30 '23 at 08:29
  • Thank you, it worked!! This solved another query I had of how a JSP would select a servlet to receive files from. Please post this as an answer so that I can accept it. Also, thanks for the tip about putting the files in WEB-INF. Still, I don't understand how I was able to display the String from the controller but not the integer... – jinoJ Jan 30 '23 at 10:22

1 Answers1

0

When loading the URL http://localhost:8080/WebApplication1/m_menu.jsp, this invokes the JSP directly, without first going through the menu_cntrlr servlet. This means it never has the opportunity to add attributes to the request. Then, when the JSP tries to access these attributes, they are returned as null.

In order to invoke the servlet, you need to visit the URL corresponding to the urlPatterns parameter of its @WebServlet mapping: http://localhost:8080/WebApplication1/mctrl

This results in the servlet being invoked first, setting the request attribute, and then forwarding to the JSP, which will then be able to read the attribute successfully.

When following the MVC pattern with the Java Servlet API, JSPs should never be accessed directly by URL. They are considered an implementation detail of the controller, and to satisfy their preconditions, the controller must always be invoked first. For that reason it is common to put JSP files into the WEB-INF directory of the webapp, as this prevents them from being directly addressable by URL from a web browser or other HTTP client. The Servlet specification requires that files in WEB-INF are not served directly to clients.

Tim Moore
  • 8,958
  • 2
  • 23
  • 34