views:

82

answers:

2

I am currently working my way through a Sam's Teach Yourself JSP. In one chapter, we wrote a crude shopping cart application which used Servlets for various functions. Come Chapter 14, we replace most of those servlets with JSP using beans.

For some reason that is eluding me, my JSP isn't working.


Here is the functional servlet:


/**
 * 
 */
package hu.flux.shoppingcart;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

/**
 * @author Brian Kessler
 *
 */
public class AddToShoppingCartServlet extends HttpServlet {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    @SuppressWarnings("deprecation")
    public void service (HttpServletRequest request, HttpServletResponse response)
        throws IOException, ServletException
        {
            // First get the item values from the request.
            String productCode = request.getParameter("productCode");
            String description = request.getParameter("description");
            int quantity = Integer.parseInt(request.getParameter("quantity"));
            double price = Double.parseDouble(request.getParameter("price"));

            // Now create an item to add to the cart.
            Item item = new Item(productCode, description, price, quantity);
            HttpSession session = request.getSession();
            ShoppingCart cart = ShoppingCart.getCart(session);

            cart.addItem(item);

            // Now display the cart and allow the user to check out or order more items.
            response.sendRedirect(
                    response.encodeRedirectUrl(ShoppingCart.SHOPPING_CART_PATH + "/ShowShoppingCart.jsp"));
        }

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub

    }

}

and


here is the dysfunctional JSP:


<%-- Get a reference to the shopping cart --%>
<jsp:useBean id="cart" class="hu.flux.shoppingcart.ShoppingCart" scope="session" />

<%-- Create an item object --%>
<jsp:useBean id="item" class="hu.flux.shoppingcart.Item" scope="page" />

<%-- Copy the request parameters into the item --%>
<jsp:setProperty name="item" property="*"/>

<%-- Add the item to the shopping cart --%>
<% cart.addItem(item); %>

<%--Display the product catalog again --%>
<jsp:forward page="ShowShoppingCart.jsp" />

To help mystify things, no errors are displaying. The last line is definitely working as it successfully forwards to ShowShoppingCart.jsp, but then the cart is empty.

After experimenting, I have come to the conclusion that whatever is going wrong must happen when or after is called. I know this because I moved some code from a on ShowShoppingCart.jsp onto the AddToShoppingCart.jsp and (after some debugging), the shopping cart would display correctly on AddToShoppingCart.jsp

As it may help to understand what is going wrong, here are two more pieces of code:

*Here is the page called by jsp:forward page="ShowShoppingCart.jsp" *

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ page import="hu.flux.shoppingcart.*"%>
<%
    String shoppingCartSerialization = "";
    ShoppingCart cart = ShoppingCart.getCart(session);
    shoppingCartSerialization = cart.getSerialization();  
    Cookie cookie = new Cookie ("ShoppingCart", shoppingCartSerialization);
    cookie.setMaxAge(999999999);
    response.addCookie (cookie);
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"&gt;
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body bgcolor="#ffffff">
<div><jsp:include page="DisplayShoppingCart.jsp" flush="true" /></div>
<form action="<%=ShoppingCart.SHOPPING_CART_PATH %>/Checkout.jsp"
        method="post" >
    You may <a 
        href="<%=ShoppingCart.SHOPPING_CART_PATH %>/ShowProductCatalog2.jsp"
    >continue shopping</a> or
    <input type="submit" value="Check Out">
</form>
<br/><br/><br/><hr/>
<form action="TerminateShoppingSessionServlet" method="post"><input
    type="submit" value="Terminate Session"></form>
</body>
</html>

*Here is the page called by jsp:include page="DisplayShoppingCart.jsp" flush="true" *

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ page import="hu.flux.shoppingcart.*"%>
<%@ page import="java.text.*"%>
<%@ page import="java.util.*"%>
<%-- Show the header with the shopping cart item --%>
<img id="cart_image"
    src="/SamsTeachYourselfJSP/ShoppingCart/images/cart4.png" />
<h1>Shopping Cart</h1>

