variable from servlet editing inside JSP - java

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" %>

Related

Sort select box items in a JSP scriptlet

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.

How to pass java variables from scriptlets to c:when expression in jstl?

what is a proper way to use variables from scriptlets in jstl?
I don't know what is wrong in my code:
<%
boolean a = true;
boolean b = false;
%>
<c:choose>
<c:when test="${a}">
<c:set var="x" value="It's true"/>
</c:when>
<c:when test="${b}">
<c:set var="x" value="It's false"/>
</c:when>
</c:choose>
It looks like it doesn't go into the whole block.
Variables in scriptlets cannot be seen in JSTL because Expression Language, the stuff between ${} used in JSTL, will look for attributes in page, request, session or application. You have to at least store the variable from scriptlet in one of these scopes, then use it.
This is an example:
<%
boolean a = true;
request.setAttribute("a", a);
%>
<c:if test="${a}">
<c:out value="a was found and it's true." />
</c:if>
More info:
Expression Language StackOverflow wiki
JSTL StackOverflow wiki
As a recommendation, stop using scriptlets. Move the business logic in your JSP to controller and the view logic into EL, JSTL and other tags like <display>. More info: How to avoid Java code in JSP files?
The default scope of JSP is page. if you want to use the variable of scriplet to JSTL use following code.
<%
boolean a = true;
boolean b = false;
pageContext.setAttribute("a", a);
pageContext.setAttribute("b", b);
%>
Then it will be usable in JSTL.

Using for loop inside of a JSP

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

JSTL c:set not working as expected

I have a JSTL loop where I'm trying to check to see if a given variable is empty or not with a dynamic variable name. When I use c:set with page scope, the variable is not accessible to the if statement. However, when I set it using <% pageCotnext.setAttribute(...); %>, the variable is available.
<%
pageContext.setAttribute("alphaParA", "test");
pageContext.setAttribute("alphaParF", "test");
int i = 0;
%>
<ul class="alphadex_links">
<c:forEach var="i" begin="0" end="25" step="1" varStatus="status">
<c:set var="currentLetter" scope="page">&#${i+65}</c:set>
<c:set var="currentPar" scope="page">alphaPar${currentLetter}</c:set>
<% pageContext.setAttribute("currentPar", "alphaPar" + (char)('A' + i++)); %>
<li>
<c:choose>
<c:when test="${not empty pageScope[currentPar]}">
The test is always fails when I remove the pageContext.setAttribute block, however it succeeds for A and F as it should when the block is in. I'm very confused and can't find help anywhere.
It fails because HTML doesn't run at the moment JSTL runs. You're effectively passing a Java String &#65 to it instead of the desired character A which would be represented as such based on the HTML entity A when the HTML is retrieved and parsed by the webbrowser after Java/JSP/JSTL has done its job. Please note that your HTML entity is missing the closing semicolon, but this isn't the cause of your concrete problem.
As to the concrete functional requirement, sorry, you're out of luck with EL. It doesn't support char. Your best bet is to deal with strings like this:
<c:forEach items="${fn:split('A,B,C,D,E,F,G,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z', ',')}" var="currentLetter">
<c:set var="currentPar" value="alphaPar${currentLetter}" />
${pageScope[currentPar]}
</c:forEach>
If necessary, just autogenerate the letters as String[] in Java end and set it as application attribute.

How to put data into HTML elements in JSP?

I am really new to JSP and I am trying to figure out how to show my data from an ArrayList in my HTML?
Could I do something like this:
<article>
<p><%= myArrayList.elementAt(0).toString() %></p>
</article>
Or do I use an out.printnln?
Any guidance is much appreciated. And the question really applies to more than just an ArrayList, it is more of that I have String data retrieved my java classes, and I need to display it in my HTML.
As always, thanks!
1 Yes it should work that way. Yet you only show the first element, you need to put that inside a loop to show everything
<% for(Object obj : myArrayList) { %>
<article>
<p><%= obj.toString() %></p>
</article>
<% } %>
2 out.println is the same than <%=. Better use the latter to show clearly the HTML code, out.println would be for complicated expressions (to avoid opening and closing <%= too often for readability.
<c:forEach items="${myArrayList}" var="product" varStatus="loop">
<td>
${product.id}
${product.name}
</td>
</c:forEach>
will call the getName(), and getId() methods and output them to html.

Categories