I am trying to loop through an Arraylist on my JSP without any luck.
I am able to loop through this successfully but only hit this error while trying to dynamically change the "
I have tried all different approaches by opening and closes the tags, trying different enclosure characters namely: single quotes and double quotes.
The error that I am getting is as follows:
javax.el.MethodNotFoundException: Method not found: class java.util.ArrayList.getChartName()
at javax.el.Util.findWrapper(Util.java:351)
at javax.el.Util.findMethod(Util.java:214)
at javax.el.BeanELResolver.invoke(BeanELResolver.java:174)
This what my JSP looks like:
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%#include file="header.jsp" %>
<div id="content_main">
<c:if test="${not empty dashboardDetail}"></c:if>
<c:forEach var="dashboardDetailList" items="${dashboardDetail}">
<div id="${dashboardDetail.getChartName()}" style="width: 100%; height: 400px;"> </div>
</c:forEach>
</div>
<%#include file="footer.jsp" %>
From the names you've used, you've got them the wrong way around.
<c:forEach var="dashboardDetailList" items="${dashboardDetail}">
items should be the list and var the current element. But you've referred to dashboardDetail correctly inside the loop. Switch the names (for every reference to the list):
<c:forEach var="dashboardDetail" items="${dashboardDetailList}">
The error occurs because as you have it now, you are calling getChartName() on an ArrayList, and that method doesn't exist.
Try this:
<c:forEach var="dashboardDetailObject" items="${dashboardDetail}">
<div id="${dashboardDetailObject.chartName}"
style="width: 100%; height: 400px;"></div>
</c:forEach>
dashboardDetailList changed to dashboardDetailObject
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>
...
<%}%>
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'm creating a JSP .tag file that will handle this use case:
<my:safeParam paramName="param1" defaultValue="testvalue"/>
Where the behavior will be to take a request parameter, escape its value for "safe" usage, and place that escaped value back on some scope (e.g. request) under the same name as the parameter (although it could be another name).
I have an implementation that works, but I've got scriptlet in there because I couldn't find a way to use variable variable names in just JSTL. But I'm no JSTL wizard, so I thought I'd see if there's a syntax/approach I'm missing. Here's the working safeParam.tag file:
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%# taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%# attribute name="paramName" required="true" %>
<%# attribute name="defaultValue" %>
<%
String name = (String) pageContext.getAttribute("paramName");
%>
<c:if test="${not empty defaultValue}">
<%
request.setAttribute(name, pageContext.getAttribute("defaultValue"));
%>
</c:if>
<c:if test="${not empty param[paramName]}">
<c:set var="escaped" value="${fn:escapeXml(param[paramName])}"/>
<%
request.setAttribute(name, pageContext.getAttribute("escaped"));
%>
</c:if>
(I sure wish EL was escaped automatically.)
<c:if test="${empty paramName}">
${defaultValue}
</c:if>
<c:if test="${not empty paramName}">
<c:out value="${paramName}" escapeXml="true"/>
</c:if>
I probably won't use this approach because it reduces the conciseness I was seeking with this custom tag, but just to document it as an option... (I'm not sure if this is what Frank Yeung is getting at.)
I could make the tag simply output the default-or-escaped parameter value, then make the user of the tag wrap that in a <c:set>.
Tag:
<c:choose>
<c:when test="${empty param[paramName]}">
${defaultValue}
</c:when>
<c:otherwise>
<c:out value="${param[paramName]}"/>
</c:otherwise>
</c:choose>
JSP:
<c:set var="myVariable">
<my:safeParam paramName="folder" defaultValue="homeFolder"/>
</c:set>
But really my goal has been to do everything inside the tag.
I want to display a div with all error messages in my page header. I know how to do for for a single command eg:
<spring:hasBindErrors name="<my_command>">
<div class="error_box">
<c:forEach var="error" items="${errors.allErrors}">
<spring:message message="${error}"></spring:message><br />
</c:forEach>
</div>
</spring:hasBindErrors>
but I would like to have global div for every command So I wouldn't need to repeat nearly same code. Any help appreciated :)
The only idea I have is:
<%
Enumeration en = request.getAttributeNames();
while(en.hasMoreElements()) {
String attr = (String)en.nextElement();
if(attr.startsWith("org.springframework.validation.BindingResult")) {
%>
<spring:hasBindErrors name='<%= attr.substring(attr.lastIndexOf(".")+1) %>' >
<div class="error_box">
<c:forEach var="error" items="${errors.allErrors}">
<spring:message message="${error}"></spring:message>
<br />
</c:forEach>
</div>
</spring:hasBindErrors>
<%
}
}
%>
Maybe one day I will get a better answer :)
I am having a problem with JSTL and empty operator. I already made few simple pages and everything worked fine, but now I have:
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%#taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<body>
<form action="/Projekt/myaccount" method="post">
<table border="1">
<tr>
<td>Artist</td>
<td>Record Name</td>
<td>Delete</td>
</tr>
<c:forEach var="item" items="${records}">
<tr>
<td>${item.artist}</td>
<td>${item.recordName}</td>
<td>
<input type="checkbox" name='${item.recordName}|${item.recordName}'/>
</td>
</tr>
</c:forEach>
</table>
<hr/>
<input type="submit" name="back" value="back"/>
<c:if test='${not empty "${records}"}'>
<input type="submit" name="delete" value="delete selected"/>
</c:if>
</form>
</body>
</html>
now no matter if I set the records attribute or not, the delete button shows up:
<c:if test='${not empty "${records}"}'>
<input type="submit" name="delete" value="delete selected"/>
</c:if>
in normal situation to records attribute I pass ArrayList and then use foreach, but sometimes ArrayList is empty, so in those situations I don't want delete button to show up, I fought that easiest way to achieve this would be to use this empty operator. Where am I making a mistake?
I even tried to manually set this attribute to null:
if (ar.size() != 0)
request.setAttribute("records", ar);
else
request.setAttribute("records",null);
EDIT:
#Qwe: yes you are right, it worked for me before because I tested if attribute was empty in my way, it was always true, because I used wrong construct, but it worked because I just wanted to show one string, if there was no String nothing showed up so I was thinking that everything worked fine.
<c:if test='${not empty "${records}"}'> as well as <c:if test="${!empty '${showWarning}'}"> (from your comment) will always resolve to true because you're are actually testing if a String ${records} is empty or not, and obviously it is not.
Just to be sure - by String ${records} I mean a String value, just as if you were assigning it in Java like String foo = "${records}";.
The next line of code will test if records variable (that is looked up from page, request, session or application scope) is empty or not:
<c:if test="${not empty records}">
The line of code is 100% guaranteed to work :)
Also, request.setAttribute("records",null) is a bad way to remove attributes because empty tests not just request scope, but page, session etc. Use <c:remove var='records'/> instead.