JSTL c:set not working as expected - java

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.

Related

variable from servlet editing inside JSP

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

Why doesn't String.equals() method work inside the JSTL Core tag <c:if>?

Purpose of code: To validate an input string from the user. If the user inputs his name, stored as 'n', as "James" then the message "Validated!" is displayed.
(A separate HTML form takes care of the input string)
Although there aren't any errors, the test inside the tag fails and the message is not displayed regardless of whether the input string is "James" or not.
<body>
<% String n = (String)request.getParameter("n");
String t = "James";
%>
Message <!-- Default message displayed to show that HTML body is read. -->
<c:if test="${t.equals(n)}">
<c:out value="Validated!"/>
</c:if>
</body>
If I were to replace the test condition with true inside the curly braces, the if condition passes and the message "Validated!" is displayed.
Why doesn't the equals() method work inside the JSTL tag?
You haven't saved your variables to the scope.
You've to do this otherwise EL won't see your variables.
Save the variables to request scope:
<c:set var="n" value="${param.n}" scope="request"/>
<c:set var="t" value="James" scope="request"/>
You need to use EL's eq operator instead of Java's .equals().
Change your code like this:
<c:if test="${t eq n}">
<c:out value="Validated!"/>
</c:if>
P.S. Your JSP file contains scriptlets that is bad practice and the approach is insecure.
Would be even better to separate the logics and the views as described here
You can use normal == comparison operator in this way:
<c:if test="${t == n}">
<c:out value="Validated!"/>
</c:if>
If you need to compare string values rather than object's attribute, you can do this:
<c:if test="${t == 'Any string can be here'}">
<c:out value="Validated!"/>
</c:if>

passing string array as hidden value from one jsp to another jsp

I am trying to pass String array from one jsp to another. I am using JSTL in my JSP.
In my first JSP i am doing like this
<c:if test="${fn:length(empBean.additionalEmailAddr) gt 0}">
<c:forEach begin="0" end="${fn:length(empBean.additionalEmailAddr) - 1}" var="ind" >
<input type="hidden" name="inbdAdditionalEmailAddr" value="${empBean.additionalEmailAddr[ind]}"/>
</c:forEach>
</c:if>
and trying to access the values in another jsp as follows
<%
String[] inbdAddEmlAddr = request.getParameter("inbdAdditionalEmailAddr");
%>
and i am planning to use JSTL to print the array values.
In the second jsp i am getting type mismatch error. Please help.
Is this the right approach ? Any help is appreciated
Thanks
request.getParameter() returns a String which the code attempts to assign to a String[], causing the exception.
Use request.getParameterValues('inbdAdditionalEmailAddr'); to retrieve parameters as an array.
See the documentation.

How to compare 2 variables with <c:if>

I am using jsp + spring mvc, and on jsp page I have some list - catList with idand name and also have some variable test. I am trying to compare cat.id and test, but can't because every time have runtime syntax errors:
<c:forEach var="cat" items="${catList}" varStatus="i">
<c:out value="${cat.id}"/>
<%-- comparison and some action--%>
</c:forEach>
tried:
<c:if test="${category.id == test}" >
<c:if test="${category.id eq test}" >
<c:if test="${category.id eq ${test}}">
Update: I resolved this problem, simply it was error with server redeploy
All JSTL tags (as well as XML and HTML tags) require an opening tag and a closing tag. The opening tag defines where the tag body starts (and also allows you to define attributes). The closing tag defines where the tag body ends.
In the following code sample, the closing tag is on the last line.
<c:if test="${category.id == test}" >
<b>Test passed!</b>
</c:if>
As you can see, it has the same name as the opening tag, and starts with a / (and has no attributes).
The first two opening tags that you included in your question should work.

conditional check in c:if always fails

The c:if test always fails for me and it never gets inside the loop. I am using the following namespaces
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:c="http://java.sun.com/jstl/core"
The string ('array') to be split is "Tom and Jerry are GAP1 friends"
<s:decorate template="/layout/display-text.xhtml">
<c:set var="array" value="#{_mybean.value}"/>
<c:set var="space" value="#{fn:split(array, ' ')}"/>
<c:set var="len" value="#{fn:length(space)}"/>
<h:outputText value="total length = #{len}"/><br/>
<c:forEach begin="0" end="5" var="index">
<h:outputText value="index = #{index}, value = #{space[index]}"/><br/>
<c:set var="val" value="#{space[index]}"/>
<c:if test="#{fn:startsWith(val, 'GAP')}">
<h:outputText value="Found keyword parameter GAP" /><br/>
</c:if>
</c:forEach>
</s:decorate>
The JSTL core URI is invalid. As per the JSTL TLD it should be (note the extra /jsp):
xmlns:c="http://java.sun.com/jsp/jstl/core"
That said, mixing JSF with JSTL is never been a good idea. It won't always give results as you'd expect because they doesn't run in sync as you would expect from the coding. It's more that JSP/JSTL runs from top to bottom first and then hands over the produced result to JSF to process further from top to bottom again. That would cause some specific constructs to fail. Better use pure JSF components/attributes instead.
Instead of c:forEach, rather use Seam's a4j:repeat or Facelets' ui:repeat and instead of c:if make use of the rendered attribute of the JSF component which has to be toggled to show/hide. Instead of all that JSTL c:set, write appropriate code logic in managed bean constructor or action method or getter.
The JSTL functions (fn) taglib is however still highly valuable in JSF. You can keep using it.

Categories