I would like to know why I am not able to get values from an outer hashtable using the keys in jstl, the keys are integer values, the values are inner hashtables and I am working on some legacy code hence the reason for the Hashtables, which are returned from a stored procedure call in this form.
Oddly in the inner hashtable as I process it in my forEach loop I am able to get those values out... ${data['NAME']} actually does work.
I am able to loop over the entire outer hashtable using JSTL forEach loop and its ok but if I try to get a value like ${missing_ciphers[1]} or even ${missing_ciphers['1']} then nothing is returned.
The hashtable when printed looks like this:
{4={SOURCE=D, NAME=D}, 3={SOURCE=C, NAME=C}, 2={SOURCE=B, NAME=B}, 1={SOURCE=A, NAME=A}}
I am able to loop over it ok using the following code but the list is not in the order I want it to be in so I wanted to use the loop counter to get objects out by their key but this doesnt seem to return anything (the inline styles will be moved into a css file once I have this working as I want...):
<c:forEach items="${missing_ciphers}" var="ciphers" varStatus="cipher_loop">
<c:set var="data" value="${ciphers.value}">
</c:set>
<tr style="border-left: none; border-right: none;" class="${cipher_loop.index % 2 == 0 ? 'even' : 'odd'}">
<td><span style="font-weight: bold;">${data['SOURCE']}</span></td>
<td><span style="font-weight: bold;">${data['NAME']}</span></td>
</tr>
</c:forEach>
Can anyone help me understand what is happening here and why I am not able to get a value out using the ${missing_ciphers[1]} type syntax?
I should add that the following code does print the inner hashtable into the tomcat console:
<% System.out.println("val: " + ((Hashtable)request.getAttribute("missing_ciphers")).get(1)); %>
I have even tried the following just to see if it was down to the type of the key this still doesnt get from the outer hashtable:
<c:forEach items="${missing_ciphers}" var="ciphers" varStatus="cipher_loop">
<c:set var="counter" value="${cipher_loop.index + 1}" />
<fmt:parseNumber var="fmt_counter" integerOnly="true" type="number" value="${counter}" />
<c:out value="${fmt_counter}" />
<c:set var="data" value="${missing_ciphers[fmt_counter]}"></c:set>
<tr style="border-left: none; border-right: none;" class="${cipher_loop.index % 2 == 0 ? 'even' : 'odd'}">
<td><span style="font-weight: bold;">${data['SOURCE']}</span></td>
<td><span style="font-weight: bold;">${data['NAME']}</span></td>
</tr>
</c:forEach>
Thanks
You should be using variable name assigned to varStatus - 'cipher_loop' and not varStatus itself.
Also you should use the index property or the count property to get the current index. (index starts at 0 and count at 1 by default)
${missing_ciphers[varStatus]}
should be
${missing_ciphers[cipher_loop.count]}
Edit
What is the type of your key in your outer hastable? Integer?
The type of varStatus.index (or counter) is long and you will have to explicitly set it as integer to use it as a key of your outer table
The following code works for me
<jsp:directive.page import="java.util.*"/>
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%
Hashtable h = new Hashtable();
Hashtable h1 = new Hashtable();h1.put("SOURCE","D");h1.put("NAME","D");
Hashtable h2 = new Hashtable();h2.put("SOURCE","C");h2.put("NAME","C");
Hashtable h3 = new Hashtable();h3.put("SOURCE","B");h3.put("NAME","B");
Hashtable h4 = new Hashtable();h4.put("SOURCE","A");h4.put("NAME","A");
h.put(4,h1);h.put(3,h2);h.put(2,h3);h.put(1,h1);
request.setAttribute("missing_ciphers",h);
%>
<c:forEach items="${missing_ciphers}" var="ciphers" varStatus="cipher_loop">
<c:set var="counter" value="${cipher_loop.index + 1}" />
<c:out value = "${counter}"/>
<c:set var = 'counter' value = '<%=new Integer(pageContext.findAttribute("counter").toString())%>'/>
<c:set var="data" value="${missing_ciphers[counter]}"></c:set>
<tr>
<td><span style="font-weight: bold;">${data['SOURCE']}</span></td>
<td><span style="font-weight: bold;">${data['NAME']}</span></td>
</tr>
</c:forEach>
OTOH, if the keys in your table is of type long, then you can use the varstatus.index property directly
<jsp:directive.page import="java.util.*"/>
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%
Hashtable h = new Hashtable();
Hashtable h1 = new Hashtable();h1.put("SOURCE","D");h1.put("NAME","D");
Hashtable h2 = new Hashtable();h2.put("SOURCE","C");h2.put("NAME","C");
Hashtable h3 = new Hashtable();h3.put("SOURCE","B");h3.put("NAME","B");
Hashtable h4 = new Hashtable();h4.put("SOURCE","A");h4.put("NAME","A");
h.put(new Long(4),h1);h.put(new Long(3),h2);h.put(new Long(2),h3);h.put(new Long(1),h1);
request.setAttribute("missing_ciphers",h);
%>
test
<<c:forEach items="${missing_ciphers}" var="ciphers" varStatus="cipher_loop">
<c:set var="counter" value="${cipher_loop.index + 1}" />
<c:set var="data" value="${missing_ciphers[counter]}"></c:set>
${data}
<tr>
<td><span style="font-weight: bold;">${data['SOURCE']}</span></td>
<td><span style="font-weight: bold;">${data['NAME']}</span></td>
</tr>
</c:forEach>
Related
This is my arraylist for index 17
In this code may have data list or may not. Data is dispay when there are records. Not handled for no records
Java code:
//To avoid arrayindexoutofbound exception length checked
if (resultList.length >17) {
statisticsDetails.setqNames(resultList[17]);
//System.out.println(resultList[17]);
String[] qName=resultList[17].split("\\^");
List<StatisticsDetails> statisticsDetailsList = new ArrayList<StatisticsDetails>();
for (String queueName:qName ){
StatisticsDetails details = new StatisticsDetails();
String[] splitQueues = queueName.split("=");
details.setqKey(splitQueues[0]);
details.setqCount(splitQueues[1]);
statisticsDetailsList.add(details);
}
statisticsDetails.setqNamesList(statisticsDetailsList);
}
Jsp code:
<logic:iterate id="iteratorId" name="statistics.statisticsDetails" property="qNamesList">
<tr>
<td class="col-sm-6 col-md-6 col-lg-6"><bean:write name="iteratorId" property="qKey" /></td>
<td class="col-sm-6 col-md-6 col-lg-6"><bean:write name="iteratorId" property="qCount" /></td>
</tr>
</logic:iterate>
how to avoid arraybound error and JSP to handle when no data found
Use a null check using JSTL(Do not forget to import the tag library):
import core library:
<%# taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
and then use:
<c:if test="${not empty statistics.statisticsDetails}">
//keep your code here to iterate the list
</c:if>
Or use:
<%# taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
and then:
<c:if test="${fn:length(statistics.statisticsDetails) > 0}">
//keep your code here to iterate the list
</c:if>
Please check all mapping is correct or not in the struts-config.xml. In my case, i found incorrect type was mentioned for form and then it was giving the error. Type means package name for the form. in tag.
I have a map like this,
Map<Integer,ArrayList<Object>> myMap = new LinkedHashMap<Integer,ArrayList<Object>>();
Now I have to iterate this Map and then the ArrayList inside the map. How can I do this using JSTL?
You can use JSTL <c:forEach> tag to iterate over arrays, collections and maps.
In case of arrays and collections, every iteration the var will give you just the currently iterated item right away.
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:forEach items="${collectionOrArray}" var="item">
Item = ${item}<br>
</c:forEach>
In case of maps, every iteration the var will give you a Map.Entry object which in turn has getKey() and getValue() methods.
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:forEach items="${map}" var="entry">
Key = ${entry.key}, value = ${entry.value}<br>
</c:forEach>
In your particular case, the ${entry.value} is actually a List, thus you need to iterate over it as well:
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:forEach items="${map}" var="entry">
Key = ${entry.key}, values =
<c:forEach items="${entry.value}" var="item" varStatus="loop">
${item} ${!loop.last ? ', ' : ''}
</c:forEach><br>
</c:forEach>
The varStatus is there just for convenience ;)
To understand better what's all going on here, here's a plain Java translation:
for (Entry<String, List<Object>> entry : map.entrySet()) {
out.print("Key = " + entry.getKey() + ", values = ");
for (Iterator<Object> iter = entry.getValue().iterator(); iter.hasNext();) {
Object item = iter.next();
out.print(item + (iter.hasNext() ? ", " : ""));
}
out.println();
}
See also:
How to loop through a HashMap in JSP?
Show JDBC ResultSet in HTML in JSP page using MVC and DAO pattern
How to loop over something a specified number of times in JSTL?
Did you try something like this?
<c:forEach var='item' items='${map}'>
<c:forEach var='arrayItem' items='${item.value}' />
...
</c:forEach>
</c:forEach>
you haven't closed c tag.try out this
<c:forEach items="${logMap}" var="entry">
Key = ${entry.key}, values =
<c:forEach items="${entry.value}" var="item" varStatus="loop">
${item} ${!loop.last ? ', ' : ''}
</c:forEach><br>
</c:forEach>
You can also loop round just the map.value its self if you know the key
<c:forEach var="value" items="${myMap[myObject.someInteger]}">
${value}
</c:forEach>
I define a class of Clue :
Class Clue{
...
String text;
..
getter/setter method
}
I want to get ${clue.text} from jsp to use in the scope "<%...%>" to just show subSequence(0, 10),like this:
<c:forEach items="${clues}" var = "clue">
<tr>
<td>${clue.weibo.user.name}</td>
<td>
<%
String str = ${clue.weibo.text};
%>
<%=str.subSequence(0, 10) %>
</td>
</tr>
</c:forEach>
How can I do?
To access A JSTL variable in a scriplet:
<%
String str = (String)pageContext.getAttribute("clue.weibo.text", PageContext.REQUEST_SCOPE);
%>
However, a better way is to use JSTL functions to manipulate the string.
<%# taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<c:forEach items="${clues}" var = "clue">
<tr>
<td>${clue.weibo.user.name}</td>
<td>
${fn:substring(clue.weibo.text, 0, 10)}
</td>
</tr>
</c:forEach>
I'm trying to use a table to display some images, I'm allowed 3 images per row but I'm not sure how to end the table row when I have a row with less then 3 images. See the snippet below for what I've been trying.
Using a ul I would not have to worry about it but I'm directed to use a table. How can I make sure the last row is properly terminated ? I'm newer to jstl.
Thanks,
<% int endTRFlag = 0; %>
<table width="100%">
<tr>
<core:forEach var="imageURL" items="${actionBean.imageURLs}" varStatus="rowCounter">
<td align="center" valign="middle">
<div class="item">
<img src="${imageURL}" alt="Photo 1" class="img" />
</div>
</td>
<% endTRFlag = 1; %>
<core:if test="${ (rowCounter.count % 3 == 0) }">
</tr>
<tr>
<% endTRFlag = 0; %>
</core:if>
<core:if test="${ (rowCounter.count % 3 != 0) && (endTRFlag == 0)}">
</tr>
</core:if>
</core:forEach>
In the code below, I use .index instead of .count because it is 0-based, and so will work better for modulus (0/3, 3/3, etc.). .last is true if the current element is the last element in the list. This solution does cause validation errors in Eclipse (at least Ganymede), which is annoying.
<c:forEach var="imageURL" items="${actionBean.imageURLs}" varStatus="rowCounter">
<c:if test="${rowCounter.index mod 3 eq 0}">
<tr>
</c:if>
<td>stuff</td>
<c:if test="${(rowCounter.index+1) mod 3 eq 0 or rowCounter.last}">
</tr>
</c:if>
</c:forEach>
Just put the </tr> after the loop.
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%# taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
<c:set var="imageCnt" value="${fn:length(actionBean.imageURLs)}"/>
<table width="100%">
<tr>
<c:forEach var="imageURL" items="${actionBean.imageURLs}"
varStatus="rowCounter">
<td align="center" valign="middle">
<span class="item">
<img src="${imageURL}" alt="Photo 1" class="img" />
</span>
</td>
</c:forEach>
<c:forEach begin="${imageCnt}" end="2">
<td/>
</c:forEach>
</tr>
</table>
I have an ArrayList and i am trying to display it in a table
.....
ArrayList rows = ....
.....
<table cellspacing="1" cellpadding="4" border="3">
<tr>
<TH>
Heading1
</TH>
<TH>
Heading2
</TH>
<TH>
Heading3
</TH>
<TH>
Heading4
</TH>
<TH>
Heading5
</TH>
<TH>
Heading6
</TH>
<TH>
Heading7
</TH>
</tr>
<tr>
<% for (int i = 0; i < rows.size(); i++) {
for (int j = 0; j < 7; j++) {
%>
<td>
<center>
<% out.println( ????? ); %>
</center>
</td>
<% } %>
</tr>
<% } %>
</table>
but i am having trouble displaying the correct data.
Well for one thing, I suspect that your outer loop should start above the <tr> tag.
Other than that, an ArrayList is a one-dimensional structure (not surprisingly, since it's a list). Trying to display this data in a table implies it's two dimensional, but without generics you've given no information as to what's contained within the list.
I'd approach this something like this:
/* header rows */
<% for (int i = 0; i < rows.size(); i++) {
Object rowObj = rows.get(i);
%>
<tr>
<% for (int j = 0; j < 7; j++) {
// This RHS made up due to not knowing the class of objects
// in your map, use something equivalent
Object cell = rowObj.getEntry(j);
%>
<td>
<center>
<%=cell.toString()%>
</center>
</td>
<% } %>
</tr>
<% } %>
You should not use scriptlets for this. Use JSTL/EL for this. Shortly back I've posted an example, you can find here: Places where JavaBeans are used?
It's a perfect scenario for using JSP taglibs. There is a huge list of available tablibs over at jsptags.com That way the HTML will be very readable but you'll have your dynamic table.
As others have pointed out you would want to use tags rather than generate a table yourself using scriptlets. The benefits are more than I care to list here. I would recommend looking at the Display tag library. It makes it trivially easy to generate a table from any Collection.
<display:table name="rows">
<display:column property="id" title="ID" />
<display:column property="name" />
<display:column property="email" />
<display:column property="status" />
<display:column property="description" title="Comments"/>
</display:table>
Of course each column would refer to a property of the objects that you have in your ArrayList.
You may use core JSTL library (download it from http://jakarta.apache.org/site/downloads/downloads_taglibs.html).
Include jstl.jar and standard.jar libraries from this distribution into you class path. Then place directive <%#taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> on top of your jsp-file. And use construction like this:
...
<br/>
<table><br/>
<c:forEach items="${rows}" var="row"><br/>
<tr><br/>
<c:forEach items="${row}" var="column"><br/>
<td><br/>
<c:out value="${column}"/><br/>
</td><br/>
</c:forEach><br/>
</tr><br/>
</c:forEach><br/>
</table><br/>
...