I want to loop through an ArrayList of "Festivals" and get their information with get methods, printing out all its values. For some reason when I use this code, it will always choose the "0"th value and not increment the loop.
If I hard code the values as "get(1)" it will get the correct values so my issue is clearly with the syntax.
<h1>All Festival Information</h1>
<jsp:useBean id="allFestivals" type="java.util.ArrayList" scope="session" />
<table border="1">
<tr>
<td>Festival Name:</td>
<td>Location:</td>
<td>Start Date:</td>
<td>End Date:</td>
<td>URL:</td>
</tr>
<% for(int i = 0; i < allFestivals.size(); i+=1) { %>
<tr>
<td>${allFestivals.get(i).getFestivalName()}</td>
<td>${allFestivals.get(i).getLocation()}</td>
<td>${allFestivals.get(i).getStartDate()}</td>
<td>${allFestivals.get(i).getEndDate()}</td>
<td>${allFestivals.get(i).getURL()}</td>
</tr>
<% } %>
</table>
You concrete problem is caused because you're mixing discouraged and old school scriptlets <% %> with its successor EL ${}. They do not share the same variable scope. The allFestivals is not available in scriptlet scope and the i is not available in EL scope.
You should install JSTL (<-- click the link for instructions) and declare it in top of JSP as follows:
<%#taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
and then iterate over the list as follows:
<c:forEach items="${allFestivals}" var="festival">
<tr>
<td>${festival.festivalName}</td>
<td>${festival.location}</td>
<td>${festival.startDate}</td>
<td>${festival.endDate}</td>
<td>${festival.URL}</td>
</tr>
</c:forEach>
(beware of possible XSS attack holes, use <c:out> accordingly)
Don't forget to remove the <jsp:useBean> as it has no utter value here when you're using a servlet as model-and-view controller. It would only lead to confusion. See also our servlets wiki page. Further you would do yourself a favour to disable scriptlets by the following entry in web.xml so that you won't accidently use them:
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<scripting-invalid>true</scripting-invalid>
</jsp-property-group>
</jsp-config>
Do this
<% for(int i = 0; i < allFestivals.size(); i+=1) { %>
<tr>
<td><%=allFestivals.get(i).getFestivalName()%></td>
</tr>
<% } %>
Better way is to use c:foreach see link jstl for each
Related
I am working on a project to try and teach myself spring and struts. I am currently stuck on a JSP page. I have a pojo class with variables eid and ename with getters/setters, I also have a table in sql with the same values with six populated rows.I am accessing my database through a JdbcTemplate and have stored the result in a list, I then passed this list to my action page in which I set it as a request.setAttribute("empList",eList). In my jsp page I call that attribute and then try to iterate through it using JSTL. However nothing shows up, I know that my list variable has data in it since i checked it using the expression tag <%=eList%> and objects show up like this:
[org.classes.database.Employee#d9b02,
org.classes.database.Employee#13bce7e,
org.classes.database.Employee#171cc79,
org.classes.database.Employee#272a02,
org.classes.database.Employee#137105d,
org.classes.database.Employee#1359ad]
I thought that maybe I was missing something on jstl but I have jstl-1.2 in my META-INF/lib folder. I have also tried to add it in the configure path file and still nothing. I also have the correct tag url. Also when I do a simple <c:out value="Hello"/>. Hello does print out. So this leads me to believe that my jstl is working properly, but when I try iterating through my list using jstl nothing shows up at all.Anyways here is my JSP page:
<%# page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO- 8859-1"%>
<%#taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# page import="java.util.List"%>
<!DOCTYPE html>
<% List eList = (List)session.getAttribute("empList");%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Employee Details</title>
</head>
<body>
<c:out value="Hello"></c:out>
<h3>Employee Details</h3>
<hr size="4" color="gray"/>
<table>
<%=eList%>
<c:forEach items="${eList}" var="employee">
<tr>
<td>Employee ID: <c:out value="${employee.eid}"/></td>
<td>Employee Pass: <c:out value="${employee.ename}"/></td>
</tr>
</c:forEach>
</table>
</body>
</html>
Any help would be highly appreciated!
Before teaching yourself Spring and Struts, you should probably dive a little deeper into the Java language. Output like this
org.classes.database.Employee#d9b02
is the result of the Object#toString() method which all objects inherit from the Object class, the superclass of all classes in Java.
The List sub classes implement this by iterating over all the elements and calling toString() on those. It seems, however, that you haven't implemented (overriden) the method in your Employee class.
Your JSTL here
<c:forEach items="${eList}" var="employee">
<tr>
<td>Employee ID: <c:out value="${employee.eid}"/></td>
<td>Employee Pass: <c:out value="${employee.ename}"/></td>
</tr>
</c:forEach>
is fine except for the fact that you don't have a page, request, session, or application scoped attribute named eList.
You need to add it
<% List eList = (List)session.getAttribute("empList");
request.setAttribute("eList", eList);
%>
Or use the attribute empList in the forEach.
<c:forEach items="${empList}" var="employee">
<tr>
<td>Employee ID: <c:out value="${employee.eid}"/></td>
<td>Employee Pass: <c:out value="${employee.ename}"/></td>
</tr>
</c:forEach>
change the code to the following
<%! List eList = (ArrayList)session.getAttribute("empList");%>
....
<table>
<%
for(int i=0; i<eList.length;i++){%>
<tr>
<td><%= ((Employee)eList[i]).getEid() %></td>
<td><%= ((Employee)eList[i]).getEname() %></td>
</tr>
<%}%>
</table>
you can read empList directly in forEach tag.Try this
<table>
<c:forEach items="${sessionScope.empList}" var="employee">
<tr>
<td>Employee ID: <c:out value="${employee.eid}"/></td>
<td>Employee Pass: <c:out value="${employee.ename}"/></td>
</tr>
</c:forEach>
</table>
<c:forEach items="${sessionScope.empL}" var="emp">
<tr>
<td>Employee ID: <c:out value="${emp.eid}"/></td>
<td>Employee Pass: <c:out value="${emp.ename}"/></td>
</tr>
</c:forEach>
another example with just scriplets, when iterating through an ArrayList that contains Maps.
<%
java.util.List<java.util.Map<String,String>> employees=(java.util.List<java.util.Map<String, String>>)request.getAttribute("employees");
for (java.util.Map employee: employees) {
%>
<tr>
<td><input value="<%=employee.get("fullName") %>"/></td>
</tr>
...
<%}%>
In have this transfer from a servlet to the jsp. Since the AllPost is a list and I go through it with for, I do not know whether it's a short way close to what I give here.
Meanwhile I solved the issue inside the class, i.e. before the value coming to the servlet & jsp, as below.
So, at this point I do not know whether it makes sense to try further.
Thank you in advance!
<c:forEach items="${AllPost}" var ="p">
<tr>
<%! int len = Integer.valueOf(${p.detail.length()}); %>
<%
if(len<25){
${p.detail}.concat("....");
}
%>
<td>${p.detail.substring(0,25)}...</td>
The 2nd option code from routine class:
ResultSet rs = DB.getPreparedStatement(SQL).executeQuery();
while(rs.next()){
News n = new News(rs.getInt(1),...);
if(Integer.valueOf(rs.getString(1.length())<25){
String sz = n.getDetail().concat(".........................");
n.setDetail(sz);
}
<%! int len = Integer.valueOf(${p.detail.length()}); %>
Here you're mixing EL and scriptlets, it's not possible to use both. Not only that, you're using JSTL in your code as well, but still resorting to scriptlets? In almost all cases, if you're using JSTL & EL, you don't need to use any scriptlets. Scriptlets is an oldschool way of using JSPs.
Your code for the first option should look something like this (without scriptlets):
<c:forEach items="${AllPost}" var ="p">
<tr>
<c:if test="${fn:length(p.detail) lt 25}">
<td>${p.detail}...</td>
</c:if>
<c:if test="${fn:length(p.detail) gt 25}">
<td>${fn:substring(p.detail, 0, 25)}...</td>
</c:if>
</tr>
</c:forEach>
make sure to include this at the top of the page for jstl functions (if you haven't already)
<%# taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
I need to loop through the list, but foreach loop is not acceptable as I want to start from the second element.
<c:forEach var="item" items="${items}">
<c:out value="${item.name}"/>
</c:forEach>
I tried to use standard java code in "<% %>" but I cannot come up how to set it up right. My syntax is just wrong, I need something like this
<% for (int i = 1; i < ${items.size()}; i++) { %>
<c:out value="${item.name}"/>
<%} %>
But, obviously, the code above is not working.
You can use JSTL varStatus property. It might help you.
<c:forEach var="item" items="${items}" varStatus="loop">
<c:if test="${loop.index != 0}">
<c:out value="${item.name}"/>
</c:if>
</c:forEach>
I'm working on a legacy Tomcat server that is no longer supported by the software developer that provided it. web.xml doesn't tell me what version of JSP I'm working with, but all the .class files are Java 1.5.
I have a customer who is upset, because the system has html boxes that are auto-populated by Java, and it fills it straight the the (unordered) results of an XML database query. I'm trying to sneak a bit of code into the JSP for the Selector to sort the list of fields before they are populated, but it doesn't work and I don't understand why.
The (abridged) relevant code:
<%# page import="src.explorer.ObjectStateFactory"%>
<%# page language="java" %>
<%# taglib uri="/WEB-INF/c.tld" prefix="c" %>
<jsp:useBean id="ExplorerViewContext" scope="session" type="src.explorer.ExplorerViewContext"/>
...
<c:forEach var="nc" items="${ExplorerViewContext.networkControllers}">
<c:choose>
<c:when test="${nc.name == ExplorerViewContext.networkControllerSelection.name}">
<option value="<c:out value="${selectAction}${nc.objectKey}"/>" selected><c:out value="${nc.name}"/></option>
</c:when>
<c:otherwise>
<option value="<c:out value="${selectAction}${nc.objectKey}"/>"><c:out value="${nc.name}"/></option>
</c:otherwise>
</c:choose>
</c:forEach>
</select>
The relevant code with my additions:
<%# page import="src.explorer.ObjectStateFactory"%>
<%# page import="java.util.*"%>
<%# page language="java" %>
<%# taglib uri="/WEB-INF/c.tld" prefix="c" %>
<jsp:useBean id="ExplorerViewContext" scope="session" type="src.explorer.ExplorerViewContext"/>
...
<%
final Comparator<src.explorer.XmldbObjectState> NC_ORDER = new Comparator<src.explorer.XmldbObjectState>(){
public int compare(src.explorer.XmldbObjectState nc1, src.explorer.XmldbObjectState nc2){
return nc1.getName().compareTo(nc2.getName());
}
};
List myList = ExplorerViewContext.getNetworkControllers();
java.util.Collections.sort(myList,NC_ORDER);
%>
<c:forEach var="nc" items="${myList}">
<c:choose>
<c:when test="${nc.name == ExplorerViewContext.networkControllerSelection.name}">
<option value="<c:out value="${selectAction}${nc.objectKey}"/>" selected><c:out value="${nc.name}"/></option>
</c:when>
<c:otherwise>
<option value="<c:out value="${selectAction}${nc.objectKey}"/>"><c:out value="${nc.name}"/></option>
</c:otherwise>
</c:choose>
</c:forEach>
</select>
Basically, I'm trying to grab the list and sort it before it gets sent to the HTML. The problem is, myList always comes up empty, and I don't understand why. I'm guessing that ExplorerViewContext.networkControllers in the original code is calling the getNetwrokControllers() method on an instance of ExplorerViewContext, yes? Why can't I do the same thing in a scriptlet and reformat the output a little before serving it?
You should not add scriptlet code to code that is already using JSTL only. The better thing to do would be to edit the bean class src.explorer.ExplorerViewContext to sort the insides for you automatically.
In any case, the reason ${myList} does nothing in the JSTL is that variables created in scriptlets (i.e. between <% and %>) do not exist for JSTL. To get a variable to exist in JSTL you have to create it in JSTL, or set it in the page context, or it has to be in the session or the request. Generally you put it in the session or request in a servlet.
In this case, your list is in the bean, so it would be better to just edit the bean class to sort the list. But you could set the variable into the page context here so that JSTL can use it:
<%
...
List myList = ExplorerViewContext.getNetworkControllers();
java.util.Collections.sort(myList,NC_ORDER);
pageContext.setAttribute("myList", myList); //set in pageContext so JSTL can see it
%>
<c:forEach var="nc" items="${myList}">
As far as the code being "legacy" adding scriptlets to it would make it even more legacy. The fact is, this code is more modern than the modifications you were trying to add. But only slightly so, since using <jsp:useBean> is an obsolete way of using beans.
I was wondering if I could pass parameters through URL to a specific action.
what I would like to do, is something like this (written using jstl core):
<c:forEach items="${listaApprodi}" var="app">
<tr>
<td></c:out></td>
</tr>
</c:forEach>
Of course I won't use a servlet as "destination" but I'll use an action named OrariAction.class.
Is it possible with Struts2 taglib?
One of the possible solution is
<%# taglib uri="/struts-tags" prefix="s" %>
<c:forEach items="${listaApprodi}" var="app">
<tr>
<td>
<s:url action="your-ActionName" var="myurlvar" >
<s:param name="app">${app.name}</s:param>
<s:param name="lin">${requestScope.linea.name}</s:param>
</s:url>
<s:a href="%{myurlvar}">${app.name}</s:a>
</td>
</tr>
</c:forEach>
You can also use <s:iterator> instead of <c:foreach>