Passing a List from servlet to a JSP file

163 views Asked by At

I have an assignment where I'm supposed to make a simple website using EJB, JPA, JSP and some other stuff such as CSS and javascript.

I'm trying to send a list containing all the products that are stored in my database. I first create and populate a list with the ProductType objects in my servlet which is then passed to my JSP through the RequestDispatcher. In my JSP I use JSTL to iterate through the list and print the names of the products.

Nothing gets printed however. And I know through earlier testing with the JSTL choose statement that the list is null. I also tried populating a list in the servlet and then "printing" the product names on my servlet. When I ran the servlet on my server the product names were shown. That tells me that it's not a problem with my database or the way I'm retrieving my ProductType objects/tuples but rather that something is wrong when I pass the list from my servlet to my JSP.

Here is my relevant servlet code:

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.getWriter().append("Served at: ").append(request.getContextPath());
        List<ProductType> productTypes = facade.getAllProducts();
        
        // Set the list of product names as a request attribute
        request.setAttribute("productTypeList", productTypes);

        // Forward the request to the homePage.jsp page
        RequestDispatcher dispatcher = request.getRequestDispatcher("homePage.jsp");
        dispatcher.forward(request, response);
        
    }

And here is my relevant code from my homePage.jsp file

    <p>
        Our products    
    </p>

    <%
     List<ProductType> productList = (List<ProductType>)session.getAttribute("productTypeList");
     request.setAttribute("productList", productList);
    %>
    <c:forEach items="${productTypeList}" var = "product">
        <p><c:out value="${product.getProductName()}"/></p>
    </c:forEach>

Figured that I might aswell post the code for retrieving the ProductType objects too

Facade

    @EJB
    ProductTypeEAOLocal productTypeEAO;

    public List<ProductType> getAllProducts() {
        return productTypeEAO.getAllProductTypes();
    }

ProductTypeEAOImpl

    public List<ProductType> getAllProductTypes() {
        return em.createQuery("SELECT p FROM ProductType p", ProductType.class).getResultList();
    }

I'm not really sure what I'm doing wrong, I'm quite new to EJB and web-developement in general. From looking around online this seems like it's the way to go about it and I'm kind of at my wits end to be honest. Would very much appreciate some help.

1

There are 1 answers

0
Gas On

Your problem is that you put list into the request:

 request.setAttribute("productTypeList", productTypes);

but read it from the session, which is not existing so returns null:

List<ProductType> productList = (List<ProductType>)session.getAttribute("productTypeList");

Request attributes are correctly passed when you use dispatcher.forward.
So your JSTL code should look like this (remove the whole line that sets the productList variable as it is the line that nullifies the variable.):

    <c:forEach items="${productTypeList}" var = "product">
        <p><c:out value="${product.getProductName()}"/></p>
    </c:forEach>

The ${productTypeList} expression will scan any scope for given attribute, but if you want to fix it to the request scope and only look in there you can use this form ${requestScope.productTypeList}

Make sure that you use same name as you have once productTypeList and then productList.

Also remove the line:

 response.getWriter().append("Served at: ").append(request.getContextPath());

as if you use the dispatcher.forward you shouldn't write to the response, before you forward.

One additional comment is that it looks like you have way too many layers for such simple app. You should just inject @EJB which should be your DAO and Facade in your servlet code and in EJB use EntityManager. There is no point to have Facade if you just have one DAO. It is only useful when you want to hide your DB complexity from the servlet layer.
Also dont create interfaces if you just have single implementation, waist of time and makes code harder to maintain. When you will have need for many implementations you can always refactor your code.