0

Background:

I'm working on a problem where I randomly generate an outcome based on buttons that are pushed. I'm using Java controllers and JSP & JSTL. I had to fish around for a solution which I found, but when trying to make sense of the solution, I had a very difficult time with one portion which I'll paste below. Note that the below is just an extract of the fundamental parts that are giving me the problem, and the actual code works well. I'm trying to figure out how it works well when I'm not grasping the underlying mechanism of how it's working:

In the controller:

public String Index(HttpSession session){
    if(session.isNew()){
        **ArrayList<> logList2 = new ArrayList<>();
        session.setAttribute(“actionJournal”, logList2);**
    }
    return “index2.jsp”;
}

public String Form(HttpSession session){

    if(val == 1){
        **ArrayList<String> list1 = (ArrayList<String>) session.getAttribute(“actionJournal”);**
        list1.add(0, “yo yo yo”);
        session.setAttribute(“logList”, list1);
    }

    if(val == 2){
        ArrayList<> list2 = (ArrayList<>) session.getAttribute(“actionJournal”);
        list2.add(0, “ha ha ha”);
        session.setAttribute(“logList”, list2);
    }
    return “redirect:/“;
}

In the index2.jsp:

<c:forEach items=“${logList}" var="event">
    <c:out value=“${event} escapeXml=“false”/>
</c:forEach>

What happens when I run the code: When I first visit the homepage, the counter is at 0 (not included in the code above) and no messages are displayed initially, but when I click a button, the counter changes up or down based on a random number (not included in the code above), and a message is displayed on the screen telling me I either lost or gained money (the message in the code above is represented by yo yo yo or ha ha ha). When I click the same button again or a different one, another random change in the counter occurs along with a new message, and these messages pile up on each other (so you can get an activity log of all the messages) --> this is represented by the forEach loop in the index2.jsp code I pasted below the controller code. This is the desired result. What I don't get is how the solution manages to get a log of all the messages.

What I'm specifically confused about: The parts in the code above that I put in asterisks are the parts that, if I changed them in some other way, causes the messages that show up to delete the message that was there previously. That is, it no longer keeps a log of all my actions up to that point and only shows the most recent message that would appear. I narrowed it down to those lines of code because when I changed everything else, the program still functioned correctly.

I can't grasp why list1 or list2 need to = (ArrayList) session.getAttribute("actionJournal") when it doesn't seem like actionJournal or even the original array list logList2 get updated when a button is pushed, only list1 or list2. I think it has something to do with session.isNew() --> but can't put my finger on anything.

The way it looks to me is that actionJournal is representing an empty list (logList2), and that each time list1 or list2 is generated, it's inheriting from an empty list. Yet it works. But when I set list1 or list2 = new ArrayList(), it only shows the most recent messages and not the whole journal of messages.

Olaf Kock
  • 46,930
  • 8
  • 59
  • 90

1 Answers1

1

If I understand correctly, you're not sure why your messages list is growing rather than being replaced with a new list every time.

What you have are session variables. These variables exist for the duration of a session.

if(session.isNew()){
        ArrayList<> logList2 = new ArrayList<>();
        session.setAttribute(“actionJournal”, logList2);
}

So here, you're saying add an actionJournal that is an ArrayList.

Then here:

(ArrayList<>) session.getAttribute(“actionJournal”);

You're saying get the same actionJournal I created earlier.

The way it looks to me is that actionJournal is representing an empty list (logList2), and that each time list1 or list2 is generated, it's inheriting from an empty list.

No, this is incorrect. First, there is no inheritance of any kind. You are retrieving the exact same list every time you hit public String Form(HttpSession session). list1 and list2 are never generated. They are always the same list that is created in public String Index(HttpSession session) because you are retrieving the session attribute actionJournal.

In fact, you have some superfluous code. This is identical functionality:

...

if(session.isNew()){
    ArrayList<> logList2 = new ArrayList<>();
    session.setAttribute(“logList”, logList2);
}

...

ArrayList<> actionJournal = (ArrayList<>)session.getAttribute(“logList”);
if(val == 1){
    list1.add(0, “yo yo yo”);
}
if(val == 2){
    list2.add(0, “ha ha ha”);
}

Notice that you don't even need to set the session attribute, because you're modifying what is already a session attribute.

Christopher Schneider
  • 3,745
  • 2
  • 24
  • 38
  • Thank you so much for your reply. I think I understand what's happening now thanks to your explanation. I want to say it back to you in my own words, if that's ok, and you tell me if I'm hitting the nail on the head or if I'm still off. What I think I'm getting from what you said is that because I put logList1 into session as actionJournal, and because I later did a getAttribute for actionJournal and put it with list1/list2, that list1/list2 effectively became one and the same as actionJournal, so by adding to list1/list2, I was essentially making entries into actionJournal. – NoCardiologist1 Feb 25 '20 at 23:41
  • (continued)...and I could therefore just use actionJournal in the .jsp file. Also, I went ahead and followed your advice about the superfluous code, removed the extra session additions under list1/list2, and the code still works as intended. I think this may have caused my confusion since I was thinking that getting the Attribute meant that I was just getting the value there, and then whatever changes I made to the newly created list wouldn't affect the session attribute it was based on so I had to create a new session attribute and variable. – NoCardiologist1 Feb 25 '20 at 23:46
  • 1
    Yeah, that sounds about right. You can also test this out with a debugger, which I'd highly recommend learning how to use. You can then set break points and look at the value of your list as the program's running, which I think would have helped with your initial confusion. It's not too hard to learn how to use a debugger. If you're using Eclipse or IntelliJ, it's about as simple as hitting the run debug button instead of run and setting breakpoints. – Christopher Schneider Feb 26 '20 at 15:18
  • 1
    An unrelated note: For this particular application, you should look at `LinkedList` instead of `ArrayList` since you always insert at index 0, and prefer using the `List` interface as your l-value, e.g. `List list = new LinkedList<>()`. I won't get into `List` too much, but inserting at index 0 of an `ArrayList` requires moving every element "down" one. e.g. moving index 0 to 1, 1 to 2, ..., n to n+1. A LinkedList simply puts the element at the head so no re-ordering is required. – Christopher Schneider Feb 26 '20 at 15:22