<% // Get the current shopping cart from the user's session.
    ShoppingCart cart = ShoppingCart.getCart(session);

    // Get the items from the cart.
    Vector<Item> items = cart.getItems();

    // If there are no items, tell the user that the cart is empty.
    if (items.size() == 0) {%><strong>Your shopping cart is empty.</strong>
<%}
    else
    {
        %>
<%-- Display the header for the shopping cart table --%>
<br />
<table border="4">
    <tr>
        <th>Description</th>
        <th>Quantity</th>
        <th>Price</th>
    </tr>
    <%
                int numItems = items.size();

                // Get a formatter to write out currency values.
                NumberFormat currency = NumberFormat.getCurrencyInstance();
                for (int i=0; i<numItems; i++)
                {
                    Item item = (Item)items.elementAt(i);
                    out.print (item.printShoppingCartTableRow(currency, 
//                              "/SamsTeachYourselfJSP/ShoppingCart/RemoveItemServlet?item="+i)
                                "/SamsTeachYourselfJSP/ShoppingCart/RemoveItem.jsp?item="+i)
                            );
                }
              %>
</table>
<%  
    }
%>

Any ideas what I'm overlooking?

A: 

try the following (assuming the jsp is in the root folder (webapp)):

final RequestDispatcher rd = request.getRequestDispatcher("ShowShoppingCart.jsp");
rd.forward(request, response);

instead of the redirect. I think a redirect causes the browser to make a new request when getting the response to the specified url.

kukudas
The servlet version is actually the working one. The request is working fine. If anything along that line maybe the <jsp:forward> is creating the problem?
Brian Kessler
oh, i misread the question then. Did you check if you can access the items on the forwarded page like: ${item} ? I'm not sure about the scope for item maybe it should be request instead of page.
kukudas
On the forward page, the shopping cart is empty, so the item was apparently lost in spite of <% cart.addItem(item); %> which should have added the item to the page. On "ShowShoppingCart.jsp", the item would only be accessed through the cart, which in turn should be a property of the session.
Brian Kessler
hm.. ok my initial thought was that maybe because the scope of item is page that it gets added but falls out of scope after the forward.
kukudas
I think you may be onto something with the scope issue. I've been playing around with the code and I discovered that if I bypass the <jsp:forward> page and include code from a <jsp:include> on the forward page, I can actually get the shopping cart to display. But then there is another anomaly because the item received is showing with a quantity of 0 ... so somehow the quantity is getting lost.
Brian Kessler
Fixed the quantity = 0 problem. _That_ was a problem in addItem() which leaves me wondering how the code actually worked properly with the Servlet. But clearing that problem still didn't resolve the issue that my cart is lost sometime after the <jsp:forward> ... still playing.
Brian Kessler
Is it possible to see the full sources ? Do you use gtalk or any messenger ? I would like to see it threw.
kukudas
I found the problem. Apparently the problem was that previously I used a different name form my variable and my session attribute. With bean, these names became one and I needed to use the same name I gave the session attribute elsewhere for those references to find it. See my answer below. Cheers for the offer! (If you still want to see the full source, I'll be happy to send it to you though.)
Brian Kessler
kukudas
I'm not familiar... I'll have to look for it. :-) Cheers for the recommendation. I think Sam's is a great series for starting many technologies, but a lot of "best practices" is certainly being ignored. Just curious, if you have time, how would you rewrite this code to get rid of the stuff which shouldn't be there?
Brian Kessler
I would try to replace the jsp expressions with EL expressions and use JSTL. As a general rule the jsp is the view and therefore there should only be things displayed. Any logic should be handled in the servlet. I don't know if it is handled in your book but the MVC pattern is a widly used pattern for this stuff. As for your examples you should stick with the servlet example which is cleaner then the jsp version.
kukudas
Heard of EL and JSTL but I don't know anything about them yet. They may be later in the book. The book mentioned MVC and I know about it, but the book hasn't really discussed it yet. I think the author mentioned he'd get into that around chapter 20. (I'm on 14 out of 24).
Brian Kessler
A: 

I found the problem.

Previously, I used one name for the variable which held my ShoppingCart, "cart".

I used a second name for the session attribute which held my ShoppingCart, "ShoppingCart".

Using Beans, these names must be the same, so I needed to change

<jsp:useBean id="cart" class="hu.flux.shoppingcart.ShoppingCart" scope="session" />

To

<jsp:useBean id="ShoppingCart" class="hu.flux.shoppingcart.ShoppingCart" scope="session" />

and likewise:

<% cart.addItem(item); %>

To

<% ShoppingCart.addItem(item); %>

For the sake of convention (starting variables with lowercase letters), it would probably be better to instead change all the other references to the session attribute name, but this worked for a "quick fix".

Brian Kessler